blob: 94664ad107757aaa6a5e9a457b91ed9f479202e6 [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 Halld80cc142015-07-06 13:36:05 -0700363 i = self.handle.expect( [ "mininet>", "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
You Wanga01d7f72019-02-27 11:23:39 -0800402 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -0800403 self.handle.sendline( "" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700404 self.handle.expect( "mininet>" )
405 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
You Wanga01d7f72019-02-27 11:23:39 -0800414 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -0800415 self.handle.sendline( "" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700416 self.handle.expect( "mininet>" )
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 Halla604fd42018-05-04 14:27:27 -0700490 self.handle.expect( "mininet>", 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
You Wanga01d7f72019-02-27 11:23:39 -0800507 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
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 Hall3c910162018-03-07 14:42:16 -0800510 self.handle.expect( "mininet>" )
511 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 Halla604fd42018-05-04 14:27:27 -0700553 self.handle.expect( "mininet>", 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
You Wanga01d7f72019-02-27 11:23:39 -0800575 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
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 Hall3c910162018-03-07 14:42:16 -0800578 self.handle.expect( "mininet>" )
579 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 Halla604fd42018-05-04 14:27:27 -0700633 self.handle.expect( "mininet>" )
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 Halla604fd42018-05-04 14:27:27 -0700636 self.handle.expect( "mininet>", 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
You Wanga01d7f72019-02-27 11:23:39 -0800642 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
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( "" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700645 self.handle.expect( "mininet>" )
646 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 Halla604fd42018-05-04 14:27:27 -0700683 self.handle.expect( "mininet>", 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
You Wanga01d7f72019-02-27 11:23:39 -0800706 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
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 Hall3c910162018-03-07 14:42:16 -0800709 self.handle.expect( "mininet>" )
710 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 ) )
741 i = self.handle.expect( [ "mininet>", 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 ) )
786 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
787 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",
876 prompt="mininet>",
877 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&",
907 prompt="mininet>",
908 timeout=10 )
909 response = self.execute(
910 cmd="h4 /usr/sbin/sshd -D&",
911 prompt="mininet>",
912 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 ",
917 prompt="mininet>",
918 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 )
940 self.handle.expect( "mininet>" )
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 )
969 self.handle.expect( "mininet>" )
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 )
1004 self.handle.expect( "mininet>" )
1005 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 )
1028 self.handle.expect( "mininet>" )
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 )
1057 self.handle.expect( "mininet>" )
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",
1081 prompt="mininet>",
1082 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,
1110 prompt="mininet>", 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",
1144 prompt="mininet>",
1145 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,
1184 prompt="mininet>",
1185 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( "" )
1207 self.expect( "mininet>" )
1208 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,
1212 prompt="mininet>",
1213 timeout=10 )
1214 self.handle.expect( "mininet>" )
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,
1239 prompt="mininet>",
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 )
1344 outcome = self.handle.expect( "mininet>", timeout )
1345 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
You Wanga01d7f72019-02-27 11:23:39 -08001378 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -08001379 self.handle.sendline( "" )
Jon Hall3b489db2015-10-05 14:38:37 -07001380 self.handle.expect( "mininet>" )
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 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001396 outcome1 = self.handle.expect( "mininet>" )
1397 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001398 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001399 outcome2 = self.handle.expect( "mininet>" )
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 ) )
You Wanga01d7f72019-02-27 11:23:39 -08001413 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -08001414 self.handle.sendline( "" )
Jon Hall439c8912016-04-15 02:22:03 -07001415 self.handle.expect( "mininet>" )
1416 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 )
1459 self.handle.expect( "mininet>" )
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 Hall7eb38402015-01-08 17:19:54 -08001555 self.handle.expect( "mininet>" )
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 )
1583 self.handle.expect( "mininet>" )
1584 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:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001606 response = self.execute( cmd = command, prompt = "mininet>" )
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,
1632 prompt="mininet>",
1633 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,
1654 prompt="mininet>",
1655 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,
1676 prompt="mininet>",
1677 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,
1714 prompt="mininet>",
1715 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:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001850 self.execute( cmd=cmd, prompt="mininet>", 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,
1877 prompt="mininet>",
1878 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,
1906 prompt="mininet>",
1907 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,
1939 prompt="mininet>",
1940 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,
2044 prompt="mininet>",
2045 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,
2079 prompt="mininet>",
2080 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,
2191 prompt="mininet>",
2192 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,
2228 prompt="mininet>",
2229 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( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002294 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002295 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002296 pexpect.EOF,
2297 pexpect.TIMEOUT ],
2298 timeout )
2299 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002300 main.log.info( "Exiting mininet.." )
2301 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002302 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002303 prompt=self.prompt,
2304 timeout=exitTimeout )
2305 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jon Halldac3eae2020-06-05 12:04:06 -07002306 cmd = "mn -c"
2307 if self.sudoRequired:
2308 cmd = "sudo " + cmd
2309 self.handle.sendline( cmd )
Jeremyd9e4eb12016-04-13 12:09:06 -07002310 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002311
Jeremyd9e4eb12016-04-13 12:09:06 -07002312 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002313 main.log.info( " Mininet trying to exit while not " +
2314 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002315 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002316 elif i == 2:
2317 main.log.error( "Something went wrong exiting mininet" )
2318 elif i == 3: # timeout
2319 main.log.error( "Something went wrong exiting mininet " +
2320 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002321
You Wang18db8592018-04-02 13:52:03 -07002322 self.handle.sendline( "" )
2323 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002324 cmd = "killall -9 dhclient dhcpd zebra bgpd"
2325 if self.sudoRequired:
2326 cmd = "sudo " + cmd
2327 self.handle.sendline( cmd )
2328 self.handle.expect( self.prompt )
You Wang18db8592018-04-02 13:52:03 -07002329
Hari Krishnab35c6d02015-03-18 11:13:51 -07002330 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002331 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002332 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002333 cmd = "kill -9 \`ps -ef | grep \"" + fileName + "\" | grep -v grep | awk '{print $2}'\`"
2334 if self.sudoRequired:
2335 cmd = "sudo " + cmd
2336 self.handle.sendline( cmd )
2337 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002338 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002339 main.log.error( self.name + ": TIMEOUT exception found" )
2340 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002341 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002342 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002343 main.log.error( self.name + ": EOF exception found" )
2344 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002345 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002346 except Exception:
2347 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002348 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002349 else:
2350 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002351 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002352 return response
2353
YPZhang26a139e2016-04-25 14:01:55 -07002354 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002355 """
2356 Description:
2357 Sends arp message from mininet host for hosts discovery
2358 Required:
2359 host - hosts name
2360 Optional:
2361 ip - ip address that does not exist in the network so there would
2362 be no reply.
2363 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002364 if ethDevice:
2365 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002366 cmd = srcHost + " arping -c1 "
2367 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002368 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 -07002369 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002370 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002371 if output:
2372 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002373 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002374 i = self.handle.expect( [ "mininet>", "arping: " ] )
2375 if i == 0:
2376 return main.TRUE
2377 elif i == 1:
2378 response = self.handle.before + self.handle.after
2379 self.handle.expect( "mininet>" )
2380 response += self.handle.before + self.handle.after
2381 main.log.warn( "Error sending arping, output was: " +
2382 response )
2383 return main.FALSE
2384 except pexpect.TIMEOUT:
2385 main.log.error( self.name + ": TIMEOUT exception found" )
2386 main.log.warn( self.handle.before )
2387 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002388 except pexpect.EOF:
2389 main.log.error( self.name + ": EOF exception found" )
2390 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002391 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002392 except Exception:
2393 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002394 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002395
Jon Hall7eb38402015-01-08 17:19:54 -08002396 def decToHex( self, num ):
2397 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002398
Jon Hall7eb38402015-01-08 17:19:54 -08002399 def getSwitchFlowCount( self, switch ):
2400 """
2401 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002402 if self.handle:
2403 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2404 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002405 response = self.execute(
2406 cmd=cmd,
2407 prompt="mininet>",
2408 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002409 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002410 main.log.error( self.name + ": EOF exception found" )
2411 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002412 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002413 except Exception:
2414 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002415 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002416 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002417 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002418 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002419 main.log.info(
2420 "Couldn't find flows on switch %s, found: %s" %
2421 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002422 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002423 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002424 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002425 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002426
Jon Hall9ed8f372016-02-24 17:34:07 -08002427 def checkFlows( self, sw, dumpFormat=None ):
2428 if dumpFormat:
2429 command = "sh ovs-ofctl -F " + \
2430 dumpFormat + " dump-flows " + str( sw )
2431 else:
2432 command = "sh ovs-ofctl dump-flows " + str( sw )
2433 try:
2434 response = self.execute(
2435 cmd=command,
2436 prompt="mininet>",
2437 timeout=10 )
2438 return response
2439 except pexpect.EOF:
2440 main.log.error( self.name + ": EOF exception found" )
2441 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002442 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002443 except Exception:
2444 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002445 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002446
GlennRC68467eb2015-11-16 18:01:01 -08002447 def flowTableComp( self, flowTable1, flowTable2 ):
2448 # This function compares the selctors and treatments of each flow
2449 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002450 assert flowTable1, "flowTable1 is empty or None"
2451 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002452 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002453 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002454 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002455 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002456 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2457 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002458 for field in dFields:
2459 try:
2460 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002461 except KeyError:
2462 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002463 try:
2464 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002465 except KeyError:
2466 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002467 for i in range( len( flowTable1 ) ):
2468 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002469 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002470 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002471 returnValue = main.FALSE
2472 break
2473 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002474 except AssertionError:
2475 main.log.exception( "Nothing to compare" )
2476 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002477 except Exception:
2478 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002479 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002480
GlennRC528ad292015-11-12 10:38:18 -08002481 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002482 '''
GlennRC956ea742015-11-05 16:14:15 -08002483 Discription: Parses flows into json format.
2484 NOTE: this can parse any string thats separated with commas
2485 Arguments:
2486 Required:
2487 flows: a list of strings that represnt flows
2488 Optional:
2489 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2490 debug: prints out the final result
2491 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002492 '''
GlennRC528ad292015-11-12 10:38:18 -08002493 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002494 try:
2495 for flow in flowTable:
2496 jsonFlow = {}
2497 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002498 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002499 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002500 for i in range( len( parsedFlow ) ):
2501 item = parsedFlow[ i ]
2502 if item[ 0 ] == " ":
2503 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002504 # grab the selector and treatment from the parsed flow
2505 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002506 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002507 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002508 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002509 index = 0
2510 # parse the flags
2511 # NOTE: This only parses one flag
2512 flag = {}
2513 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002514 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002515 index += 1
2516 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002517 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002518 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002520 # the priority is stuck in the selecter so put it back
2521 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002522 if 'priority' in sel[0]:
2523 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002524 # parse selector
2525 criteria = []
2526 for item in sel:
2527 # this is the type of the packet e.g. "arp"
2528 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002529 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002530 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002531 field = item.split( "=" )
2532 criteria.append( { field[ 0 ]: field[ 1 ] } )
2533 selector = { "selector": { "criteria": sorted( criteria ) } }
2534 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002535 # get rid of the action part e.g. "action=output:2"
2536 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002537 treat = treat.split( "=" )
2538 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002539 # parse treatment
2540 action = []
2541 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002542 if ":" in item:
2543 field = item.split( ":" )
2544 action.append( { field[ 0 ]: field[ 1 ] } )
2545 else:
2546 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2547 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002548 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002549 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002550 # parse the rest of the flow
2551 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002552 field = item.split( "=" )
2553 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002554 # add the treatment and the selector to the json flow
2555 jsonFlow.update( selector )
2556 jsonFlow.update( treatment )
2557 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002558
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002559 if debug:
2560 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002561
You Wang91c37cf2016-05-23 09:39:42 -07002562 # add the json flow to the json flow table
2563 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002564
You Wang91c37cf2016-05-23 09:39:42 -07002565 return jsonFlowTable
2566
2567 except IndexError:
2568 main.log.exception( self.name + ": IndexError found" )
2569 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002570 except pexpect.EOF:
2571 main.log.error( self.name + ": EOF exception found" )
2572 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002573 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002574 except Exception:
2575 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002576 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002577
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002578 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002579 '''
2580 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002581 Each element is a flow.
2582 Arguments:
2583 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002584 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002585 a list of switches.
2586 Optional:
2587 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2588 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002589 '''
GlennRC956ea742015-11-05 16:14:15 -08002590 try:
2591 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002592 if isinstance( sw, list ):
2593 switches.extend( sw )
2594 else:
2595 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002596
2597 flows = []
2598 for s in switches:
2599 cmd = "sh ovs-ofctl dump-flows " + s
2600
GlennRC528ad292015-11-12 10:38:18 -08002601 if "1.0" == version:
2602 cmd += " -F OpenFlow10-table_id"
2603 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002604 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002605
2606 main.log.info( "Sending: " + cmd )
2607 self.handle.sendline( cmd )
2608 self.handle.expect( "mininet>" )
2609 response = self.handle.before
2610 response = response.split( "\r\n" )
2611 # dump the first two elements and the last
2612 # the first element is the command that was sent
2613 # the second is the table header
2614 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002615 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002616 flows.extend( response )
2617
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002618 if debug:
2619 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002620
GlennRC528ad292015-11-12 10:38:18 -08002621 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002622
GlennRC956ea742015-11-05 16:14:15 -08002623 except pexpect.EOF:
2624 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002625 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002626 except Exception:
2627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002628 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002629
2630 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002631 '''
GlennRC956ea742015-11-05 16:14:15 -08002632 Discription: Checks whether the ID provided matches a flow ID in Mininet
2633 Arguments:
2634 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002635 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002636 a list of switches.
2637 flowId: the flow ID in hex format. Can also be a list of IDs
2638 Optional:
2639 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2640 debug: prints out the final result
2641 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2642 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002643 '''
GlennRC956ea742015-11-05 16:14:15 -08002644 try:
2645 main.log.info( "Getting flows from Mininet" )
2646 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002647 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002648 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002649
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002650 if debug:
2651 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002652
2653 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002654 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002655 result = False
2656 for f in flows:
2657 if flowId in f.get( 'cookie' ):
2658 result = True
2659 break
2660 # flowId is a list
2661 else:
2662 result = True
2663 # Get flow IDs from Mininet
2664 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2665 # Save the IDs that are not in Mininet
2666 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2667
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002668 if debug:
2669 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002670
2671 # Print out the IDs that are not in Mininet
2672 if absentIds:
2673 main.log.warn( "Absent ids: {}".format( absentIds ) )
2674 result = False
2675
2676 return main.TRUE if result else main.FALSE
2677
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002678 except pexpect.EOF:
2679 main.log.error( self.name + ": EOF exception found" )
2680 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002681 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002682 except Exception:
2683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002684 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002685
Charles Chan029be652015-08-24 01:46:10 +08002686 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002687 """
Jon Hallefbd9792015-03-05 16:11:36 -08002688 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002689 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002690 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002691 self.handle.sendline( "" )
2692 self.handle.expect( "mininet>" )
Jon Halldac3eae2020-06-05 12:04:06 -07002693 if self.sudoRequired:
2694 sudoStr = "sudo "
2695 else:
2696 sudoStr = ""
Jon Hall7eb38402015-01-08 17:19:54 -08002697 self.handle.sendline(
Jon Halldac3eae2020-06-05 12:04:06 -07002698 "sh " + sudoStr + "tcpdump -n -i " +
2699 intf + " " + port + " -w " +
2700 filename.strip() + " &" )
Jon Hall7eb38402015-01-08 17:19:54 -08002701 self.handle.sendline( "" )
2702 i = self.handle.expect( [ 'No\ssuch\device',
2703 'listening\son',
2704 pexpect.TIMEOUT,
2705 "mininet>" ],
2706 timeout=10 )
2707 main.log.warn( self.handle.before + self.handle.after )
2708 self.handle.sendline( "" )
2709 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002710 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002711 main.log.error(
2712 self.name +
2713 ": tcpdump - No such device exists. " +
2714 "tcpdump attempted on: " +
2715 intf )
admin2a9548d2014-06-17 14:08:07 -07002716 return main.FALSE
2717 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002718 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002719 return main.TRUE
2720 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002721 main.log.error(
2722 self.name +
2723 ": tcpdump command timed out! Check interface name," +
2724 " given interface was: " +
2725 intf )
admin2a9548d2014-06-17 14:08:07 -07002726 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002727 elif i == 3:
2728 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002729 return main.TRUE
2730 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002731 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002732 return main.FALSE
2733 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002734 main.log.error( self.name + ": EOF exception found" )
2735 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002736 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002737 except Exception:
2738 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002739 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002740
kelvin-onlabd3b64892015-01-20 13:26:24 -08002741 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002742 """
2743 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002744 try:
Jon Halldac3eae2020-06-05 12:04:06 -07002745 if self.sudoRequired:
2746 sudoStr = "sudo "
2747 else:
2748 sudoStr = ""
2749 self.handle.sendline( "sh " + sudoStr + " pkill tcpdump" )
Jon Hall7eb38402015-01-08 17:19:54 -08002750 self.handle.expect( "mininet>" )
2751 self.handle.sendline( "" )
2752 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002753 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002754 main.log.error( self.name + ": TIMEOUT exception found" )
2755 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002756 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002757 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002758 main.log.error( self.name + ": EOF exception found" )
2759 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002760 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002761 except Exception:
2762 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002763 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002764
Jon Halld80cc142015-07-06 13:36:05 -07002765 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002766 """
2767 Read ports from a Mininet switch.
2768
2769 Returns a json structure containing information about the
2770 ports of the given switch.
2771 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002772 try:
2773 response = self.getInterfaces( nodeName )
2774 # TODO: Sanity check on response. log if no such switch exists
2775 ports = []
2776 for line in response.split( "\n" ):
2777 if not line.startswith( "name=" ):
2778 continue
2779 portVars = {}
2780 for var in line.split( "," ):
2781 key, value = var.split( "=" )
2782 portVars[ key ] = value
2783 isUp = portVars.pop( 'enabled', "True" )
2784 isUp = "True" in isUp
2785 if verbose:
2786 main.log.info( "Reading switch port %s(%s)" %
2787 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2788 mac = portVars[ 'mac' ]
2789 if mac == 'None':
2790 mac = None
2791 ips = []
2792 ip = portVars[ 'ip' ]
2793 if ip == 'None':
2794 ip = None
2795 ips.append( ip )
2796 name = portVars[ 'name' ]
2797 if name == 'None':
2798 name = None
2799 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2800 if name == 'lo':
2801 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2802 else:
2803 portNo = re.search( portRe, name ).group( 'port' )
2804 ports.append( { 'of_port': portNo,
2805 'mac': str( mac ).replace( '\'', '' ),
2806 'name': name,
2807 'ips': ips,
2808 'enabled': isUp } )
2809 return ports
2810 except pexpect.EOF:
2811 main.log.error( self.name + ": EOF exception found" )
2812 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002813 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002814 except Exception:
2815 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002816 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002817
You Wangdb8cd0a2016-05-26 15:19:45 -07002818 def getOVSPorts( self, nodeName ):
2819 """
2820 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2821
2822 Returns a list of dictionaries containing information about each
2823 port of the given switch.
2824 """
2825 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2826 try:
2827 response = self.execute(
2828 cmd=command,
2829 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002830 timeout=10,
2831 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002832 ports = []
2833 if response:
2834 for line in response.split( "\n" ):
2835 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2836 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002837 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002838 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2839 result = re.search( pattern, line )
2840 if result:
2841 index = result.group( 'index' )
2842 name = result.group( 'name' )
2843 # This port number is extracted from port name
2844 port = result.group( 'port' )
2845 mac = result.group( 'mac' )
2846 ports.append( { 'index': index,
2847 'name': name,
2848 'port': port,
2849 'mac': mac } )
2850 return ports
2851 except pexpect.EOF:
2852 main.log.error( self.name + ": EOF exception found" )
2853 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002854 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002855 except Exception:
2856 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002857 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002858
Jon Halldac3eae2020-06-05 12:04:06 -07002859 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[], switchRegex=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002860 """
2861 Read switches from Mininet.
2862
2863 Returns a dictionary whose keys are the switch names and the value is
2864 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002865 If excludeNodes is specified, switches with names included in excludeNodes
2866 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002867 """
Jon Halla22481b2015-07-28 17:46:01 -07002868 # NOTE: To support new Mininet switch classes, just append the new
2869 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002870
Jon Halla22481b2015-07-28 17:46:01 -07002871 # Regex patterns to parse 'dump' output
2872 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002873 # <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 -07002874 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002875 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2876 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2877 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Jon Halldac3eae2020-06-05 12:04:06 -07002878 if not switchRegex:
2879 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2880 else:
2881 switchClasses = switchRegex
You Wang7d14d642019-01-23 15:10:08 -08002882 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002883 swRE = r"<(?P<class>" + switchClasses + r")" +\
2884 r"(?P<options>\{.*\})?\s" +\
2885 r"(?P<name>[^:]+)\:\s" +\
2886 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2887 r"\spid=(?P<pid>(\d)+)"
2888 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002889 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002890 output = {}
2891 dump = self.dump().split( "\n" )
2892 for line in dump:
2893 result = re.search( swRE, line, re.I )
2894 if result:
2895 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002896 if name in excludeNodes:
2897 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002898 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2899 pid = result.group( 'pid' )
2900 swClass = result.group( 'class' )
2901 options = result.group( 'options' )
2902 if verbose:
2903 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2904 ports = self.getPorts( name )
2905 output[ name ] = { "dpid": dpid,
2906 "ports": ports,
2907 "swClass": swClass,
2908 "pid": pid,
2909 "options": options }
2910 return output
2911 except pexpect.EOF:
2912 main.log.error( self.name + ": EOF exception found" )
2913 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002914 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002915 except Exception:
2916 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002917 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002918
You Wangd66de192018-04-30 17:30:12 -07002919 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002920 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2921 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002922 """
2923 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002924 Optional:
2925 hostClass: it is used to match the class of the mininet host. It
2926 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002927 Returns a dictionary whose keys are the host names and the value is
2928 a dictionary containing information about the host.
2929 """
2930 # Regex patterns to parse dump output
2931 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002932 # <Host h1: pid=12725>
2933 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2934 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2935 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002936 # NOTE: Does not correctly match hosts with multi-links
2937 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2938 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002939 try:
You Wang53dba1e2018-02-02 17:45:44 -08002940 if not isinstance( hostClass, types.ListType ):
2941 hostClass = [ str( hostClass ) ]
2942 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002943 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2944 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2945 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002946 if update:
2947 # update mn port info
2948 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002949 # Get mininet dump
2950 dump = self.dump().split( "\n" )
2951 hosts = {}
2952 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002953 result = re.search( hostRE, line )
2954 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002955 name = result.group( 'name' )
2956 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002957 if getInterfaces:
2958 response = self.getInterfaces( name )
2959 # Populate interface info
2960 for line in response.split( "\n" ):
2961 if line.startswith( "name=" ):
2962 portVars = {}
2963 for var in line.split( "," ):
2964 key, value = var.split( "=" )
2965 portVars[ key ] = value
2966 isUp = portVars.pop( 'enabled', "True" )
2967 isUp = "True" in isUp
2968 if verbose:
2969 main.log.info( "Reading host port %s(%s)" %
2970 ( portVars[ 'name' ],
2971 portVars[ 'mac' ] ) )
2972 mac = portVars[ 'mac' ]
2973 if mac == 'None':
2974 mac = None
2975 ips = []
2976 ip = portVars[ 'ip' ]
2977 if ip == 'None':
2978 ip = None
2979 ips.append( ip )
2980 intfName = portVars[ 'name' ]
2981 if name == 'None':
2982 name = None
2983 interfaces.append( {
2984 "name": intfName,
2985 "ips": ips,
2986 "mac": str( mac ),
2987 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002988 hosts[ name ] = { "interfaces": interfaces }
2989 return hosts
2990 except pexpect.EOF:
2991 main.log.error( self.name + ": EOF exception found" )
2992 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002993 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002994 except Exception:
2995 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002996 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002997
You Wang7d14d642019-01-23 15:10:08 -08002998 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002999 """
3000 Gathers information about current Mininet links. These links may not
3001 be up if one of the ports is down.
3002
3003 Returns a list of dictionaries with link endpoints.
3004
3005 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003006 { 'node1': str( node1 name )
3007 'node2': str( node2 name )
3008 'port1': str( port1 of_port )
3009 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08003010
You Wangb1665b52019-02-01 15:49:48 -08003011 If either node1 or node2 name matches any of the names sepcified in
3012 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08003013
Jon Hallafa8a472015-06-12 14:02:42 -07003014 Note: The port number returned is the eth#, not necessarily the of_port
3015 number. In Mininet, for OVS switch, these should be the same. For
3016 hosts, this is just the eth#.
3017 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003018 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003019 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003020 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003021
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003022 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003023 # s1-eth3<->s2-eth1 (OK OK)
3024 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08003025 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
3026 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003027 links = []
3028 for line in response:
3029 match = re.search( linkRE, line )
3030 if match:
3031 node1 = match.group( 'node1' )
3032 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08003033 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08003034 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003035 port1 = match.group( 'port1' )
3036 port2 = match.group( 'port2' )
3037 links.append( { 'node1': node1,
3038 'node2': node2,
3039 'port1': port1,
3040 'port2': port2 } )
3041 return links
3042
3043 except pexpect.EOF:
3044 main.log.error( self.name + ": EOF exception found" )
3045 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003046 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003047 except Exception:
3048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003049 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003050
3051 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003052 """
3053 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003054 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003055
Jon Hallafa8a472015-06-12 14:02:42 -07003056 Dependencies:
3057 1. numpy - "sudo pip install numpy"
3058 """
3059 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003060 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003061 try:
3062 mnDPIDs = []
3063 for swName, switch in switches.iteritems():
3064 mnDPIDs.append( switch[ 'dpid' ].lower() )
3065 mnDPIDs.sort()
3066 if switchesJson == "": # if rest call fails
3067 main.log.error(
3068 self.name +
3069 ".compareSwitches(): Empty JSON object given from ONOS" )
3070 return main.FALSE
3071 onos = switchesJson
3072 onosDPIDs = []
3073 for switch in onos:
3074 if switch[ 'available' ]:
3075 onosDPIDs.append(
3076 switch[ 'id' ].replace(
3077 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003078 '' ).replace(
3079 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003080 '' ).lower() )
3081 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003082
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003083 if mnDPIDs != onosDPIDs:
3084 switchResults = main.FALSE
3085 main.log.error( "Switches in MN but not in ONOS:" )
3086 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3087 main.log.error( str( list1 ) )
3088 main.log.error( "Switches in ONOS but not in MN:" )
3089 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3090 main.log.error( str( list2 ) )
3091 else: # list of dpid's match in onos and mn
3092 switchResults = main.TRUE
3093 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003094
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003095 # FIXME: this does not look for extra ports in ONOS, only checks that
3096 # ONOS has what is in MN
3097 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003098
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003099 # PORTS
3100 for name, mnSwitch in switches.iteritems():
3101 mnPorts = []
3102 onosPorts = []
3103 switchResult = main.TRUE
3104 for port in mnSwitch[ 'ports' ]:
3105 if port[ 'enabled' ]:
3106 mnPorts.append( int( port[ 'of_port' ] ) )
3107 for onosSwitch in portsJson:
3108 if onosSwitch[ 'device' ][ 'available' ]:
3109 if onosSwitch[ 'device' ][ 'id' ].replace(
3110 ':',
3111 '' ).replace(
3112 "of",
3113 '' ) == mnSwitch[ 'dpid' ]:
3114 for port in onosSwitch[ 'ports' ]:
3115 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003116 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003117 # onosPorts.append( 'local' )
3118 onosPorts.append( long( uint64( -2 ) ) )
3119 else:
3120 onosPorts.append( int( port[ 'port' ] ) )
3121 break
3122 mnPorts.sort( key=float )
3123 onosPorts.sort( key=float )
3124
3125 mnPortsLog = mnPorts
3126 onosPortsLog = onosPorts
3127 mnPorts = [ x for x in mnPorts ]
3128 onosPorts = [ x for x in onosPorts ]
3129
3130 # TODO: handle other reserved port numbers besides LOCAL
3131 # NOTE: Reserved ports
3132 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3133 # long( uint64( -2 ) )
3134 for mnPort in mnPortsLog:
3135 if mnPort in onosPorts:
3136 # don't set results to true here as this is just one of
3137 # many checks and it might override a failure
3138 mnPorts.remove( mnPort )
3139 onosPorts.remove( mnPort )
3140
3141 # NOTE: OVS reports this as down since there is no link
3142 # So ignoring these for now
3143 # TODO: Come up with a better way of handling these
3144 if 65534 in mnPorts:
3145 mnPorts.remove( 65534 )
3146 if long( uint64( -2 ) ) in onosPorts:
3147 onosPorts.remove( long( uint64( -2 ) ) )
3148 if len( mnPorts ): # the ports of this switch don't match
3149 switchResult = main.FALSE
3150 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3151 if len( onosPorts ): # the ports of this switch don't match
3152 switchResult = main.FALSE
3153 main.log.warn(
3154 "Ports in ONOS but not MN: " +
3155 str( onosPorts ) )
3156 if switchResult == main.FALSE:
3157 main.log.error(
3158 "The list of ports for switch %s(%s) does not match:" %
3159 ( name, mnSwitch[ 'dpid' ] ) )
3160 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3161 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3162 portsResults = portsResults and switchResult
3163 finalResults = finalResults and portsResults
3164 return finalResults
3165 except pexpect.EOF:
3166 main.log.error( self.name + ": EOF exception found" )
3167 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003168 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003169 except Exception:
3170 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003171 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003172
Jon Hallafa8a472015-06-12 14:02:42 -07003173 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003174 """
3175 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003176 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003177
Jon Hallafa8a472015-06-12 14:02:42 -07003178 """
Jon Hall7eb38402015-01-08 17:19:54 -08003179 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003180 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003181 try:
3182 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003183
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003184 mnLinks = []
3185 for l in links:
3186 try:
3187 node1 = switches[ l[ 'node1' ] ]
3188 node2 = switches[ l[ 'node2' ] ]
3189 enabled = True
3190 for port in node1[ 'ports' ]:
3191 if port[ 'of_port' ] == l[ 'port1' ]:
3192 enabled = enabled and port[ 'enabled' ]
3193 for port in node2[ 'ports' ]:
3194 if port[ 'of_port' ] == l[ 'port2' ]:
3195 enabled = enabled and port[ 'enabled' ]
3196 if enabled:
3197 mnLinks.append( l )
3198 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003199 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003200 if 2 * len( mnLinks ) == len( onos ):
3201 linkResults = main.TRUE
3202 else:
3203 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003204 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003205 "Mininet has " + str( len( mnLinks ) ) +
3206 " bidirectional links and ONOS has " +
3207 str( len( onos ) ) + " unidirectional links" )
3208
3209 # iterate through MN links and check if an ONOS link exists in
3210 # both directions
3211 for link in mnLinks:
3212 # TODO: Find a more efficient search method
3213 node1 = None
3214 port1 = None
3215 node2 = None
3216 port2 = None
3217 firstDir = main.FALSE
3218 secondDir = main.FALSE
3219 for swName, switch in switches.iteritems():
3220 if swName == link[ 'node1' ]:
3221 node1 = switch[ 'dpid' ]
3222 for port in switch[ 'ports' ]:
3223 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3224 port1 = port[ 'of_port' ]
3225 if node1 is not None and node2 is not None:
3226 break
3227 if swName == link[ 'node2' ]:
3228 node2 = switch[ 'dpid' ]
3229 for port in switch[ 'ports' ]:
3230 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3231 port2 = port[ 'of_port' ]
3232 if node1 is not None and node2 is not None:
3233 break
3234
3235 for onosLink in onos:
3236 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3237 ":", '' ).replace( "of", '' )
3238 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3239 ":", '' ).replace( "of", '' )
3240 onosPort1 = onosLink[ 'src' ][ 'port' ]
3241 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3242
3243 # check onos link from node1 to node2
3244 if str( onosNode1 ) == str( node1 ) and str(
3245 onosNode2 ) == str( node2 ):
3246 if int( onosPort1 ) == int( port1 ) and int(
3247 onosPort2 ) == int( port2 ):
3248 firstDir = main.TRUE
3249 else:
Jon Hallab611372018-02-21 15:26:05 -08003250 # The right switches, but wrong ports, could be
3251 # another link between these devices, or onos
3252 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003253 main.log.warn(
3254 'The port numbers do not match for ' +
3255 str( link ) +
3256 ' between ONOS and MN. When checking ONOS for ' +
3257 'link %s/%s -> %s/%s' %
3258 ( node1, port1, node2, port2 ) +
3259 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003260 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3261 '. This could be another link between these devices' +
3262 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003263
3264 # check onos link from node2 to node1
3265 elif ( str( onosNode1 ) == str( node2 ) and
3266 str( onosNode2 ) == str( node1 ) ):
3267 if ( int( onosPort1 ) == int( port2 )
3268 and int( onosPort2 ) == int( port1 ) ):
3269 secondDir = main.TRUE
3270 else:
Jon Hallab611372018-02-21 15:26:05 -08003271 # The right switches, but wrong ports, could be
3272 # another link between these devices, or onos
3273 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003274 main.log.warn(
3275 'The port numbers do not match for ' +
3276 str( link ) +
3277 ' between ONOS and MN. When checking ONOS for ' +
3278 'link %s/%s -> %s/%s' %
3279 ( node1, port1, node2, port2 ) +
3280 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003281 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3282 '. This could be another link between these devices' +
3283 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003284 else: # this is not the link you're looking for
3285 pass
3286 if not firstDir:
3287 main.log.error(
3288 'ONOS does not have the link %s/%s -> %s/%s' %
3289 ( node1, port1, node2, port2 ) )
3290 if not secondDir:
3291 main.log.error(
3292 'ONOS does not have the link %s/%s -> %s/%s' %
3293 ( node2, port2, node1, port1 ) )
3294 linkResults = linkResults and firstDir and secondDir
3295 return linkResults
3296 except pexpect.EOF:
3297 main.log.error( self.name + ": EOF exception found" )
3298 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003299 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003300 except Exception:
3301 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003302 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003303
Jon Hallafa8a472015-06-12 14:02:42 -07003304 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003305 """
Jon Hallafa8a472015-06-12 14:02:42 -07003306 Compare mn and onos Hosts.
3307 Since Mininet hosts are quiet, ONOS will only know of them when they
3308 speak. For this reason, we will only check that the hosts in ONOS
3309 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003310
Jon Hallafa8a472015-06-12 14:02:42 -07003311 Arguments:
3312 hostsJson: parsed json object from the onos hosts api
3313 Returns:
3314 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003315 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003316 try:
3317 hostResults = main.TRUE
3318 for onosHost in hostsJson:
3319 onosMAC = onosHost[ 'mac' ].lower()
3320 match = False
3321 for mnHost, info in hosts.iteritems():
3322 for mnIntf in info[ 'interfaces' ]:
3323 if onosMAC == mnIntf[ 'mac' ].lower():
3324 match = True
3325 for ip in mnIntf[ 'ips' ]:
3326 if ip in onosHost[ 'ipAddresses' ]:
3327 pass # all is well
3328 else:
3329 # misssing ip
3330 main.log.error( "ONOS host " +
3331 onosHost[ 'id' ] +
3332 " has a different IP(" +
3333 str( onosHost[ 'ipAddresses' ] ) +
3334 ") than the Mininet host(" +
3335 str( ip ) +
3336 ")." )
3337 output = json.dumps(
3338 onosHost,
3339 sort_keys=True,
3340 indent=4,
3341 separators=( ',', ': ' ) )
3342 main.log.info( output )
3343 hostResults = main.FALSE
3344 if not match:
3345 hostResults = main.FALSE
3346 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3347 "corresponding Mininet host." )
3348 output = json.dumps( onosHost,
3349 sort_keys=True,
3350 indent=4,
3351 separators=( ',', ': ' ) )
3352 main.log.info( output )
3353 return hostResults
3354 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003355 main.log.error( self.name + ": EOF exception found" )
3356 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003357 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003358 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003359 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003360 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003361
You Wangd66de192018-04-30 17:30:12 -07003362 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003363 """
3364 Description:
3365 Verify that all hosts have IP address assigned to them
3366 Optional:
3367 hostList: If specified, verifications only happen to the hosts
3368 in hostList
3369 prefix: at least one of the ip address assigned to the host
3370 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003371 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003372 Returns:
3373 main.TRUE if all hosts have specific IP address assigned;
3374 main.FALSE otherwise
3375 """
3376 try:
You Wangd66de192018-04-30 17:30:12 -07003377 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003378 if not hostList:
3379 hostList = hosts.keys()
3380 for hostName in hosts.keys():
3381 if hostName not in hostList:
3382 continue
3383 ipList = []
3384 self.handle.sendline( str( hostName ) + " ip a" )
3385 self.handle.expect( "mininet>" )
3386 ipa = self.handle.before
3387 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3388 ipList += re.findall( ipv4Pattern, ipa )
3389 # It's tricky to make regex for IPv6 addresses and this one is simplified
3390 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})/'
3391 ipList += re.findall( ipv6Pattern, ipa )
3392 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3393 if not ipList:
3394 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3395 else:
3396 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3397 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3398 else:
3399 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3400 hostList.remove( hostName )
3401 return main.FALSE if hostList else main.TRUE
3402 except KeyError:
3403 main.log.exception( self.name + ": host data not as expected: " + hosts )
3404 return None
3405 except pexpect.EOF:
3406 main.log.error( self.name + ": EOF exception found" )
3407 main.log.error( self.name + ": " + self.handle.before )
3408 main.cleanAndExit()
3409 except Exception:
3410 main.log.exception( self.name + ": Uncaught exception" )
3411 return None
3412
Jon Hallafa8a472015-06-12 14:02:42 -07003413 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003414 """
3415 Returns a list of all hosts
3416 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003417 try:
3418 self.handle.sendline( "" )
3419 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003420
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003421 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3422 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003423
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 handlePy = self.handle.before
3425 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3426 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 self.handle.sendline( "" )
3429 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003430
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431 hostStr = handlePy.replace( "]", "" )
3432 hostStr = hostStr.replace( "'", "" )
3433 hostStr = hostStr.replace( "[", "" )
3434 hostStr = hostStr.replace( " ", "" )
3435 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003436
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003437 return hostList
3438 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003439 main.log.error( self.name + ": TIMEOUT exception found" )
3440 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003442 except pexpect.EOF:
3443 main.log.error( self.name + ": EOF exception found" )
3444 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003445 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003446 except Exception:
3447 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003448 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003449
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003450 def getSwitch( self ):
3451 """
3452 Returns a list of all switches
3453 Again, don't ask question just use it...
3454 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003455 try:
3456 # get host list...
3457 hostList = self.getHosts()
3458 # Make host set
3459 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003460
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003461 # Getting all the nodes in mininet
3462 self.handle.sendline( "" )
3463 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003464
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003465 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3466 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003467
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003468 handlePy = self.handle.before
3469 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3470 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003471
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003472 self.handle.sendline( "" )
3473 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003474
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003475 nodesStr = handlePy.replace( "]", "" )
3476 nodesStr = nodesStr.replace( "'", "" )
3477 nodesStr = nodesStr.replace( "[", "" )
3478 nodesStr = nodesStr.replace( " ", "" )
3479 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003480
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003481 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003482 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 nodesSet.discard( 'c0' )
3484 nodesSet.discard( 'c1' )
3485 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003486
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003487 switchSet = nodesSet - hostSet
3488 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003489
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003490 return switchList
3491 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003492 main.log.error( self.name + ": TIMEOUT exception found" )
3493 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003494 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003495 except pexpect.EOF:
3496 main.log.error( self.name + ": EOF exception found" )
3497 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003498 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003499 except Exception:
3500 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003501 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003502
You Wang7d14d642019-01-23 15:10:08 -08003503 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003504 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003505 """
3506 Return a dictionary which describes the latest Mininet topology data as a
3507 graph.
3508 An example of the dictionary:
3509 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3510 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3511 Each vertex should at least have an 'edges' attribute which describes the
3512 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003513 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003514 list of attributes.
3515 An example of the edges dictionary:
3516 'edges': { vertex2: { 'port': ..., 'weight': ... },
3517 vertex3: { 'port': ..., 'weight': ... } }
3518 If useId == True, dpid/mac will be used instead of names to identify
3519 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3520 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003521 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003522 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003523 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3524 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003525 Note that link or switch that are brought down by 'link x x down' or 'switch
3526 x down' commands still show in the output of Mininet CLI commands such as
3527 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3528 recommended to use delLink() or delSwitch functions to simulate link/switch
3529 down, and addLink() or addSwitch to add them back.
3530 """
3531 graphDict = {}
3532 try:
You Wang7d14d642019-01-23 15:10:08 -08003533 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003534 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003535 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003536 if includeHost:
3537 hosts = self.getHosts()
3538 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003539 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003540 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3541 continue
3542 nodeName1 = link[ 'node1' ]
3543 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003544 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3545 # The device is probably offline
3546 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003547 port1 = link[ 'port1' ]
3548 port2 = link[ 'port2' ]
3549 # Loop for two nodes
3550 for i in range( 2 ):
3551 # Get port index from OVS
3552 # The index extracted from port name may be inconsistent with ONOS
3553 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003554 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003555 portList = self.getOVSPorts( nodeName1 )
3556 if len( portList ) == 0:
3557 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3558 return None
3559 portDict[ nodeName1 ] = portList
3560 for port in portDict[ nodeName1 ]:
3561 if port[ 'port' ] == port1:
3562 portIndex = port[ 'index' ]
3563 break
3564 if portIndex == -1:
3565 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3566 return None
3567 if useId:
3568 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3569 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3570 else:
3571 node1 = nodeName1
3572 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003573 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003574 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003575 graphDict[ node1 ] = { 'edges': {},
3576 'dpid': switches[ nodeName1 ][ 'dpid' ],
3577 'name': nodeName1,
3578 'ports': switches[ nodeName1 ][ 'ports' ],
3579 'swClass': switches[ nodeName1 ][ 'swClass' ],
3580 'pid': switches[ nodeName1 ][ 'pid' ],
3581 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003582 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003583 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003584 else:
3585 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003586 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3587 pass
3588 for port in switches[ nodeName1 ][ 'ports' ]:
3589 if port[ 'of_port' ] == str( portIndex ):
3590 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003591 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003592 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3593 else:
3594 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003595 # Swap two nodes/ports
3596 nodeName1, nodeName2 = nodeName2, nodeName1
3597 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003598 # Remove links with disabled ports
3599 linksToRemove = []
3600 for node, edges in graphDict.items():
3601 for neighbor, port in edges[ 'edges' ].items():
3602 if port[ 'port' ] == -1:
3603 linksToRemove.append( ( node, neighbor ) )
3604 for node1, node2 in linksToRemove:
3605 for i in range( 2 ):
3606 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3607 graphDict[ node1 ][ 'edges' ].pop( node2 )
3608 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003609 return graphDict
3610 except KeyError:
3611 main.log.exception( self.name + ": KeyError exception found" )
3612 return None
3613 except AssertionError:
3614 main.log.exception( self.name + ": AssertionError exception found" )
3615 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003616 except pexpect.EOF:
3617 main.log.error( self.name + ": EOF exception found" )
3618 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003619 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003620 except Exception:
3621 main.log.exception( self.name + ": Uncaught exception" )
3622 return None
3623
Devin Lima7cfdbd2017-09-29 15:02:22 -07003624 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003625 """
3626 updates the port address and status information for
3627 each port in mn"""
Jon Hallefbd9792015-03-05 16:11:36 -08003628 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003629 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003630 self.handle.sendline( "" )
3631 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003632
Jon Hall43060f62020-06-23 13:13:33 -07003633 # If update command isn't available, do it manually
Jon Hall7eb38402015-01-08 17:19:54 -08003634 self.handle.sendline( "update" )
Jon Hall43060f62020-06-23 13:13:33 -07003635 self.handle.expect( "update" )
3636 i = self.handle.expect( [ "Unknown command: update", "mininet>" ], timeout )
3637 if i == 0:
3638 main.log.debug( self.handle.before + self.handle.after )
3639 main.log.warn( "Mininet cli does not have update command, attempting to update interfaces without it" )
3640 self.handle.expect( "mininet>" )
3641 self.handle.sendline( "px [i.updateAddr() for h in net.hosts for i in h.intfs.values() ] " )
3642 self.handle.expect( "mininet>", timeout )
3643 self.handle.sendline( "px [i.updateAddr() for s in net.switches for i in h.intfs.values() ] " )
3644 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003645
Jon Hall7eb38402015-01-08 17:19:54 -08003646 self.handle.sendline( "" )
3647 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003648
Jon Hallb1290e82014-11-18 16:17:48 -05003649 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003650 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003651 main.log.error( self.name + ": TIMEOUT exception found" )
3652 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003653 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003654 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003655 main.log.error( self.name + ": EOF exception found" )
3656 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003657 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003658 except Exception:
3659 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003660 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003661
Jon Halld80cc142015-07-06 13:36:05 -07003662 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003663 """
3664 Add vlan tag to a host.
3665 Dependencies:
3666 This class depends on the "vlan" package
3667 $ sudo apt-get install vlan
3668 Configuration:
3669 Load the 8021q module into the kernel
3670 $sudo modprobe 8021q
3671
3672 To make this setup permanent:
3673 $ sudo su -c 'echo "8021q" >> /etc/modules'
3674 """
3675 if self.handle:
3676 try:
Jon Halld80cc142015-07-06 13:36:05 -07003677 # get the ip address of the host
3678 main.log.info( "Get the ip address of the host" )
3679 ipaddr = self.getIPAddress( host )
3680 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003681
Jon Halld80cc142015-07-06 13:36:05 -07003682 # remove IP from interface intf
3683 # Ex: h1 ifconfig h1-eth0 inet 0
3684 main.log.info( "Remove IP from interface " )
3685 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3686 self.handle.sendline( cmd2 )
3687 self.handle.expect( "mininet>" )
3688 response = self.handle.before
3689 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003690
Jon Halld80cc142015-07-06 13:36:05 -07003691 # create VLAN interface
3692 # Ex: h1 vconfig add h1-eth0 100
3693 main.log.info( "Create Vlan" )
3694 cmd3 = host + " vconfig add " + intf + " " + vlan
3695 self.handle.sendline( cmd3 )
3696 self.handle.expect( "mininet>" )
3697 response = self.handle.before
3698 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003699
Jon Halld80cc142015-07-06 13:36:05 -07003700 # assign the host's IP to the VLAN interface
3701 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3702 main.log.info( "Assign the host IP to the vlan interface" )
3703 vintf = intf + "." + vlan
3704 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3705 self.handle.sendline( cmd4 )
3706 self.handle.expect( "mininet>" )
3707 response = self.handle.before
3708 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003709
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003710 # update Mininet node variables
3711 main.log.info( "Update Mininet node variables" )
3712 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3713 self.handle.sendline( cmd5 )
3714 self.handle.expect( "mininet>" )
3715 response = self.handle.before
3716 main.log.info( "====> %s ", response )
3717
3718 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3719 self.handle.sendline( cmd6 )
3720 self.handle.expect( "mininet>" )
3721 response = self.handle.before
3722 main.log.info( "====> %s ", response )
3723
3724 return main.TRUE
3725 except pexpect.TIMEOUT:
3726 main.log.error( self.name + ": TIMEOUT exception found" )
3727 main.log.error( self.name + ": " + self.handle.before )
3728 main.cleanAndExit()
3729 except pexpect.EOF:
3730 main.log.error( self.name + ": EOF exception found" )
3731 main.log.error( self.name + ": " + self.handle.before )
3732 return main.FALSE
3733 except Exception:
3734 main.log.exception( self.name + ": Uncaught exception!" )
3735 return main.FALSE
3736
3737 def removeVLAN( self, host, intf ):
3738 """
3739 Remove vlan tag from a host.
3740 Dependencies:
3741 This class depends on the "vlan" package
3742 $ sudo apt-get install vlan
3743 Configuration:
3744 Load the 8021q module into the kernel
3745 $sudo modprobe 8021q
3746
3747 To make this setup permanent:
3748 $ sudo su -c 'echo "8021q" >> /etc/modules'
3749 """
3750 if self.handle:
3751 try:
3752 # get the ip address of the host
3753 main.log.info( "Get the ip address of the host" )
3754 ipaddr = self.getIPAddress( host )
3755
3756 # remove VLAN interface
3757 # Ex: h1 vconfig rem h1-eth0.100
3758 main.log.info( "Remove Vlan interface" )
3759 cmd2 = host + " vconfig rem " + intf
3760 self.handle.sendline( cmd2 )
3761 self.handle.expect( "mininet>" )
3762 response = self.handle.before
3763 main.log.info( "====> %s ", response )
3764
3765 # assign the host's IP to the original interface
3766 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3767 main.log.info( "Assign the host IP to the original interface" )
3768 original_intf = intf.split(".")[0]
3769 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3770 self.handle.sendline( cmd3 )
3771 self.handle.expect( "mininet>" )
3772 response = self.handle.before
3773 main.log.info( "====> %s ", response )
3774
3775 # update Mininet node variables
3776 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3777 self.handle.sendline( cmd4 )
3778 self.handle.expect( "mininet>" )
3779 response = self.handle.before
3780 main.log.info( "====> %s ", response )
3781
3782 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3783 self.handle.sendline( cmd5 )
3784 self.handle.expect( "mininet>" )
3785 response = self.handle.before
3786 main.log.info( "====> %s ", response )
3787
kaouthera3f13ca22015-05-05 15:01:41 -07003788 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003789 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003790 main.log.error( self.name + ": TIMEOUT exception found" )
3791 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003792 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003793 except pexpect.EOF:
3794 main.log.error( self.name + ": EOF exception found" )
3795 main.log.error( self.name + ": " + self.handle.before )
3796 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003797 except Exception:
3798 main.log.exception( self.name + ": Uncaught exception!" )
3799 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003800
Jon Hall43060f62020-06-23 13:13:33 -07003801 def createHostComponent( self, name, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003802 """
3803 Creates a new mininet cli component with the same parameters as self.
3804 This new component is intended to be used to login to the hosts created
3805 by mininet.
3806
3807 Arguments:
3808 name - The string of the name of this component. The new component
3809 will be assigned to main.<name> .
3810 In addition, main.<name>.name = str( name )
3811 """
3812 try:
3813 # look to see if this component already exists
3814 getattr( main, name )
3815 except AttributeError:
3816 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003817 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3818 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall43060f62020-06-23 13:13:33 -07003819 component = main.componentInit( name )
3820 if execDir is not None:
3821 component.mExecDir = execDir
3822 else:
3823 component.mExecDir = self.mExecDir
3824
3825 if hostHome is not None:
3826 component.hostHome = hostHome
3827 else:
3828 component.hostHome = self.hostHome
3829 component.hostPrompt = self.hostPrompt
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003830 except pexpect.EOF:
3831 main.log.error( self.name + ": EOF exception found" )
3832 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003833 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003834 except Exception:
3835 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003836 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003837 else:
3838 # namespace is not clear!
3839 main.log.error( name + " component already exists!" )
3840 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003841 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003842
3843 def removeHostComponent( self, name ):
3844 """
3845 Remove host component
3846 Arguments:
3847 name - The string of the name of the component to delete.
3848 """
3849 try:
3850 # Get host component
3851 component = getattr( main, name )
3852 except AttributeError:
3853 main.log.error( "Component " + name + " does not exist." )
3854 return
3855 try:
3856 # Disconnect from component
3857 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003858 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003859 # Delete component
3860 delattr( main, name )
3861 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003862 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003863 except StandardError:
3864 self.log.exception( "Exception while closing log files for " + name )
3865 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003866 except pexpect.EOF:
3867 main.log.error( self.name + ": EOF exception found" )
3868 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003869 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003870 except Exception:
3871 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003872 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003873
Jon Hall43060f62020-06-23 13:13:33 -07003874 def startHostCli( self, host=None, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003875 """
3876 Use the mininet m utility to connect to the host's cli
Jon Hall43060f62020-06-23 13:13:33 -07003877 mnexec tries to cd to cwd after it connects to the host. If execDir
3878 is set, this will change cwd to execDir before executing m.
3879 If hostHome is set, the function will export the value to the HOME
3880 environment variable.
Jon Hall892818c2015-10-20 17:58:34 -07003881 """
3882 # These are fields that can be used by scapy packets. Initialized to None
3883 self.hostIp = None
3884 self.hostMac = None
Jon Hall43060f62020-06-23 13:13:33 -07003885 if execDir is not None:
3886 self.mExecDir = execDir
3887 if hostHome is not None:
3888 self.hostHome = hostHome
Jon Hall892818c2015-10-20 17:58:34 -07003889 try:
3890 if not host:
3891 host = self.name
Jon Hall43060f62020-06-23 13:13:33 -07003892 if self.mExecDir:
3893 self.handle.sendline( "cd %s" % self.mExecDir )
3894 self.handle.expect( self.prompt )
3895
Jon Hall892818c2015-10-20 17:58:34 -07003896 self.handle.sendline( self.home + "/util/m " + host )
Jon Hall43060f62020-06-23 13:13:33 -07003897 if self.hostHome:
3898 self.handle.sendline( "export HOME=%s" % self.hostHome )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003899 self.handle.sendline( "cd" )
3900 self.handle.expect( self.hostPrompt )
3901 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003902 self.handle.expect( self.hostPrompt )
3903 return main.TRUE
3904 except pexpect.TIMEOUT:
3905 main.log.exception( self.name + ": Command timed out" )
Jon Hall43060f62020-06-23 13:13:33 -07003906 main.log.debug( self.handle.before )
Jon Hall892818c2015-10-20 17:58:34 -07003907 return main.FALSE
3908 except pexpect.EOF:
3909 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003910 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003911 except Exception:
3912 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003913 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003914
YPZhang801d46d2016-08-08 13:26:28 -07003915 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003916 '''
3917
YPZhang801d46d2016-08-08 13:26:28 -07003918 Args:
3919 devicename: switch name
3920 intf: port name on switch
3921 status: up or down
3922
3923 Returns: boolean to show success change status
3924
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003925 '''
YPZhang801d46d2016-08-08 13:26:28 -07003926 if status == "down" or status == "up":
3927 try:
3928 cmd = devicename + " ifconfig " + intf + " " + status
3929 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003930 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003931 return main.TRUE
3932 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003933 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003934 return main.FALSE
3935 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003936 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003937 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003938 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003939 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003940 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003941 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003942 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003943 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003944 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003945 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003946 return main.FALSE
3947
You Wang6e5b48e2018-07-23 16:17:38 -07003948 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003949 """
You Wang6e5b48e2018-07-23 16:17:38 -07003950 Moves a host from one switch to another on the fly
3951 Optional:
3952 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3953 prefixLen: length of the host IP prefix
3954 ipv6: move an IPv6 host if True
3955 intfSuffix: suffix of the new interface after host movement
3956 vlan: vlan ID of the host. Use None for non-vlan host
3957 Note: The intf between host and oldSw when detached
3958 using detach(), will still show up in the 'net'
3959 cmd, because switch.detach() doesn't affect switch.intfs[]
3960 ( which is correct behavior since the interfaces
3961 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003962 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003963 if self.handle:
3964 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003965 newIntf = "%s-%s" % ( host, intfSuffix )
3966 commands = [
3967 # Bring link between oldSw-host down
3968 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3969 # Determine hostintf and Oldswitchintf
3970 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3971 ]
3972 # Determine ip address of the host-oldSw interface
3973 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3974 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3975 commands += [
3976 # Determine mac address of the host-oldSw interface
3977 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3978 # Detach interface between oldSw-host
3979 "px " + oldSw + ".detach( sintf )",
3980 # Add link between host-newSw
3981 "py net.addLink(" + host + "," + newSw + ")",
3982 # Determine hostintf and Newswitchintf
3983 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3984 # Attach interface between newSw-host
3985 "px " + newSw + ".attach( sintf )",
3986 ]
3987 if vlan:
3988 vlanIntf = "%s.%s" % ( newIntf, vlan )
3989 commands += [
3990 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3991 host + " ip link set up %s" % vlanIntf,
3992 "px hintf.name = '" + vlanIntf + "'",
3993 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3994 ]
3995 newIntf = vlanIntf
3996 commands += [
3997 # Set mac address of the host-newSw interface
3998 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3999 # Set IP address of the host-newSw interface
4000 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
4001 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
4002 ]
4003 if ipv6:
4004 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
4005 commands += [
4006 "net",
4007 host + " ifconfig"
4008 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004009 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004010 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004011 self.handle.sendline( cmd )
4012 self.handle.expect( "mininet>" )
4013 main.log.info( "====> %s ", self.handle.before )
4014 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004015 except pexpect.TIMEOUT:
4016 main.log.error( self.name + ": TIMEOUT exception found" )
4017 main.log.error( self.name + ": " + self.handle.before )
4018 main.cleanAndExit()
4019 except pexpect.EOF:
4020 main.log.error( self.name + ": EOF exception found" )
4021 main.log.error( self.name + ": " + self.handle.before )
4022 return main.FALSE
4023 except Exception:
4024 main.log.exception( self.name + ": Uncaught exception!" )
4025 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004026
You Wang6e5b48e2018-07-23 16:17:38 -07004027 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4028 macAddr=None, prefixLen=None, ipv6=False,
4029 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07004030 """
You Wang6e5b48e2018-07-23 16:17:38 -07004031 Moves a dual-homed host from one switch-pair to another pair on the fly
4032 Optional:
4033 macAddr: when specified, change MAC address of the host interface to specified MAC address.
4034 prefixLen: length of the host IP prefix
4035 ipv6: move an IPv6 host if True
4036 intfSuffix1: suffix of the first new interface
4037 intfSuffix2: suffix of the second new interface
4038 bondSuffix: suffix of the new bond interface
4039 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07004040 """
You Wang7ea90582018-07-19 15:27:58 -07004041 if self.handle:
4042 try:
You Wang6e5b48e2018-07-23 16:17:38 -07004043 bondIntf = "%s-%s" % ( host, bondSuffix )
4044 newIntf = "%s-%s" % ( host, intfSuffix1 )
4045 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07004046 commands = [
4047 # Bring link between oldSw-host down
4048 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4049 # Bring link between oldPairSw-host down
4050 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4051 # Determine hostintf and Oldswitchintf
4052 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07004053 ]
4054 # Determine ip address of the host-oldSw interface
4055 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4056 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4057 commands += [
4058 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07004059 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4060 # Detach interface between oldSw-host
4061 "px " + oldSw + ".detach( sintf )",
4062 # Determine hostintf and Oldpairswitchintf
4063 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4064 # Detach interface between oldPairSw-host
4065 "px " + oldPairSw + ".detach( sintfpair )",
4066 # Add link between host-newSw
4067 "py net.addLink(" + host + "," + newSw + ", 2)",
4068 # Add link between host-newPairSw
4069 "py net.addLink(" + host + "," + newPairSw + ")",
4070 # Determine hostintf and Newswitchintf
4071 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4072 # Determine hostintf and NewPairswitchintf
4073 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4074 # Attach interface between newSw-host
4075 "px " + newSw + ".attach( sintf )",
4076 # Attach interface between newPairSw-host
4077 "px " + newPairSw + ".attach( sintfpair )",
4078 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004079 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004080 host + ' ip link set %s down' % newIntf,
4081 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004082 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4083 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004084 host + ' ip addr flush dev %s' % newIntf,
4085 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004086 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004087 "px lowestIntf = min( [ hintf, hintfpair ] )",
4088 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004089 "px lowestIntf.name = '" + bondIntf + "'",
4090 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004091 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4092 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004093 ]
4094 if vlan:
4095 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4096 commands += [
4097 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4098 host + " ip link set up %s" % vlanIntf,
4099 "px lowestIntf.name = '" + vlanIntf + "'",
4100 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4101 ]
4102 bondIntf = vlanIntf
4103 commands += [
4104 # Set macaddress of the host-newSw interface
4105 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004106 # Set ipaddress of the host-newSw interface
4107 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4108 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004109 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004110 if ipv6:
4111 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4112 commands += [
4113 "net",
4114 host + " ifconfig"
4115 ]
You Wang7ea90582018-07-19 15:27:58 -07004116 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004117 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004118 self.handle.sendline( cmd )
4119 self.handle.expect( "mininet>" )
4120 main.log.info( "====> %s ", self.handle.before )
4121 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004122 except pexpect.TIMEOUT:
4123 main.log.error( self.name + ": TIMEOUT exception found" )
4124 main.log.error( self.name + ": " + self.handle.before )
4125 main.cleanAndExit()
4126 except pexpect.EOF:
4127 main.log.error( self.name + ": EOF exception found" )
4128 main.log.error( self.name + ": " + self.handle.before )
4129 return main.FALSE
4130 except Exception:
4131 main.log.exception( self.name + ": Uncaught exception!" )
4132 return main.FALSE
4133
adminbae64d82013-08-01 10:50:15 -07004134if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004135 sys.modules[ __name__ ] = MininetCliDriver()