blob: 55a106fce92fc9a5315d17ab2e032d490c5eab17 [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
adminbae64d82013-08-01 10:50:15 -070066
Jon Hall7eb38402015-01-08 17:19:54 -080067 def connect( self, **connectargs ):
68 """
69 Here the main is the TestON instance after creating
70 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080071 try:
72 for key in connectargs:
73 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070074 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080075 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070076 for key in self.options:
77 if key == "home":
78 self.home = self.options[ 'home' ]
Jon Halldac3eae2020-06-05 12:04:06 -070079 elif key == "sudo_required":
80 self.sudoRequired = False if self.options[ key ] == "false" else True
kelvin-onlabd9e23de2015-08-06 10:34:44 -070081 if self.home is None or self.home == "":
82 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070083
84 try:
Jon Hall892818c2015-10-20 17:58:34 -070085 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070086 self.ip_address = os.getenv( str( self.ip_address ) )
87 else:
88 main.log.info( self.name +
89 ": Trying to connect to " +
90 self.ip_address )
91
92 except KeyError:
93 main.log.info( "Invalid host name," +
94 " connecting to local host instead" )
95 self.ip_address = 'localhost'
96 except Exception as inst:
97 main.log.error( "Uncaught exception: " + str( inst ) )
98
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -0700100 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -0800101 self ).connect(
102 user_name=self.user_name,
103 ip_address=self.ip_address,
104 port=None,
105 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800106
kelvin-onlaba1484582015-02-02 15:46:20 -0800107 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800108 main.log.info( "Connection successful to the host " +
109 self.user_name +
110 "@" +
111 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800112 return main.TRUE
113 else:
114 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800115 self.user_name +
116 "@" +
117 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800118 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800119 return main.FALSE
120 except pexpect.EOF:
121 main.log.error( self.name + ": EOF exception found" )
122 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700123 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800124 except Exception:
125 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700126 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800127
kelvin-onlab10e8d392015-06-03 13:53:45 -0700128 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800129 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000131 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700132 argument, to start the mininet, as a parameter.
133 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700134 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000136 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700137 args = extra option added when starting the topology from the file
138 mnCmd = Mininet command use to start topology
139 Returns:
140 main.TRUE if the mininet starts successfully, main.FALSE
141 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800142 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700143 try:
144 if self.handle:
145 # make sure old networks are cleaned up
146 main.log.info( self.name +
147 ": Clearing any residual state or processes" )
Jon Halldac3eae2020-06-05 12:04:06 -0700148 cmd = "mn -c"
149 if self.sudoRequired:
150 cmd = "sudo " + cmd
151 self.handle.sendline( cmd )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700152 i = self.handle.expect( [ 'password\sfor\s',
153 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800154 pexpect.EOF,
155 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700156 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800157 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 # Sudo asking for password
159 main.log.info( self.name + ": Sending sudo password" )
160 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800161 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700162 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700163 pexpect.EOF,
164 pexpect.TIMEOUT ],
165 timeout )
166 if i == 1:
167 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700168 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700169 main.log.error( self.name + ": Connection terminated" )
170 elif i == 3: # timeout
171 main.log.error( self.name + ": Something while cleaning " +
172 "Mininet took too long... " )
173 # Craft the string to start mininet
Jon Halldac3eae2020-06-05 12:04:06 -0700174 if self.sudoRequired:
175 cmdString = "sudo "
176 else:
177 cmdString = ""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700178 if not mnCmd:
179 if topoFile is None or topoFile == '': # If no file is given
180 main.log.info( self.name + ": building fresh Mininet" )
181 cmdString += "mn "
182 if args is None or args == '':
183 # If no args given, use args from .topo file
184 args = self.options[ 'arg1' ] +\
185 " " + self.options[ 'arg2' ] +\
186 " --mac --controller " +\
187 self.options[ 'controller' ] + " " +\
188 self.options[ 'arg3' ]
189 else: # else only use given args
190 pass
191 # TODO: allow use of topo args and method args?
192 else: # Use given topology file
193 main.log.info(
194 "Starting Mininet from topo file " +
195 topoFile )
Jon Halldac3eae2020-06-05 12:04:06 -0700196 if self.sudoRequired:
197 cmdString += "-E "
198 cmdString += "python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700199 if args is None:
200 args = ''
201 # TODO: allow use of args from .topo file?
202 cmdString += args
203 else:
204 main.log.info( "Starting Mininet topology using '" + mnCmd +
205 "' command" )
206 cmdString += mnCmd
207 # Send the command and check if network started
208 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700209 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 main.log.info( "Sending '" + cmdString + "' to " + self.name )
211 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 while True:
214 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700215 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700216 '\*\*\*',
217 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800218 pexpect.TIMEOUT,
219 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700220 timeout )
221 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700222 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700223 return main.TRUE
224 elif i == 1:
225 response = str( self.handle.before +
226 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700227 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700228 response += str( self.handle.before +
229 self.handle.after )
230 main.log.error(
231 self.name +
232 ": Launching Mininet failed: " + response )
233 return main.FALSE
234 elif i == 2:
235 self.handle.expect( [ "\n",
236 pexpect.EOF,
237 pexpect.TIMEOUT ],
238 timeout )
239 main.log.info( self.handle.before )
240 elif i == 3:
241 main.log.error( self.name + ": Connection timeout" )
242 return main.FALSE
243 elif i == 4: # timeout
244 main.log.error(
245 self.name +
246 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700247 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700248 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800249 elif i == 5:
250 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
251 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700252 # Why did we hit this part?
253 main.log.error( "startNet did not return correctly" )
254 return main.FASLE
255 else: # if no handle
256 main.log.error( self.name + ": Connection failed to the host " +
257 self.user_name + "@" + self.ip_address )
258 main.log.error( self.name + ": Failed to connect to the Mininet" )
259 return main.FALSE
260 except pexpect.TIMEOUT:
261 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
262 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700263 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700264 except pexpect.EOF:
265 main.log.error( self.name + ": EOF exception found" )
266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700267 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700268 except Exception:
269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700270 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800271
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800272 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700273 try:
274 if topoType == 'tree':
275 # In tree topology, if fanout arg is not given, by default it is 2
276 if fanout is None:
277 fanout = 2
278 k = 0
279 count = 0
280 while( k <= depth - 1 ):
281 count = count + pow( fanout, k )
282 k = k + 1
283 numSwitches = count
284 while( k <= depth - 2 ):
285 # depth-2 gives you only core links and not considering
286 # edge links as seen by ONOS. If all the links including
287 # edge links are required, do depth-1
288 count = count + pow( fanout, k )
289 k = k + 1
290 numLinks = count * fanout
291 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
292 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800293
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700294 elif topoType == 'linear':
295 # In linear topology, if fanout or numHostsPerSw is not given,
296 # by default it is 1
297 if fanout is None:
298 fanout = 1
299 numSwitches = depth
300 numHostsPerSw = fanout
301 totalNumHosts = numSwitches * numHostsPerSw
302 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800303 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
304 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700305 topoDict = { "num_switches": int( numSwitches ),
306 "num_corelinks": int( numLinks ) }
307 return topoDict
308 except Exception:
309 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700310 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400311
kelvin-onlabd3b64892015-01-20 13:26:24 -0800312 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700313 """
314 Calculate the number of switches and links in a topo."""
315 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700316 try:
317 argList = self.options[ 'arg1' ].split( "," )
318 topoArgList = argList[ 0 ].split( " " )
319 argList = map( int, argList[ 1: ] )
320 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700321
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700322 topoDict = self.numSwitchesNlinks( *topoArgList )
323 return topoDict
324 except Exception:
325 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700326 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400327
GlennRCf07c44a2015-09-18 13:33:46 -0700328 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800329 """
330 Verifies the reachability of the hosts using pingall command.
331 Optional parameter timeout allows you to specify how long to
332 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700333 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700334 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700335 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700336 ping
337 acceptableFailed - Set the number of acceptable failed pings for the
338 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800339 Returns:
340 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700341 otherwise main.FALSE
342 """
343 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700344 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700345 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700346 if self.handle:
347 main.log.info(
348 self.name +
349 ": Checking reachabilty to the hosts using pingall" )
350 response = ""
351 failedPings = 0
352 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700353 cmd = "pingall"
354 if protocol == "IPv6":
355 cmd = "py net.pingAll6()"
356 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700357 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700358 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700359 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700360 pexpect.EOF,
361 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700362 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700363 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700364 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700365 response += self.handle.before
366 break
367 elif i == 1:
368 response += self.handle.before + self.handle.after
369 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700370 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700371 returnValue = main.FALSE
372 if shortCircuit:
373 main.log.error( self.name +
374 ": Aborting pingall - "
375 + str( failedPings ) +
376 " pings failed" )
377 break
Jon Hall390696c2015-05-05 17:13:41 -0700378 if ( time.time() - startTime ) > timeout:
379 returnValue = main.FALSE
380 main.log.error( self.name +
381 ": Aborting pingall - " +
382 "Function took too long " )
383 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700384 elif i == 2:
385 main.log.error( self.name +
386 ": EOF exception found" )
387 main.log.error( self.name + ": " +
388 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700389 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700390 elif i == 3:
391 response += self.handle.before
392 main.log.error( self.name +
393 ": TIMEOUT exception found" )
394 main.log.error( self.name +
395 ": " +
396 str( response ) )
397 # NOTE: Send ctrl-c to make sure pingall is done
You Wanga01d7f72019-02-27 11:23:39 -0800398 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -0800399 self.handle.sendline( "" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700400 self.handle.expect( "mininet>" )
401 break
402 pattern = "Results\:"
403 main.log.info( "Pingall output: " + str( response ) )
404 if re.search( pattern, response ):
405 main.log.info( self.name + ": Pingall finished with "
406 + str( failedPings ) + " failed pings" )
407 return returnValue
408 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700409 # NOTE: Send ctrl-c to make sure pingall is done
You Wanga01d7f72019-02-27 11:23:39 -0800410 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -0800411 self.handle.sendline( "" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700412 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700413 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700414 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700415 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700416 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700417 except pexpect.TIMEOUT:
418 if response:
419 main.log.info( "Pingall output: " + str( response ) )
420 main.log.error( self.name + ": pexpect.TIMEOUT found" )
421 return main.FALSE
422 except pexpect.EOF:
423 main.log.error( self.name + ": EOF exception found" )
424 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700425 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700426
Jon Hall7eb38402015-01-08 17:19:54 -0800427 def fpingHost( self, **pingParams ):
428 """
429 Uses the fping package for faster pinging...
430 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700431 try:
432 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
433 command = args[ "SRC" ] + \
434 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
435 self.handle.sendline( command )
436 self.handle.expect(
437 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
438 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
439 response = self.handle.before
440 if re.search( ":\s-", response ):
441 main.log.info( self.name + ": Ping fail" )
442 return main.FALSE
443 elif re.search( ":\s\d{1,2}\.\d\d", response ):
444 main.log.info( self.name + ": Ping good!" )
445 return main.TRUE
446 main.log.info( self.name + ": Install fping on mininet machine... " )
447 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700448 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700449 except Exception:
450 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700451 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700452
Jon Hall3b489db2015-10-05 14:38:37 -0700453 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400454 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700455 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700456
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700458 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700459
460 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700462
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400463 Returns main.FALSE if one or more of hosts specified
464 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700465 wait = int( wait )
466 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400467
468 try:
469 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700470
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400471 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700472 pingResponse = "IPv4 ping across specified hosts\n"
473 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400474 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700475 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400476 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700477 pingList = hostList[ :listIndex ] + \
478 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700479
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700480 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700481
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400482 for temp in pingList:
483 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700484 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700485 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700486 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400487 response = self.handle.before
488 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700489 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400490 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700491 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400492 # One of the host to host pair is unreachable
493 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700494 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700495 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700496 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700497 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700498 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700499 except pexpect.TIMEOUT:
500 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800501 response = self.handle.before
502 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800503 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800504 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800505 self.handle.sendline( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800506 self.handle.expect( "mininet>" )
507 response += self.handle.before + self.handle.after
508 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700509 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400510 except pexpect.EOF:
511 main.log.error( self.name + ": EOF exception found" )
512 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700513 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700514 except Exception:
515 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700516 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400517
You Wangf19d9f42018-02-23 16:34:19 -0800518 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700519 """
You Wangf19d9f42018-02-23 16:34:19 -0800520 IPv6 ping all hosts in hostList.
521
522 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700523
Jon Hall3b489db2015-10-05 14:38:37 -0700524 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700525 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700526 """
527 try:
528 main.log.info( "Testing reachability between specified IPv6 hosts" )
529 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700530 wait = int( wait )
531 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700532 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800533 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700534 for host in hostList:
535 listIndex = hostList.index( host )
536 # List of hosts to ping other than itself
537 pingList = hostList[ :listIndex ] + \
538 hostList[ ( listIndex + 1 ): ]
539
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700540 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700541
Hari Krishna9592fc82015-07-31 15:11:15 -0700542 for temp in pingList:
543 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800544 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700545 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800546 while failedPings <= acceptableFailed:
547 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
548 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700549 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800550 response = self.handle.before
551 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800552 pingResponse += " " + str( temp )
553 break
554 else:
555 failedPings += 1
556 time.sleep(1)
557 if failedPings > acceptableFailed:
558 # One of the host to host pair is unreachable
559 pingResponse += " X"
560 isReachable = main.FALSE
561 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700562 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800563 pingResponse += "\n"
564 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
565 return isReachable
566
567 except pexpect.TIMEOUT:
568 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800569 response = self.handle.before
570 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800571 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800572 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800573 self.handle.sendline( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800574 self.handle.expect( "mininet>" )
575 response += self.handle.before + self.handle.after
576 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800577 return main.FALSE
578 except pexpect.EOF:
579 main.log.error( self.name + ": EOF exception found" )
580 main.log.error( self.name + ": " + self.handle.before )
581 main.cleanAndExit()
582 except Exception:
583 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700584
585 main.cleanAndExit()
586
You Wang32833172018-10-23 15:19:31 -0700587 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700588 '''
You Wang32833172018-10-23 15:19:31 -0700589 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
590 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
591 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700592 Optional:
593 hostList: a list of names of the hosts that need to be discovered. If not
594 specified mininet will send ping from all the hosts
You Wang32833172018-10-23 15:19:31 -0700595 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700596 dstIp: destination address used by IPv4 hosts
597 dstIp6: destination address used by IPv6 hosts
598 Returns:
You Wang32833172018-10-23 15:19:31 -0700599 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700600 '''
601 try:
You Wang32833172018-10-23 15:19:31 -0700602 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700603 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700604 hostList = hosts.keys()
605 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700606 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700607 flushCmd = ""
You Wang036ec2c2019-02-27 15:44:15 -0800608 cmds = []
You Wang48381752018-05-07 13:50:57 -0700609 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700610 flushCmd = "{} ip neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800611 cmds.append( "{} arping -c 1 -w {} {}".format( host, wait, dstIp ) )
You Wang32833172018-10-23 15:19:31 -0700612 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700613 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700614 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800615 # FIXME: we are using the same ipv6Addr for all interfaces
616 ipv6Addr = self.getIPAddress( host, proto='IPV6' )
You Wangad347c92019-02-20 16:13:47 -0800617 for intf in hosts[ host ][ 'interfaces' ]:
618 intfName = intf[ 'name' ]
You Wang036ec2c2019-02-27 15:44:15 -0800619 cmds.append( "{} ndsend {} {}".format( host, ipv6Addr, intfName ) )
You Wangad347c92019-02-20 16:13:47 -0800620 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700621 else:
622 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
623 discoveryResult = main.FALSE
You Wang036ec2c2019-02-27 15:44:15 -0800624 if flushCmd:
You Wang0b82aa52018-06-06 14:33:58 -0700625 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700626 self.handle.expect( "mininet>" )
You Wang036ec2c2019-02-27 15:44:15 -0800627 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700628 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700629 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700630 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700631 except pexpect.TIMEOUT:
632 main.log.exception( self.name + ": TIMEOUT exception" )
633 response = self.handle.before
634 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800635 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700636 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800637 self.handle.sendline( "" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700638 self.handle.expect( "mininet>" )
639 response += self.handle.before + self.handle.after
640 main.log.debug( response )
641 return main.FALSE
642 except pexpect.EOF:
643 main.log.error( self.name + ": EOF exception found" )
644 main.log.error( self.name + ": " + self.handle.before )
645 main.cleanAndExit()
646 except Exception:
647 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800648 main.cleanAndExit()
649
650 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
651 """
652 Verify ping from each host in srcList to each host in dstList
653
654 acceptableFailed: max number of acceptable failed pings
655
656 Returns main.TRUE if all src hosts can reach all dst hosts
657 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
658 """
659 try:
660 main.log.info( "Verifying ping from each src host to each dst host" )
661 isReachable = main.TRUE
662 wait = int( wait )
663 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
664 pingResponse = "Ping output:\n"
665 failedPingsTotal = 0
666 for host in srcList:
667 pingResponse += str( str( host ) + " -> " )
668 for temp in dstList:
669 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700670 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
671 assert dstIP, "Not able to get IP address of host {}".format( temp )
672 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800673 while failedPings <= acceptableFailed:
674 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
675 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700676 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800677 response = self.handle.before
678 if re.search( ',\s0\%\spacket\sloss', response ):
679 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800680 break
681 else:
682 failedPings += 1
683 time.sleep(1)
684 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700685 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800686 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700687 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800688 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700689 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800690 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700692 except AssertionError:
693 main.log.exception( "" )
694 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except pexpect.TIMEOUT:
696 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800697 response = self.handle.before
698 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800699 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800700 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800701 self.handle.sendline( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800702 self.handle.expect( "mininet>" )
703 response += self.handle.before + self.handle.after
704 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700705 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700706 except pexpect.EOF:
707 main.log.error( self.name + ": EOF exception found" )
708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700709 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700710 except Exception:
711 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700712 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700713
Jon Hall7eb38402015-01-08 17:19:54 -0800714 def pingHost( self, **pingParams ):
715 """
Jon Hall3b489db2015-10-05 14:38:37 -0700716 Ping from one mininet host to another
717 Currently the only supported Params: SRC, TARGET, and WAIT
718 """
719 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700720 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700721 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800722 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700723 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700724 try:
Jon Hall61282e32015-03-19 11:34:11 -0700725 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800726 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700727 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700728 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700729 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800730 main.log.error(
731 self.name +
732 ": timeout when waiting for response from mininet" )
733 main.log.error( "response: " + str( self.handle.before ) )
734 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700735 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800736 main.log.error(
737 self.name +
738 ": timeout when waiting for response from mininet" )
739 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700740 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700741 if re.search( ',\s0\%\spacket\sloss', response ):
742 main.log.info( self.name + ": no packets lost, host is reachable" )
743 return main.TRUE
744 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800745 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700746 self.name +
747 ": PACKET LOST, HOST IS NOT REACHABLE" )
748 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800749 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800750 main.log.error( self.name + ": EOF exception found" )
751 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700752 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700753 except Exception:
754 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700755 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700756
757 def ping6pair( self, **pingParams ):
758 """
GlennRC2cf7d952015-09-11 16:32:13 -0700759 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700760 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000761 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700762 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
763 """
Jon Hall3b489db2015-10-05 14:38:37 -0700764 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700765 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700766 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530767 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700768 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700769 try:
770 main.log.info( "Sending: " + command )
771 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700772 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700773 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700774 if i == 1:
775 main.log.error(
776 self.name +
777 ": timeout when waiting for response from mininet" )
778 main.log.error( "response: " + str( self.handle.before ) )
779 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
780 if i == 1:
781 main.log.error(
782 self.name +
783 ": timeout when waiting for response from mininet" )
784 main.log.error( "response: " + str( self.handle.before ) )
785 response = self.handle.before
786 main.log.info( self.name + ": Ping Response: " + response )
787 if re.search( ',\s0\%\spacket\sloss', response ):
788 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700789 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700790 else:
alisone4121a92016-11-22 16:31:36 -0800791 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700792 self.name +
793 ": PACKET LOST, HOST IS NOT REACHABLE" )
794 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700795 except pexpect.EOF:
796 main.log.error( self.name + ": EOF exception found" )
797 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700798 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700799 except Exception:
800 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700801 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800802
You Wangdb927a52016-02-26 11:03:28 -0800803 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
804 """
805 Description:
806 Ping a set of destination host from host CLI.
807 Logging into a Mininet host CLI is required before calling this funtion.
808 Params:
809 dstIPList is a list of destination ip addresses
810 Returns:
811 main.TRUE if the destination host is reachable
812 main.FALSE otherwise
813 """
814 isReachable = main.TRUE
815 wait = int( wait )
816 cmd = "ping"
817 if IPv6:
818 cmd = cmd + "6"
819 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
820 try:
821 for dstIP in dstIPList:
822 pingCmd = cmd + " " + dstIP
823 self.handle.sendline( pingCmd )
824 i = self.handle.expect( [ self.hostPrompt,
825 '\*\*\* Unknown command: ' + pingCmd,
826 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700827 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700828 # For some reason we need to send something
829 # Otherwise ping results won't be read by handle
830 self.handle.sendline( "" )
831 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800832 if i == 0:
833 response = self.handle.before
834 if not re.search( ',\s0\%\spacket\sloss', response ):
835 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
836 isReachable = main.FALSE
837 elif i == 1:
838 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800840 elif i == 2:
841 main.log.error( self.name + ": timeout when waiting for response" )
842 isReachable = main.FALSE
843 else:
844 main.log.error( self.name + ": unknown response: " + self.handle.before )
845 isReachable = main.FALSE
846 except pexpect.TIMEOUT:
847 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700848 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800849 isReachable = main.FALSE
850 except pexpect.EOF:
851 main.log.error( self.name + ": EOF exception found" )
852 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700853 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800854 except Exception:
855 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700856 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800857 return isReachable
858
Jon Hall7eb38402015-01-08 17:19:54 -0800859 def checkIP( self, host ):
860 """
861 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700862 try:
863 if self.handle:
864 try:
865 response = self.execute(
866 cmd=host +
867 " ifconfig",
868 prompt="mininet>",
869 timeout=10 )
870 except pexpect.EOF:
871 main.log.error( self.name + ": EOF exception found" )
872 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700873 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700874
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700875 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
876 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
877 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
878 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
879 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
880 "[0-9]|25[0-5]|[0-9]{1,2})"
881 # pattern = "inet addr:10.0.0.6"
882 if re.search( pattern, response ):
883 main.log.info( self.name + ": Host Ip configured properly" )
884 return main.TRUE
885 else:
886 main.log.error( self.name + ": Host IP not found" )
887 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700888 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700889 main.log.error( self.name + ": Connection failed to the host" )
890 except Exception:
891 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700892 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800893
Jon Hall7eb38402015-01-08 17:19:54 -0800894 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800895 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700896 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800897 response = self.execute(
898 cmd="h1 /usr/sbin/sshd -D&",
899 prompt="mininet>",
900 timeout=10 )
901 response = self.execute(
902 cmd="h4 /usr/sbin/sshd -D&",
903 prompt="mininet>",
904 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700905 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800906 vars( self )[ key ] = connectargs[ key ]
907 response = self.execute(
908 cmd="xterm h1 h4 ",
909 prompt="mininet>",
910 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800911 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800912 main.log.error( self.name + ": EOF exception found" )
913 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700914 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700915 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800916 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700917 if self.flag == 0:
918 self.flag = 1
919 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800920 else:
adminbae64d82013-08-01 10:50:15 -0700921 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800922
Jon Hall7eb38402015-01-08 17:19:54 -0800923 def changeIP( self, host, intf, newIP, newNetmask ):
924 """
925 Changes the ip address of a host on the fly
926 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800927 if self.handle:
928 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800929 cmd = host + " ifconfig " + intf + " " + \
930 newIP + " " + 'netmask' + " " + newNetmask
931 self.handle.sendline( cmd )
932 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800933 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800934 main.log.info( "response = " + response )
935 main.log.info(
936 "Ip of host " +
937 host +
938 " changed to new IP " +
939 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800940 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700941 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700942 main.log.error( self.name + ": TIMEOUT exception found" )
943 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700944 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800945 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 main.log.error( self.name + ": EOF exception found" )
947 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700949 except Exception:
950 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700951 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800952
Jon Hall7eb38402015-01-08 17:19:54 -0800953 def changeDefaultGateway( self, host, newGW ):
954 """
955 Changes the default gateway of a host
956 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800957 if self.handle:
958 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800959 cmd = host + " route add default gw " + newGW
960 self.handle.sendline( cmd )
961 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800962 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800963 main.log.info( "response = " + response )
964 main.log.info(
965 "Default gateway of host " +
966 host +
967 " changed to " +
968 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800969 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700970 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700971 main.log.error( self.name + ": TIMEOUT exception found" )
972 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700973 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800974 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800975 main.log.error( self.name + ": EOF exception found" )
976 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800977 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700978 except Exception:
979 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700980 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800981
You Wange24d6272018-03-27 21:18:50 -0700982 def addRoute( self, host, dstIP, interface, ipv6=False ):
983 """
984 Add a route to host
985 Ex: h1 route add -host 224.2.0.1 h1-eth0
986 """
987 if self.handle:
988 try:
989 cmd = str( host )
990 if ipv6:
991 cmd += " route -A inet6 add "
992 else:
993 cmd += " route add -host "
994 cmd += str( dstIP ) + " " + str( interface )
995 self.handle.sendline( cmd )
996 self.handle.expect( "mininet>" )
997 response = self.handle.before
998 main.log.debug( "response = " + response )
999 return main.TRUE
1000 except pexpect.TIMEOUT:
1001 main.log.error( self.name + ": TIMEOUT exception found" )
1002 main.log.error( self.name + ": " + self.handle.before )
1003 main.cleanAndExit()
1004 except pexpect.EOF:
1005 main.log.error( self.name + ": EOF exception found" )
1006 main.log.error( self.name + ": " + self.handle.before )
1007 return main.FALSE
1008 except Exception:
1009 main.log.exception( self.name + ": Uncaught exception!" )
1010 main.cleanAndExit()
1011
Jon Hall7eb38402015-01-08 17:19:54 -08001012 def addStaticMACAddress( self, host, GW, macaddr ):
1013 """
Jon Hallefbd9792015-03-05 16:11:36 -08001014 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001015 if self.handle:
1016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001017 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1018 cmd = host + " arp -s " + GW + " " + macaddr
1019 self.handle.sendline( cmd )
1020 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001021 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001022 main.log.info( "response = " + response )
1023 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001024 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001025 GW +
1026 " changed to " +
1027 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001028 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001029 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001030 main.log.error( self.name + ": TIMEOUT exception found" )
1031 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001032 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001033 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001034 main.log.error( self.name + ": EOF exception found" )
1035 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001036 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001037 except Exception:
1038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001039 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001040
Jon Hall7eb38402015-01-08 17:19:54 -08001041 def verifyStaticGWandMAC( self, host ):
1042 """
1043 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001044 if self.handle:
1045 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001046 # h1 arp -an
1047 cmd = host + " arp -an "
1048 self.handle.sendline( cmd )
1049 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001050 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001051 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001052 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001053 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001054 main.log.error( self.name + ": TIMEOUT exception found" )
1055 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001056 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001057 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001058 main.log.error( self.name + ": EOF exception found" )
1059 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001060 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001061 except Exception:
1062 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001063 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001064
Jon Hall7eb38402015-01-08 17:19:54 -08001065 def getMacAddress( self, host ):
1066 """
1067 Verifies the host's ip configured or not."""
1068 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001069 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001070 response = self.execute(
1071 cmd=host +
1072 " ifconfig",
1073 prompt="mininet>",
1074 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001075 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001076 main.log.error( self.name + ": EOF exception found" )
1077 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001078 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001079 except Exception:
1080 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001081 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001082
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001083 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001084 macAddressSearch = re.search( pattern, response, re.I )
1085 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001086 main.log.info(
1087 self.name +
1088 ": Mac-Address of Host " +
1089 host +
1090 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001091 macAddress )
1092 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001093 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001095
Jon Hall7eb38402015-01-08 17:19:54 -08001096 def getInterfaceMACAddress( self, host, interface ):
1097 """
1098 Return the IP address of the interface on the given host"""
1099 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001100 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001101 response = self.execute( cmd=host + " ifconfig " + interface,
1102 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001103 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001104 main.log.error( self.name + ": EOF exception found" )
1105 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001106 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001107 except Exception:
1108 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001109 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001110
1111 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001112 macAddressSearch = re.search( pattern, response, re.I )
1113 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001114 main.log.info( "No mac address found in %s" % response )
1115 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001116 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001117 main.log.info(
1118 "Mac-Address of " +
1119 host +
1120 ":" +
1121 interface +
1122 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001123 macAddress )
1124 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001125 else:
1126 main.log.error( "Connection failed to the host" )
1127
You Wang5da39c82018-04-26 22:55:08 -07001128 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001129 """
1130 Verifies the host's ip configured or not."""
1131 if self.handle:
1132 try:
1133 response = self.execute(
1134 cmd=host +
1135 " ifconfig",
1136 prompt="mininet>",
1137 timeout=10 )
1138 except pexpect.EOF:
1139 main.log.error( self.name + ": EOF exception found" )
1140 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001141 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001142 except Exception:
1143 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001144 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001145
sathishmad953462015-12-03 17:42:07 +05301146 pattern = ''
1147 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001148 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301149 else:
Jon Hall439c8912016-04-15 02:22:03 -07001150 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001152 if not ipAddressSearch:
1153 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001154 main.log.info(
1155 self.name +
1156 ": IP-Address of Host " +
1157 host +
1158 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001159 ipAddressSearch.group( 1 ) )
1160 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001161 else:
1162 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001163
Jon Hall7eb38402015-01-08 17:19:54 -08001164 def getSwitchDPID( self, switch ):
1165 """
1166 return the datapath ID of the switch"""
1167 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001168 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001169 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001170 response = self.execute(
1171 cmd=cmd,
1172 prompt="mininet>",
1173 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001174 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 main.log.error( self.name + ": EOF exception found" )
1176 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001177 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001178 except Exception:
1179 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001180 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001181 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001182 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001183 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 main.log.info(
1185 "Couldn't find DPID for switch %s, found: %s" %
1186 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001187 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001188 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001189 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001190 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001191
Jon Hall7eb38402015-01-08 17:19:54 -08001192 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001193 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 self.handle.sendline( "" )
1195 self.expect( "mininet>" )
1196 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001197 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001198 response = self.execute(
1199 cmd=cmd,
1200 prompt="mininet>",
1201 timeout=10 )
1202 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001203 response = self.handle.before
1204 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001205 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001206 main.log.error( self.name + ": TIMEOUT exception found" )
1207 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001208 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001209 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 main.log.error( self.name + ": EOF exception found" )
1211 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001212 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001213 except Exception:
1214 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001215 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001216
Jon Hall7eb38402015-01-08 17:19:54 -08001217 def getInterfaces( self, node ):
1218 """
1219 return information dict about interfaces connected to the node"""
1220 if self.handle:
1221 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001222 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001223 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001224 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001225 response = self.execute(
1226 cmd=cmd,
1227 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08001228 timeout=10,
1229 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001230 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001231 main.log.error( self.name + ": EOF exception found" )
1232 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001233 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001234 except Exception:
1235 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001236 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001237 return response
1238 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001239 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001240
Jon Hall7eb38402015-01-08 17:19:54 -08001241 def dump( self ):
1242 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001243 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001244 response = self.execute(
1245 cmd='dump',
1246 prompt='mininet>',
1247 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001248 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001251 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001252 except Exception:
1253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001255 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001256
Jon Hall7eb38402015-01-08 17:19:54 -08001257 def intfs( self ):
1258 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001259 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001260 response = self.execute(
1261 cmd='intfs',
1262 prompt='mininet>',
1263 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001264 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001265 main.log.error( self.name + ": EOF exception found" )
1266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001267 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001268 except Exception:
1269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001270 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001271 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001272
Jon Hall7eb38402015-01-08 17:19:54 -08001273 def net( self ):
1274 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001275 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001276 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001277 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 main.log.error( self.name + ": EOF exception found" )
1279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001281 except Exception:
1282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001283 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001284 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001285
Devin Lima7cfdbd2017-09-29 15:02:22 -07001286 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001287 main.log.info( self.name + ": List network links" )
1288 try:
1289 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001290 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001291 except pexpect.EOF:
1292 main.log.error( self.name + ": EOF exception found" )
1293 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001294 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001295 except Exception:
1296 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001297 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001298 return response
1299
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001300 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001301 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001302 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001303
kelvin-onlab7cce9382015-07-17 10:21:03 -07001304 @parm:
1305 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1306 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001307 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001308 try:
1309 for host1 in hosts:
1310 for host2 in hosts:
1311 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001312 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1313 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001314 except Exception:
1315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001316 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001317
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001318 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001319 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001320 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1321 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001322
kelvin-onlab7cce9382015-07-17 10:21:03 -07001323 @parm:
1324 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1325 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001326 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001327 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1328 try:
1329 # Setup the mininet command
1330 cmd1 = 'iperf ' + host1 + " " + host2
1331 self.handle.sendline( cmd1 )
1332 outcome = self.handle.expect( "mininet>", timeout )
1333 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001334
kelvin-onlab7cce9382015-07-17 10:21:03 -07001335 # checks if there are results in the mininet response
1336 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001337 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001338 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001339 response = response.split( "\r\n" )
1340 response = response[ len( response )-2 ]
1341 response = response.split( ": " )
1342 response = response[ len( response )-1 ]
1343 response = response.replace( "[", "" )
1344 response = response.replace( "]", "" )
1345 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001346
kelvin-onlab7cce9382015-07-17 10:21:03 -07001347 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001348 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001349
kelvin-onlab7cce9382015-07-17 10:21:03 -07001350 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001351 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001352 if len( bandwidth ) == 2:
1353 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001354 return main.TRUE
1355 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001356 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001357 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001358 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001359 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001360 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001361 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001362 main.log.error( self.name + ": TIMEOUT exception found" )
1363 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001364 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001365 # NOTE: Send ctrl-c to make sure iperf is done
You Wanga01d7f72019-02-27 11:23:39 -08001366 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -08001367 self.handle.sendline( "" )
Jon Hall3b489db2015-10-05 14:38:37 -07001368 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001369 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001370 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001371 main.log.error( self.name + ": EOF exception found" )
1372 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001373 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001374 except Exception:
1375 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001376 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001377
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001378 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001379 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1380 try:
1381 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001382 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001383 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001384 outcome1 = self.handle.expect( "mininet>" )
1385 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001386 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001387 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001388 response1 = self.handle.before
1389 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001390 print response1, response2
1391 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001392 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001393 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001394 return main.TRUE
1395 else:
1396 main.log.error( self.name + ": iperf test failed" )
1397 return main.FALSE
1398 except pexpect.TIMEOUT:
1399 main.log.error( self.name + ": TIMEOUT exception found" )
1400 main.log.error( self.name + " response: " + repr( self.handle.before ) )
You Wanga01d7f72019-02-27 11:23:39 -08001401 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
You Wang7ce29462019-03-04 13:37:14 -08001402 self.handle.sendline( "" )
Jon Hall439c8912016-04-15 02:22:03 -07001403 self.handle.expect( "mininet>" )
1404 return main.FALSE
1405 except pexpect.EOF:
1406 main.log.error( self.name + ": EOF exception found" )
1407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001408 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001409 except Exception:
1410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001411 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001412
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001413 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001414 '''
GlennRC61321f22015-07-16 13:36:54 -07001415 Runs the iperfudp function with a given set of hosts and specified
1416 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001417
GlennRC61321f22015-07-16 13:36:54 -07001418 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001419 bandwidth: the targeted bandwidth, in megabits ('M')
1420 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001421 try:
1422 for host1 in hosts:
1423 for host2 in hosts:
1424 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1426 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001427 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001428 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001429 return main.FALSE
1430 except Exception:
1431 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001432 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001433
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001434 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001435 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001436 Creates an iperf UDP test with a specific bandwidth.
1437 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001438
kelvin-onlab7cce9382015-07-17 10:21:03 -07001439 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001440 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1441 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001442 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001443 try:
1444 # setup the mininet command
1445 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 self.handle.sendline( cmd )
1447 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001448 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001449
kelvin-onlab7cce9382015-07-17 10:21:03 -07001450 # check if there are in results in the mininet response
1451 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001452 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001453 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001454 response = response.split( "\r\n" )
1455 response = response[ len( response )-2 ]
1456 response = response.split( ": " )
1457 response = response[ len( response )-1 ]
1458 response = response.replace( "[", "" )
1459 response = response.replace( "]", "" )
1460 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001461
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001462 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001463
kelvin-onlab7cce9382015-07-17 10:21:03 -07001464 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001465 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001467 # if one entry is blank then something is wrong
1468 for item in mnBandwidth:
1469 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001470 main.log.error( self.name + ": Could not parse iperf output" )
1471 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001472 return main.FALSE
1473 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001474 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001475 return main.TRUE
1476 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001477 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001478 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001479
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001480 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001481 main.log.error( self.name + ": TIMEOUT exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001484 except pexpect.EOF:
1485 main.log.error( self.name + ": EOF exception found" )
1486 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001487 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001488 except Exception:
1489 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001490 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001491
Jon Hall7eb38402015-01-08 17:19:54 -08001492 def nodes( self ):
1493 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001494 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 response = self.execute(
1496 cmd='nodes',
1497 prompt='mininet>',
1498 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001499 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001500 main.log.error( self.name + ": EOF exception found" )
1501 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001502 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001503 except Exception:
1504 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001505 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001506 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001507
Jon Hall7eb38402015-01-08 17:19:54 -08001508 def pingpair( self ):
1509 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001510 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001511 response = self.execute(
1512 cmd='pingpair',
1513 prompt='mininet>',
1514 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001515 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001516 main.log.error( self.name + ": EOF exception found" )
1517 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001518 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001519 except Exception:
1520 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001521 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001522
Jon Hall7eb38402015-01-08 17:19:54 -08001523 if re.search( ',\s0\%\spacket\sloss', response ):
1524 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001525 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001526 else:
alisone4121a92016-11-22 16:31:36 -08001527 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001528 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001529
Jon Hall7eb38402015-01-08 17:19:54 -08001530 def link( self, **linkargs ):
1531 """
GlennRCed771242016-01-13 17:02:47 -08001532 Bring link( s ) between two nodes up or down
1533 """
Jon Hall6094a362014-04-11 14:46:56 -07001534 try:
GlennRCed771242016-01-13 17:02:47 -08001535 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1536 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1537 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1538 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1539
1540 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1541 cmd = "link {} {} {}".format( end1, end2, option )
1542 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001543 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001544 response = self.handle.before
1545 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001546 if "not in network" in response:
1547 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1548 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001549 return main.TRUE
1550 except pexpect.TIMEOUT:
1551 main.log.exception( self.name + ": Command timed out" )
1552 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001553 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001554 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001555 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001556 except Exception:
1557 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001558 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001559
pingping-lin8244a3b2015-09-16 13:36:56 -07001560 def switch( self, **switchargs ):
1561 """
1562 start/stop a switch
1563 """
1564 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1565 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1566 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1567 command = "switch " + str( sw ) + " " + str( option )
1568 main.log.info( command )
1569 try:
1570 self.handle.sendline( command )
1571 self.handle.expect( "mininet>" )
1572 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001573 main.log.error( self.name + ": TIMEOUT exception found" )
1574 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001575 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001576 except pexpect.EOF:
1577 main.log.error( self.name + ": EOF exception found" )
1578 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001579 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001580 return main.TRUE
1581
pingping-lin5bb663b2015-09-24 11:47:50 -07001582 def node( self, nodeName, commandStr ):
1583 """
1584 Carry out a command line on a given node
1585 @parm:
1586 nodeName: the node name in Mininet testbed
1587 commandStr: the command line will be carried out on the node
1588 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1589 """
1590 command = str( nodeName ) + " " + str( commandStr )
1591 main.log.info( command )
1592
1593 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001594 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001595 if re.search( "Unknown command", response ):
1596 main.log.warn( response )
1597 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001598 if re.search( "Permission denied", response ):
1599 main.log.warn( response )
1600 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001601 except pexpect.EOF:
1602 main.log.error( self.name + ": EOF exception found" )
1603 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001604 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001605 main.log.info( " response is :" )
1606 main.log.info( response )
1607 return response
1608
Jon Hall7eb38402015-01-08 17:19:54 -08001609 def yank( self, **yankargs ):
1610 """
1611 yank a mininet switch interface to a host"""
1612 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001613 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001614 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1615 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001616 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001617 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001618 response = self.execute(
1619 cmd=command,
1620 prompt="mininet>",
1621 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001622 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 main.log.error( self.name + ": EOF exception found" )
1624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001626 except Exception:
1627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001628 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001629 return main.TRUE
1630
Jon Hall7eb38402015-01-08 17:19:54 -08001631 def plug( self, **plugargs ):
1632 """
1633 plug the yanked mininet switch interface to a switch"""
1634 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001635 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001636 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1637 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001638 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001639 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001640 response = self.execute(
1641 cmd=command,
1642 prompt="mininet>",
1643 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001644 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001645 main.log.error( self.name + ": EOF exception found" )
1646 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001647 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001648 except Exception:
1649 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001650 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001651 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001652
Jon Hall7eb38402015-01-08 17:19:54 -08001653 def dpctl( self, **dpctlargs ):
1654 """
1655 Run dpctl command on all switches."""
1656 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001657 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001658 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1659 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1660 command = "dpctl " + cmd + " " + str( cmdargs )
1661 try:
1662 response = self.execute(
1663 cmd=command,
1664 prompt="mininet>",
1665 timeout=10 )
1666 except pexpect.EOF:
1667 main.log.error( self.name + ": EOF exception found" )
1668 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001669 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001670 except Exception:
1671 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001672 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001673 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001674
kelvin-onlabd3b64892015-01-20 13:26:24 -08001675 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001676 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001677 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001678 try:
1679 fileInput = path + '/lib/Mininet/INSTALL'
1680 version = super( Mininet, self ).getVersion()
1681 pattern = 'Mininet\s\w\.\w\.\w\w*'
1682 for line in open( fileInput, 'r' ).readlines():
1683 result = re.match( pattern, line )
1684 if result:
1685 version = result.group( 0 )
1686 return version
1687 except Exception:
1688 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001689 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001690
kelvin-onlabd3b64892015-01-20 13:26:24 -08001691 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001692 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001693 Parameters:
1694 sw: The name of an OVS switch. Example "s1"
1695 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001696 The output of the command from the mininet cli
1697 or main.FALSE on timeout"""
1698 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001699 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001700 response = self.execute(
1701 cmd=command,
1702 prompt="mininet>",
1703 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001704 if response:
Jon Hallab611372018-02-21 15:26:05 -08001705 if "no bridge named" in response:
1706 main.log.error( self.name + ": Error in getSwController: " +
1707 self.handle.before )
1708 return main.FALSE
1709 else:
1710 return response
admin2a9548d2014-06-17 14:08:07 -07001711 else:
1712 return main.FALSE
1713 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001714 main.log.error( self.name + ": EOF exception found" )
1715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001716 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001717 except Exception:
1718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001719 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001720
Charles Chan029be652015-08-24 01:46:10 +08001721 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001722 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001723 Description:
1724 Assign switches to the controllers ( for ovs use only )
1725 Required:
1726 sw - Name of the switch. This can be a list or a string.
1727 ip - Ip addresses of controllers. This can be a list or a string.
1728 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001729 port - ONOS use port 6653, if no list of ports is passed, then
1730 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001731 ptcp - ptcp number, This can be a string or a list that has
1732 the same length as switch. This is optional and not required
1733 when using ovs switches.
1734 NOTE: If switches and ptcp are given in a list type they should have the
1735 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1736 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001737
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001738 Return:
1739 Returns main.TRUE if mininet correctly assigned switches to
1740 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001741 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001742 """
1743 assignResult = main.TRUE
1744 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001745 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001746 command = "sh ovs-vsctl set-controller "
1747 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001748 try:
1749 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001750 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001751 if isinstance( port, types.StringType ) or \
1752 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001753 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001754 elif isinstance( port, types.ListType ):
1755 main.log.error( self.name + ": Only one controller " +
1756 "assigned and a list of ports has" +
1757 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001758 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001759 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001760 main.log.error( self.name + ": Invalid controller port " +
1761 "number. Please specify correct " +
1762 "controller port" )
1763 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001764
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001765 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001766 if isinstance( port, types.StringType ) or \
1767 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001768 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001769 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1770 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001771 elif isinstance( port, types.ListType ):
1772 if ( len( ip ) != len( port ) ):
1773 main.log.error( self.name + ": Port list = " +
1774 str( len( port ) ) +
1775 "should be the same as controller" +
1776 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001777 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001778 else:
1779 onosIp = ""
1780 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001781 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1782 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001783 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001784 main.log.error( self.name + ": Invalid controller port " +
1785 "number. Please specify correct " +
1786 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001787 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001788 else:
1789 main.log.error( self.name + ": Invalid ip address" )
1790 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001791
1792 if isinstance( sw, types.StringType ):
1793 command += sw + " "
1794 if ptcp:
1795 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001796 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001797 elif isinstance( ptcp, types.ListType ):
1798 main.log.error( self.name + ": Only one switch is " +
1799 "being set and multiple PTCP is " +
1800 "being passed " )
1801 else:
1802 main.log.error( self.name + ": Invalid PTCP" )
1803 ptcp = ""
1804 command += onosIp
1805 commandList.append( command )
1806
1807 elif isinstance( sw, types.ListType ):
1808 if ptcp:
1809 if isinstance( ptcp, types.ListType ):
1810 if len( ptcp ) != len( sw ):
1811 main.log.error( self.name + ": PTCP length = " +
1812 str( len( ptcp ) ) +
1813 " is not the same as switch" +
1814 " length = " +
1815 str( len( sw ) ) )
1816 return main.FALSE
1817 else:
1818 for switch, ptcpNum in zip( sw, ptcp ):
1819 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001820 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001821 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001822 tempCmd += onosIp
1823 commandList.append( tempCmd )
1824 else:
1825 main.log.error( self.name + ": Invalid PTCP" )
1826 return main.FALSE
1827 else:
1828 for switch in sw:
1829 tempCmd = "sh ovs-vsctl set-controller "
1830 tempCmd += switch + " " + onosIp
1831 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001832 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001833 main.log.error( self.name + ": Invalid switch type " )
1834 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001835
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001836 for cmd in commandList:
1837 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001838 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001839 if "no bridge named" in self.handle.before:
1840 main.log.error( self.name + ": Error in assignSwController: " +
1841 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001842 except pexpect.TIMEOUT:
1843 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1844 return main.FALSE
1845 except pexpect.EOF:
1846 main.log.error( self.name + ": EOF exception found" )
1847 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001848 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001849 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001850 except pexpect.EOF:
1851 main.log.error( self.name + ": EOF exception found" )
1852 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001853 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 except Exception:
1855 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001856 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001857
kelvin-onlabd3b64892015-01-20 13:26:24 -08001858 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001859 """
1860 Removes the controller target from sw"""
1861 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001862 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001863 response = self.execute(
1864 cmd=command,
1865 prompt="mininet>",
1866 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001867 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001868 main.log.error( self.name + ": EOF exception found" )
1869 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001870 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001871 except Exception:
1872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001873 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001874 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001875 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001876
kelvin-onlabd3b64892015-01-20 13:26:24 -08001877 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001878 """
Jon Hallb1290e82014-11-18 16:17:48 -05001879 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001880 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001881 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001882 NOTE: cannot currently specify what type of switch
1883 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001884 sw = name of the new switch as a string
1885 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001886 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001887 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001888 """
1889 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001890 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001891 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 response = self.execute(
1893 cmd=command,
1894 prompt="mininet>",
1895 timeout=10 )
1896 if re.search( "already exists!", response ):
1897 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001898 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001899 elif re.search( "Error", response ):
1900 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001901 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001902 elif re.search( "usage:", response ):
1903 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001904 return main.FALSE
1905 else:
1906 return main.TRUE
1907 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001908 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001909 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001910 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001911 except Exception:
1912 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001913 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001914
kelvin-onlabd3b64892015-01-20 13:26:24 -08001915 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001916 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001917 delete a switch from the mininet topology
1918 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001919 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001920 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001921 sw = name of the switch as a string
1922 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001923 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001925 response = self.execute(
1926 cmd=command,
1927 prompt="mininet>",
1928 timeout=10 )
1929 if re.search( "no switch named", response ):
1930 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001931 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001932 elif re.search( "Error", response ):
1933 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001934 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001935 elif re.search( "usage:", response ):
1936 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001937 return main.FALSE
1938 else:
1939 return main.TRUE
1940 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001941 main.log.error( self.name + ": EOF exception found" )
1942 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001943 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001944 except Exception:
1945 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001946 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001947
You Wangb1665b52019-02-01 15:49:48 -08001948 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001949 """
1950 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001951 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001952 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001953 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001954 it just randomly returns one switch from all current switches in
1955 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001956 excludeNodes will be pased to getGraphDict method
You Wangb1665b52019-02-01 15:49:48 -08001957 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001958 Returns the name of the chosen switch.
1959 """
1960 import random
1961 candidateSwitches = []
1962 try:
1963 if not nonCut:
You Wangb1665b52019-02-01 15:49:48 -08001964 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001965 assert len( switches ) != 0
1966 for switchName in switches.keys():
1967 candidateSwitches.append( switchName )
1968 else:
You Wang7d14d642019-01-23 15:10:08 -08001969 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08001970 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001971 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001972 return None
1973 self.graph.update( graphDict )
1974 candidateSwitches = self.graph.getNonCutVertices()
You Wangb1665b52019-02-01 15:49:48 -08001975 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001976 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001977 return None
1978 elif len( candidateSwitches ) == 0:
1979 main.log.info( self.name + ": No candidate switch for deletion" )
1980 return None
1981 else:
1982 switch = random.sample( candidateSwitches, 1 )
1983 return switch[ 0 ]
1984 except KeyError:
1985 main.log.exception( self.name + ": KeyError exception found" )
1986 return None
1987 except AssertionError:
1988 main.log.exception( self.name + ": AssertionError exception found" )
1989 return None
1990 except Exception:
1991 main.log.exception( self.name + ": Uncaught exception" )
1992 return None
1993
1994 def delSwitchRandom( self, timeout=60, nonCut=True ):
1995 """
1996 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001997 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001998 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001999 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002000 otherwise it just randomly delete one switch from all current
2001 switches in Mininet.
2002 Returns the name of the deleted switch
2003 """
2004 try:
2005 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002006 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002007 return None
2008 else:
2009 deletionResult = self.delSwitch( switch )
2010 if deletionResult:
2011 return switch
2012 else:
2013 return None
2014 except Exception:
2015 main.log.exception( self.name + ": Uncaught exception" )
2016 return None
2017
kelvin-onlabd3b64892015-01-20 13:26:24 -08002018 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002019 """
2020 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002021 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002022 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002023 NOTE: cannot currently specify what type of link
2024 required params:
2025 node1 = the string node name of the first endpoint of the link
2026 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002027 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002028 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002029 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002030 response = self.execute(
2031 cmd=command,
2032 prompt="mininet>",
2033 timeout=10 )
2034 if re.search( "doesnt exist!", response ):
2035 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002036 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002037 elif re.search( "Error", response ):
2038 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002039 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002040 elif re.search( "usage:", response ):
2041 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002042 return main.FALSE
2043 else:
2044 return main.TRUE
2045 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002046 main.log.error( self.name + ": EOF exception found" )
2047 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002048 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002049 except Exception:
2050 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002051 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002052
kelvin-onlabd3b64892015-01-20 13:26:24 -08002053 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002054 """
2055 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002056 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002057 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002058 required params:
2059 node1 = the string node name of the first endpoint of the link
2060 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002061 returns: main.FALSE on an error, else main.TRUE
2062 """
Jon Hallffb386d2014-11-21 13:43:38 -08002063 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002065 response = self.execute(
2066 cmd=command,
2067 prompt="mininet>",
2068 timeout=10 )
2069 if re.search( "no node named", response ):
2070 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002071 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002072 elif re.search( "Error", response ):
2073 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002074 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002075 elif re.search( "usage:", response ):
2076 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002077 return main.FALSE
2078 else:
2079 return main.TRUE
2080 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002081 main.log.error( self.name + ": EOF exception found" )
2082 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002083 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002084 except Exception:
2085 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002086 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002087
You Wangb1665b52019-02-01 15:49:48 -08002088 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002089 """
2090 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002091 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002092 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002093 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002094 it just randomly returns one link from all current links in
2095 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002096 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangb1665b52019-02-01 15:49:48 -08002097 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002098 Returns the link as a list, e.g. [ 's1', 's2' ]
2099 """
2100 import random
2101 candidateLinks = []
2102 try:
2103 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002104 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002105 assert len( links ) != 0
2106 for link in links:
2107 # Exclude host-switch link
2108 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2109 continue
2110 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2111 else:
You Wang7d14d642019-01-23 15:10:08 -08002112 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002113 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002114 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002115 return None
2116 self.graph.update( graphDict )
2117 candidateLinks = self.graph.getNonCutEdges()
You Wangb1665b52019-02-01 15:49:48 -08002118 candidateLinks = [ link for link in candidateLinks
2119 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002120 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002121 return None
2122 elif len( candidateLinks ) == 0:
2123 main.log.info( self.name + ": No candidate link for deletion" )
2124 return None
2125 else:
2126 link = random.sample( candidateLinks, 1 )
2127 return link[ 0 ]
2128 except KeyError:
2129 main.log.exception( self.name + ": KeyError exception found" )
2130 return None
2131 except AssertionError:
2132 main.log.exception( self.name + ": AssertionError exception found" )
2133 return None
2134 except Exception:
2135 main.log.exception( self.name + ": Uncaught exception" )
2136 return None
2137
2138 def delLinkRandom( self, timeout=60, nonCut=True ):
2139 """
2140 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002141 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002142 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002143 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002144 otherwise it just randomly delete one link from all current links
2145 in Mininet.
2146 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2147 """
2148 try:
2149 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002150 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002151 return None
2152 else:
2153 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2154 if deletionResult:
2155 return link
2156 else:
2157 return None
2158 except Exception:
2159 main.log.exception( self.name + ": Uncaught exception" )
2160 return None
2161
kelvin-onlabd3b64892015-01-20 13:26:24 -08002162 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002163 """
Jon Hallb1290e82014-11-18 16:17:48 -05002164 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002165 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002166 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002167 NOTE: cannot currently specify what type of host
2168 required params:
2169 hostname = the string hostname
2170 optional key-value params
2171 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002172 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002173 """
2174 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002175 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002176 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002177 response = self.execute(
2178 cmd=command,
2179 prompt="mininet>",
2180 timeout=10 )
2181 if re.search( "already exists!", response ):
2182 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002183 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002184 elif re.search( "doesnt exists!", response ):
2185 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002186 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002187 elif re.search( "Error", response ):
2188 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002189 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002190 elif re.search( "usage:", response ):
2191 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002192 return main.FALSE
2193 else:
2194 return main.TRUE
2195 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002196 main.log.error( self.name + ": EOF exception found" )
2197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002198 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002199 except Exception:
2200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002201 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002202
kelvin-onlabd3b64892015-01-20 13:26:24 -08002203 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002204 """
2205 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002206 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002207 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002208 NOTE: this uses a custom mn function
2209 required params:
2210 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002211 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002212 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002213 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002214 response = self.execute(
2215 cmd=command,
2216 prompt="mininet>",
2217 timeout=10 )
2218 if re.search( "no host named", response ):
2219 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002220 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002221 elif re.search( "Error", response ):
2222 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002223 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002224 elif re.search( "usage:", response ):
2225 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002226 return main.FALSE
2227 else:
2228 return main.TRUE
2229 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002230 main.log.error( self.name + ": EOF exception found" )
2231 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002232 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002233 except Exception:
2234 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002235 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002236
Jon Hall7eb38402015-01-08 17:19:54 -08002237 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002238 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002239 Called at the end of the test to stop the mininet and
2240 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002241 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002242 try:
2243 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002244 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002245 timeout=2 )
2246 response = main.TRUE
2247 if i == 0:
2248 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002249 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002250 return main.TRUE
2251 # print "Disconnecting Mininet"
2252 if self.handle:
2253 self.handle.sendline( "exit" )
2254 self.handle.expect( "exit" )
2255 self.handle.expect( "(.*)" )
2256 else:
2257 main.log.error( "Connection failed to the host" )
2258 return response
2259 except pexpect.EOF:
2260 main.log.error( self.name + ": EOF exception found" )
2261 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002262 # Do not exit the entire test when pexpect.EOF is caught
2263 # FIXME: We might need to do something else here
2264 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002265 except Exception:
2266 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002267 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002268
Devin Lima7cfdbd2017-09-29 15:02:22 -07002269 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002270 """
Jon Hall21270ac2015-02-16 17:59:55 -08002271 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002272 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002273 main.FALSE if the pexpect handle does not exist.
2274
Jon Halld61331b2015-02-17 16:35:47 -08002275 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002276 """
Jon Halld61331b2015-02-17 16:35:47 -08002277 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002278 response = ''
2279 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002280 try:
Jon Halld80cc142015-07-06 13:36:05 -07002281 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002282 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002283 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002284 pexpect.EOF,
2285 pexpect.TIMEOUT ],
2286 timeout )
2287 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002288 main.log.info( "Exiting mininet.." )
2289 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002290 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002291 prompt=self.prompt,
2292 timeout=exitTimeout )
2293 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jon Halldac3eae2020-06-05 12:04:06 -07002294 cmd = "mn -c"
2295 if self.sudoRequired:
2296 cmd = "sudo " + cmd
2297 self.handle.sendline( cmd )
Jeremyd9e4eb12016-04-13 12:09:06 -07002298 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002299
Jeremyd9e4eb12016-04-13 12:09:06 -07002300 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002301 main.log.info( " Mininet trying to exit while not " +
2302 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002303 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002304 elif i == 2:
2305 main.log.error( "Something went wrong exiting mininet" )
2306 elif i == 3: # timeout
2307 main.log.error( "Something went wrong exiting mininet " +
2308 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002309
You Wang18db8592018-04-02 13:52:03 -07002310 self.handle.sendline( "" )
2311 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002312 cmd = "killall -9 dhclient dhcpd zebra bgpd"
2313 if self.sudoRequired:
2314 cmd = "sudo " + cmd
2315 self.handle.sendline( cmd )
2316 self.handle.expect( self.prompt )
You Wang18db8592018-04-02 13:52:03 -07002317
Hari Krishnab35c6d02015-03-18 11:13:51 -07002318 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002319 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002320 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002321 cmd = "kill -9 \`ps -ef | grep \"" + fileName + "\" | grep -v grep | awk '{print $2}'\`"
2322 if self.sudoRequired:
2323 cmd = "sudo " + cmd
2324 self.handle.sendline( cmd )
2325 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002326 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002327 main.log.error( self.name + ": TIMEOUT exception found" )
2328 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002329 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002330 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002331 main.log.error( self.name + ": EOF exception found" )
2332 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002333 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002334 except Exception:
2335 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002336 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002337 else:
2338 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002339 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002340 return response
2341
YPZhang26a139e2016-04-25 14:01:55 -07002342 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002343 """
2344 Description:
2345 Sends arp message from mininet host for hosts discovery
2346 Required:
2347 host - hosts name
2348 Optional:
2349 ip - ip address that does not exist in the network so there would
2350 be no reply.
2351 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002352 if ethDevice:
2353 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002354 cmd = srcHost + " arping -c1 "
2355 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002356 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 -07002357 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002358 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002359 if output:
2360 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002361 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002362 i = self.handle.expect( [ "mininet>", "arping: " ] )
2363 if i == 0:
2364 return main.TRUE
2365 elif i == 1:
2366 response = self.handle.before + self.handle.after
2367 self.handle.expect( "mininet>" )
2368 response += self.handle.before + self.handle.after
2369 main.log.warn( "Error sending arping, output was: " +
2370 response )
2371 return main.FALSE
2372 except pexpect.TIMEOUT:
2373 main.log.error( self.name + ": TIMEOUT exception found" )
2374 main.log.warn( self.handle.before )
2375 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002376 except pexpect.EOF:
2377 main.log.error( self.name + ": EOF exception found" )
2378 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002379 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002380 except Exception:
2381 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002382 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002383
Jon Hall7eb38402015-01-08 17:19:54 -08002384 def decToHex( self, num ):
2385 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002386
Jon Hall7eb38402015-01-08 17:19:54 -08002387 def getSwitchFlowCount( self, switch ):
2388 """
2389 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002390 if self.handle:
2391 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2392 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002393 response = self.execute(
2394 cmd=cmd,
2395 prompt="mininet>",
2396 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002397 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002398 main.log.error( self.name + ": EOF exception found" )
2399 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002400 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002401 except Exception:
2402 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002403 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002404 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002405 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002406 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002407 main.log.info(
2408 "Couldn't find flows on switch %s, found: %s" %
2409 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002410 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002411 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002412 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002413 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002414
Jon Hall9ed8f372016-02-24 17:34:07 -08002415 def checkFlows( self, sw, dumpFormat=None ):
2416 if dumpFormat:
2417 command = "sh ovs-ofctl -F " + \
2418 dumpFormat + " dump-flows " + str( sw )
2419 else:
2420 command = "sh ovs-ofctl dump-flows " + str( sw )
2421 try:
2422 response = self.execute(
2423 cmd=command,
2424 prompt="mininet>",
2425 timeout=10 )
2426 return response
2427 except pexpect.EOF:
2428 main.log.error( self.name + ": EOF exception found" )
2429 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002430 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002431 except Exception:
2432 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002433 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002434
GlennRC68467eb2015-11-16 18:01:01 -08002435 def flowTableComp( self, flowTable1, flowTable2 ):
2436 # This function compares the selctors and treatments of each flow
2437 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002438 assert flowTable1, "flowTable1 is empty or None"
2439 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002440 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002441 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002442 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002443 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002444 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2445 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002446 for field in dFields:
2447 try:
2448 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002449 except KeyError:
2450 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002451 try:
2452 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002453 except KeyError:
2454 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002455 for i in range( len( flowTable1 ) ):
2456 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002457 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002458 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002459 returnValue = main.FALSE
2460 break
2461 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002462 except AssertionError:
2463 main.log.exception( "Nothing to compare" )
2464 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002465 except Exception:
2466 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002467 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002468
GlennRC528ad292015-11-12 10:38:18 -08002469 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002470 '''
GlennRC956ea742015-11-05 16:14:15 -08002471 Discription: Parses flows into json format.
2472 NOTE: this can parse any string thats separated with commas
2473 Arguments:
2474 Required:
2475 flows: a list of strings that represnt flows
2476 Optional:
2477 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2478 debug: prints out the final result
2479 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002480 '''
GlennRC528ad292015-11-12 10:38:18 -08002481 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002482 try:
2483 for flow in flowTable:
2484 jsonFlow = {}
2485 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002486 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002487 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002488 for i in range( len( parsedFlow ) ):
2489 item = parsedFlow[ i ]
2490 if item[ 0 ] == " ":
2491 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002492 # grab the selector and treatment from the parsed flow
2493 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002494 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002495 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002496 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002497 index = 0
2498 # parse the flags
2499 # NOTE: This only parses one flag
2500 flag = {}
2501 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002502 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002503 index += 1
2504 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002505 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002506 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002507 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002508 # the priority is stuck in the selecter so put it back
2509 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002510 if 'priority' in sel[0]:
2511 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002512 # parse selector
2513 criteria = []
2514 for item in sel:
2515 # this is the type of the packet e.g. "arp"
2516 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002517 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002518 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 field = item.split( "=" )
2520 criteria.append( { field[ 0 ]: field[ 1 ] } )
2521 selector = { "selector": { "criteria": sorted( criteria ) } }
2522 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002523 # get rid of the action part e.g. "action=output:2"
2524 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002525 treat = treat.split( "=" )
2526 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002527 # parse treatment
2528 action = []
2529 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002530 if ":" in item:
2531 field = item.split( ":" )
2532 action.append( { field[ 0 ]: field[ 1 ] } )
2533 else:
2534 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2535 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002536 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002537 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002538 # parse the rest of the flow
2539 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002540 field = item.split( "=" )
2541 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002542 # add the treatment and the selector to the json flow
2543 jsonFlow.update( selector )
2544 jsonFlow.update( treatment )
2545 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002546
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002547 if debug:
2548 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002549
You Wang91c37cf2016-05-23 09:39:42 -07002550 # add the json flow to the json flow table
2551 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002552
You Wang91c37cf2016-05-23 09:39:42 -07002553 return jsonFlowTable
2554
2555 except IndexError:
2556 main.log.exception( self.name + ": IndexError found" )
2557 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002558 except pexpect.EOF:
2559 main.log.error( self.name + ": EOF exception found" )
2560 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002561 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002562 except Exception:
2563 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002564 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002565
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002566 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002567 '''
2568 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002569 Each element is a flow.
2570 Arguments:
2571 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002572 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002573 a list of switches.
2574 Optional:
2575 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2576 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002577 '''
GlennRC956ea742015-11-05 16:14:15 -08002578 try:
2579 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002580 if isinstance( sw, list ):
2581 switches.extend( sw )
2582 else:
2583 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002584
2585 flows = []
2586 for s in switches:
2587 cmd = "sh ovs-ofctl dump-flows " + s
2588
GlennRC528ad292015-11-12 10:38:18 -08002589 if "1.0" == version:
2590 cmd += " -F OpenFlow10-table_id"
2591 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002592 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002593
2594 main.log.info( "Sending: " + cmd )
2595 self.handle.sendline( cmd )
2596 self.handle.expect( "mininet>" )
2597 response = self.handle.before
2598 response = response.split( "\r\n" )
2599 # dump the first two elements and the last
2600 # the first element is the command that was sent
2601 # the second is the table header
2602 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002603 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002604 flows.extend( response )
2605
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002606 if debug:
2607 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002608
GlennRC528ad292015-11-12 10:38:18 -08002609 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002610
GlennRC956ea742015-11-05 16:14:15 -08002611 except pexpect.EOF:
2612 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002613 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002614 except Exception:
2615 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002616 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002617
2618 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002619 '''
GlennRC956ea742015-11-05 16:14:15 -08002620 Discription: Checks whether the ID provided matches a flow ID in Mininet
2621 Arguments:
2622 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002623 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002624 a list of switches.
2625 flowId: the flow ID in hex format. Can also be a list of IDs
2626 Optional:
2627 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2628 debug: prints out the final result
2629 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2630 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002631 '''
GlennRC956ea742015-11-05 16:14:15 -08002632 try:
2633 main.log.info( "Getting flows from Mininet" )
2634 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002635 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002636 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002637
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002638 if debug:
2639 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002640
2641 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002642 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002643 result = False
2644 for f in flows:
2645 if flowId in f.get( 'cookie' ):
2646 result = True
2647 break
2648 # flowId is a list
2649 else:
2650 result = True
2651 # Get flow IDs from Mininet
2652 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2653 # Save the IDs that are not in Mininet
2654 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2655
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002656 if debug:
2657 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002658
2659 # Print out the IDs that are not in Mininet
2660 if absentIds:
2661 main.log.warn( "Absent ids: {}".format( absentIds ) )
2662 result = False
2663
2664 return main.TRUE if result else main.FALSE
2665
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002666 except pexpect.EOF:
2667 main.log.error( self.name + ": EOF exception found" )
2668 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002669 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002670 except Exception:
2671 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002672 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002673
Charles Chan029be652015-08-24 01:46:10 +08002674 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002675 """
Jon Hallefbd9792015-03-05 16:11:36 -08002676 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002677 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002678 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002679 self.handle.sendline( "" )
2680 self.handle.expect( "mininet>" )
Jon Halldac3eae2020-06-05 12:04:06 -07002681 if self.sudoRequired:
2682 sudoStr = "sudo "
2683 else:
2684 sudoStr = ""
Jon Hall7eb38402015-01-08 17:19:54 -08002685 self.handle.sendline(
Jon Halldac3eae2020-06-05 12:04:06 -07002686 "sh " + sudoStr + "tcpdump -n -i " +
2687 intf + " " + port + " -w " +
2688 filename.strip() + " &" )
Jon Hall7eb38402015-01-08 17:19:54 -08002689 self.handle.sendline( "" )
2690 i = self.handle.expect( [ 'No\ssuch\device',
2691 'listening\son',
2692 pexpect.TIMEOUT,
2693 "mininet>" ],
2694 timeout=10 )
2695 main.log.warn( self.handle.before + self.handle.after )
2696 self.handle.sendline( "" )
2697 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002698 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002699 main.log.error(
2700 self.name +
2701 ": tcpdump - No such device exists. " +
2702 "tcpdump attempted on: " +
2703 intf )
admin2a9548d2014-06-17 14:08:07 -07002704 return main.FALSE
2705 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002706 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002707 return main.TRUE
2708 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002709 main.log.error(
2710 self.name +
2711 ": tcpdump command timed out! Check interface name," +
2712 " given interface was: " +
2713 intf )
admin2a9548d2014-06-17 14:08:07 -07002714 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002715 elif i == 3:
2716 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002717 return main.TRUE
2718 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002719 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002720 return main.FALSE
2721 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002722 main.log.error( self.name + ": EOF exception found" )
2723 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002724 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002725 except Exception:
2726 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002727 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002728
kelvin-onlabd3b64892015-01-20 13:26:24 -08002729 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002730 """
2731 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002732 try:
Jon Halldac3eae2020-06-05 12:04:06 -07002733 if self.sudoRequired:
2734 sudoStr = "sudo "
2735 else:
2736 sudoStr = ""
2737 self.handle.sendline( "sh " + sudoStr + " pkill tcpdump" )
Jon Hall7eb38402015-01-08 17:19:54 -08002738 self.handle.expect( "mininet>" )
2739 self.handle.sendline( "" )
2740 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002741 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002742 main.log.error( self.name + ": TIMEOUT exception found" )
2743 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002744 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002745 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002746 main.log.error( self.name + ": EOF exception found" )
2747 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002748 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002749 except Exception:
2750 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002751 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002752
Jon Halld80cc142015-07-06 13:36:05 -07002753 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002754 """
2755 Read ports from a Mininet switch.
2756
2757 Returns a json structure containing information about the
2758 ports of the given switch.
2759 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002760 try:
2761 response = self.getInterfaces( nodeName )
2762 # TODO: Sanity check on response. log if no such switch exists
2763 ports = []
2764 for line in response.split( "\n" ):
2765 if not line.startswith( "name=" ):
2766 continue
2767 portVars = {}
2768 for var in line.split( "," ):
2769 key, value = var.split( "=" )
2770 portVars[ key ] = value
2771 isUp = portVars.pop( 'enabled', "True" )
2772 isUp = "True" in isUp
2773 if verbose:
2774 main.log.info( "Reading switch port %s(%s)" %
2775 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2776 mac = portVars[ 'mac' ]
2777 if mac == 'None':
2778 mac = None
2779 ips = []
2780 ip = portVars[ 'ip' ]
2781 if ip == 'None':
2782 ip = None
2783 ips.append( ip )
2784 name = portVars[ 'name' ]
2785 if name == 'None':
2786 name = None
2787 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2788 if name == 'lo':
2789 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2790 else:
2791 portNo = re.search( portRe, name ).group( 'port' )
2792 ports.append( { 'of_port': portNo,
2793 'mac': str( mac ).replace( '\'', '' ),
2794 'name': name,
2795 'ips': ips,
2796 'enabled': isUp } )
2797 return ports
2798 except pexpect.EOF:
2799 main.log.error( self.name + ": EOF exception found" )
2800 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002801 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002802 except Exception:
2803 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002804 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002805
You Wangdb8cd0a2016-05-26 15:19:45 -07002806 def getOVSPorts( self, nodeName ):
2807 """
2808 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2809
2810 Returns a list of dictionaries containing information about each
2811 port of the given switch.
2812 """
2813 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2814 try:
2815 response = self.execute(
2816 cmd=command,
2817 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002818 timeout=10,
2819 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002820 ports = []
2821 if response:
2822 for line in response.split( "\n" ):
2823 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2824 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002825 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002826 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2827 result = re.search( pattern, line )
2828 if result:
2829 index = result.group( 'index' )
2830 name = result.group( 'name' )
2831 # This port number is extracted from port name
2832 port = result.group( 'port' )
2833 mac = result.group( 'mac' )
2834 ports.append( { 'index': index,
2835 'name': name,
2836 'port': port,
2837 'mac': mac } )
2838 return ports
2839 except pexpect.EOF:
2840 main.log.error( self.name + ": EOF exception found" )
2841 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002842 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002843 except Exception:
2844 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002845 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002846
Jon Halldac3eae2020-06-05 12:04:06 -07002847 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[], switchRegex=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002848 """
2849 Read switches from Mininet.
2850
2851 Returns a dictionary whose keys are the switch names and the value is
2852 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002853 If excludeNodes is specified, switches with names included in excludeNodes
2854 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002855 """
Jon Halla22481b2015-07-28 17:46:01 -07002856 # NOTE: To support new Mininet switch classes, just append the new
2857 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002858
Jon Halla22481b2015-07-28 17:46:01 -07002859 # Regex patterns to parse 'dump' output
2860 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002861 # <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 -07002862 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002863 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2864 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2865 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Jon Halldac3eae2020-06-05 12:04:06 -07002866 if not switchRegex:
2867 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2868 else:
2869 switchClasses = switchRegex
You Wang7d14d642019-01-23 15:10:08 -08002870 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002871 swRE = r"<(?P<class>" + switchClasses + r")" +\
2872 r"(?P<options>\{.*\})?\s" +\
2873 r"(?P<name>[^:]+)\:\s" +\
2874 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2875 r"\spid=(?P<pid>(\d)+)"
2876 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002877 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002878 output = {}
2879 dump = self.dump().split( "\n" )
2880 for line in dump:
2881 result = re.search( swRE, line, re.I )
2882 if result:
2883 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002884 if name in excludeNodes:
2885 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002886 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2887 pid = result.group( 'pid' )
2888 swClass = result.group( 'class' )
2889 options = result.group( 'options' )
2890 if verbose:
2891 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2892 ports = self.getPorts( name )
2893 output[ name ] = { "dpid": dpid,
2894 "ports": ports,
2895 "swClass": swClass,
2896 "pid": pid,
2897 "options": options }
2898 return output
2899 except pexpect.EOF:
2900 main.log.error( self.name + ": EOF exception found" )
2901 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002902 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002903 except Exception:
2904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002905 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002906
You Wangd66de192018-04-30 17:30:12 -07002907 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002908 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2909 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002910 """
2911 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002912 Optional:
2913 hostClass: it is used to match the class of the mininet host. It
2914 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002915 Returns a dictionary whose keys are the host names and the value is
2916 a dictionary containing information about the host.
2917 """
2918 # Regex patterns to parse dump output
2919 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002920 # <Host h1: pid=12725>
2921 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2922 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2923 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002924 # NOTE: Does not correctly match hosts with multi-links
2925 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2926 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002927 try:
You Wang53dba1e2018-02-02 17:45:44 -08002928 if not isinstance( hostClass, types.ListType ):
2929 hostClass = [ str( hostClass ) ]
2930 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002931 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2932 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2933 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002934 if update:
2935 # update mn port info
2936 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002937 # Get mininet dump
2938 dump = self.dump().split( "\n" )
2939 hosts = {}
2940 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002941 result = re.search( hostRE, line )
2942 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002943 name = result.group( 'name' )
2944 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002945 if getInterfaces:
2946 response = self.getInterfaces( name )
2947 # Populate interface info
2948 for line in response.split( "\n" ):
2949 if line.startswith( "name=" ):
2950 portVars = {}
2951 for var in line.split( "," ):
2952 key, value = var.split( "=" )
2953 portVars[ key ] = value
2954 isUp = portVars.pop( 'enabled', "True" )
2955 isUp = "True" in isUp
2956 if verbose:
2957 main.log.info( "Reading host port %s(%s)" %
2958 ( portVars[ 'name' ],
2959 portVars[ 'mac' ] ) )
2960 mac = portVars[ 'mac' ]
2961 if mac == 'None':
2962 mac = None
2963 ips = []
2964 ip = portVars[ 'ip' ]
2965 if ip == 'None':
2966 ip = None
2967 ips.append( ip )
2968 intfName = portVars[ 'name' ]
2969 if name == 'None':
2970 name = None
2971 interfaces.append( {
2972 "name": intfName,
2973 "ips": ips,
2974 "mac": str( mac ),
2975 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002976 hosts[ name ] = { "interfaces": interfaces }
2977 return hosts
2978 except pexpect.EOF:
2979 main.log.error( self.name + ": EOF exception found" )
2980 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002981 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002982 except Exception:
2983 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002984 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002985
You Wang7d14d642019-01-23 15:10:08 -08002986 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002987 """
2988 Gathers information about current Mininet links. These links may not
2989 be up if one of the ports is down.
2990
2991 Returns a list of dictionaries with link endpoints.
2992
2993 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002994 { 'node1': str( node1 name )
2995 'node2': str( node2 name )
2996 'port1': str( port1 of_port )
2997 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002998
You Wangb1665b52019-02-01 15:49:48 -08002999 If either node1 or node2 name matches any of the names sepcified in
3000 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08003001
Jon Hallafa8a472015-06-12 14:02:42 -07003002 Note: The port number returned is the eth#, not necessarily the of_port
3003 number. In Mininet, for OVS switch, these should be the same. For
3004 hosts, this is just the eth#.
3005 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003006 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003007 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003008 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003009
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003010 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003011 # s1-eth3<->s2-eth1 (OK OK)
3012 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08003013 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
3014 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003015 links = []
3016 for line in response:
3017 match = re.search( linkRE, line )
3018 if match:
3019 node1 = match.group( 'node1' )
3020 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08003021 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08003022 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003023 port1 = match.group( 'port1' )
3024 port2 = match.group( 'port2' )
3025 links.append( { 'node1': node1,
3026 'node2': node2,
3027 'port1': port1,
3028 'port2': port2 } )
3029 return links
3030
3031 except pexpect.EOF:
3032 main.log.error( self.name + ": EOF exception found" )
3033 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003034 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003035 except Exception:
3036 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003037 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003038
3039 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003040 """
3041 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003042 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003043
Jon Hallafa8a472015-06-12 14:02:42 -07003044 Dependencies:
3045 1. numpy - "sudo pip install numpy"
3046 """
3047 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003048 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003049 try:
3050 mnDPIDs = []
3051 for swName, switch in switches.iteritems():
3052 mnDPIDs.append( switch[ 'dpid' ].lower() )
3053 mnDPIDs.sort()
3054 if switchesJson == "": # if rest call fails
3055 main.log.error(
3056 self.name +
3057 ".compareSwitches(): Empty JSON object given from ONOS" )
3058 return main.FALSE
3059 onos = switchesJson
3060 onosDPIDs = []
3061 for switch in onos:
3062 if switch[ 'available' ]:
3063 onosDPIDs.append(
3064 switch[ 'id' ].replace(
3065 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003066 '' ).replace(
3067 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003068 '' ).lower() )
3069 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003070
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003071 if mnDPIDs != onosDPIDs:
3072 switchResults = main.FALSE
3073 main.log.error( "Switches in MN but not in ONOS:" )
3074 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3075 main.log.error( str( list1 ) )
3076 main.log.error( "Switches in ONOS but not in MN:" )
3077 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3078 main.log.error( str( list2 ) )
3079 else: # list of dpid's match in onos and mn
3080 switchResults = main.TRUE
3081 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003082
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003083 # FIXME: this does not look for extra ports in ONOS, only checks that
3084 # ONOS has what is in MN
3085 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003086
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003087 # PORTS
3088 for name, mnSwitch in switches.iteritems():
3089 mnPorts = []
3090 onosPorts = []
3091 switchResult = main.TRUE
3092 for port in mnSwitch[ 'ports' ]:
3093 if port[ 'enabled' ]:
3094 mnPorts.append( int( port[ 'of_port' ] ) )
3095 for onosSwitch in portsJson:
3096 if onosSwitch[ 'device' ][ 'available' ]:
3097 if onosSwitch[ 'device' ][ 'id' ].replace(
3098 ':',
3099 '' ).replace(
3100 "of",
3101 '' ) == mnSwitch[ 'dpid' ]:
3102 for port in onosSwitch[ 'ports' ]:
3103 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003104 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003105 # onosPorts.append( 'local' )
3106 onosPorts.append( long( uint64( -2 ) ) )
3107 else:
3108 onosPorts.append( int( port[ 'port' ] ) )
3109 break
3110 mnPorts.sort( key=float )
3111 onosPorts.sort( key=float )
3112
3113 mnPortsLog = mnPorts
3114 onosPortsLog = onosPorts
3115 mnPorts = [ x for x in mnPorts ]
3116 onosPorts = [ x for x in onosPorts ]
3117
3118 # TODO: handle other reserved port numbers besides LOCAL
3119 # NOTE: Reserved ports
3120 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3121 # long( uint64( -2 ) )
3122 for mnPort in mnPortsLog:
3123 if mnPort in onosPorts:
3124 # don't set results to true here as this is just one of
3125 # many checks and it might override a failure
3126 mnPorts.remove( mnPort )
3127 onosPorts.remove( mnPort )
3128
3129 # NOTE: OVS reports this as down since there is no link
3130 # So ignoring these for now
3131 # TODO: Come up with a better way of handling these
3132 if 65534 in mnPorts:
3133 mnPorts.remove( 65534 )
3134 if long( uint64( -2 ) ) in onosPorts:
3135 onosPorts.remove( long( uint64( -2 ) ) )
3136 if len( mnPorts ): # the ports of this switch don't match
3137 switchResult = main.FALSE
3138 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3139 if len( onosPorts ): # the ports of this switch don't match
3140 switchResult = main.FALSE
3141 main.log.warn(
3142 "Ports in ONOS but not MN: " +
3143 str( onosPorts ) )
3144 if switchResult == main.FALSE:
3145 main.log.error(
3146 "The list of ports for switch %s(%s) does not match:" %
3147 ( name, mnSwitch[ 'dpid' ] ) )
3148 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3149 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3150 portsResults = portsResults and switchResult
3151 finalResults = finalResults and portsResults
3152 return finalResults
3153 except pexpect.EOF:
3154 main.log.error( self.name + ": EOF exception found" )
3155 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003156 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003157 except Exception:
3158 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003159 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003160
Jon Hallafa8a472015-06-12 14:02:42 -07003161 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003162 """
3163 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003164 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003165
Jon Hallafa8a472015-06-12 14:02:42 -07003166 """
Jon Hall7eb38402015-01-08 17:19:54 -08003167 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003168 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003169 try:
3170 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003171
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003172 mnLinks = []
3173 for l in links:
3174 try:
3175 node1 = switches[ l[ 'node1' ] ]
3176 node2 = switches[ l[ 'node2' ] ]
3177 enabled = True
3178 for port in node1[ 'ports' ]:
3179 if port[ 'of_port' ] == l[ 'port1' ]:
3180 enabled = enabled and port[ 'enabled' ]
3181 for port in node2[ 'ports' ]:
3182 if port[ 'of_port' ] == l[ 'port2' ]:
3183 enabled = enabled and port[ 'enabled' ]
3184 if enabled:
3185 mnLinks.append( l )
3186 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003187 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003188 if 2 * len( mnLinks ) == len( onos ):
3189 linkResults = main.TRUE
3190 else:
3191 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003192 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003193 "Mininet has " + str( len( mnLinks ) ) +
3194 " bidirectional links and ONOS has " +
3195 str( len( onos ) ) + " unidirectional links" )
3196
3197 # iterate through MN links and check if an ONOS link exists in
3198 # both directions
3199 for link in mnLinks:
3200 # TODO: Find a more efficient search method
3201 node1 = None
3202 port1 = None
3203 node2 = None
3204 port2 = None
3205 firstDir = main.FALSE
3206 secondDir = main.FALSE
3207 for swName, switch in switches.iteritems():
3208 if swName == link[ 'node1' ]:
3209 node1 = switch[ 'dpid' ]
3210 for port in switch[ 'ports' ]:
3211 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3212 port1 = port[ 'of_port' ]
3213 if node1 is not None and node2 is not None:
3214 break
3215 if swName == link[ 'node2' ]:
3216 node2 = switch[ 'dpid' ]
3217 for port in switch[ 'ports' ]:
3218 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3219 port2 = port[ 'of_port' ]
3220 if node1 is not None and node2 is not None:
3221 break
3222
3223 for onosLink in onos:
3224 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3225 ":", '' ).replace( "of", '' )
3226 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3227 ":", '' ).replace( "of", '' )
3228 onosPort1 = onosLink[ 'src' ][ 'port' ]
3229 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3230
3231 # check onos link from node1 to node2
3232 if str( onosNode1 ) == str( node1 ) and str(
3233 onosNode2 ) == str( node2 ):
3234 if int( onosPort1 ) == int( port1 ) and int(
3235 onosPort2 ) == int( port2 ):
3236 firstDir = main.TRUE
3237 else:
Jon Hallab611372018-02-21 15:26:05 -08003238 # The right switches, but wrong ports, could be
3239 # another link between these devices, or onos
3240 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003241 main.log.warn(
3242 'The port numbers do not match for ' +
3243 str( link ) +
3244 ' between ONOS and MN. When checking ONOS for ' +
3245 'link %s/%s -> %s/%s' %
3246 ( node1, port1, node2, port2 ) +
3247 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003248 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3249 '. This could be another link between these devices' +
3250 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003251
3252 # check onos link from node2 to node1
3253 elif ( str( onosNode1 ) == str( node2 ) and
3254 str( onosNode2 ) == str( node1 ) ):
3255 if ( int( onosPort1 ) == int( port2 )
3256 and int( onosPort2 ) == int( port1 ) ):
3257 secondDir = main.TRUE
3258 else:
Jon Hallab611372018-02-21 15:26:05 -08003259 # The right switches, but wrong ports, could be
3260 # another link between these devices, or onos
3261 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003262 main.log.warn(
3263 'The port numbers do not match for ' +
3264 str( link ) +
3265 ' between ONOS and MN. When checking ONOS for ' +
3266 'link %s/%s -> %s/%s' %
3267 ( node1, port1, node2, port2 ) +
3268 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003269 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3270 '. This could be another link between these devices' +
3271 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003272 else: # this is not the link you're looking for
3273 pass
3274 if not firstDir:
3275 main.log.error(
3276 'ONOS does not have the link %s/%s -> %s/%s' %
3277 ( node1, port1, node2, port2 ) )
3278 if not secondDir:
3279 main.log.error(
3280 'ONOS does not have the link %s/%s -> %s/%s' %
3281 ( node2, port2, node1, port1 ) )
3282 linkResults = linkResults and firstDir and secondDir
3283 return linkResults
3284 except pexpect.EOF:
3285 main.log.error( self.name + ": EOF exception found" )
3286 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003287 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003288 except Exception:
3289 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003290 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003291
Jon Hallafa8a472015-06-12 14:02:42 -07003292 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003293 """
Jon Hallafa8a472015-06-12 14:02:42 -07003294 Compare mn and onos Hosts.
3295 Since Mininet hosts are quiet, ONOS will only know of them when they
3296 speak. For this reason, we will only check that the hosts in ONOS
3297 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003298
Jon Hallafa8a472015-06-12 14:02:42 -07003299 Arguments:
3300 hostsJson: parsed json object from the onos hosts api
3301 Returns:
3302 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003303 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003304 try:
3305 hostResults = main.TRUE
3306 for onosHost in hostsJson:
3307 onosMAC = onosHost[ 'mac' ].lower()
3308 match = False
3309 for mnHost, info in hosts.iteritems():
3310 for mnIntf in info[ 'interfaces' ]:
3311 if onosMAC == mnIntf[ 'mac' ].lower():
3312 match = True
3313 for ip in mnIntf[ 'ips' ]:
3314 if ip in onosHost[ 'ipAddresses' ]:
3315 pass # all is well
3316 else:
3317 # misssing ip
3318 main.log.error( "ONOS host " +
3319 onosHost[ 'id' ] +
3320 " has a different IP(" +
3321 str( onosHost[ 'ipAddresses' ] ) +
3322 ") than the Mininet host(" +
3323 str( ip ) +
3324 ")." )
3325 output = json.dumps(
3326 onosHost,
3327 sort_keys=True,
3328 indent=4,
3329 separators=( ',', ': ' ) )
3330 main.log.info( output )
3331 hostResults = main.FALSE
3332 if not match:
3333 hostResults = main.FALSE
3334 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3335 "corresponding Mininet host." )
3336 output = json.dumps( onosHost,
3337 sort_keys=True,
3338 indent=4,
3339 separators=( ',', ': ' ) )
3340 main.log.info( output )
3341 return hostResults
3342 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003343 main.log.error( self.name + ": EOF exception found" )
3344 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003345 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003346 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003347 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003348 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003349
You Wangd66de192018-04-30 17:30:12 -07003350 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003351 """
3352 Description:
3353 Verify that all hosts have IP address assigned to them
3354 Optional:
3355 hostList: If specified, verifications only happen to the hosts
3356 in hostList
3357 prefix: at least one of the ip address assigned to the host
3358 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003359 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003360 Returns:
3361 main.TRUE if all hosts have specific IP address assigned;
3362 main.FALSE otherwise
3363 """
3364 try:
You Wangd66de192018-04-30 17:30:12 -07003365 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003366 if not hostList:
3367 hostList = hosts.keys()
3368 for hostName in hosts.keys():
3369 if hostName not in hostList:
3370 continue
3371 ipList = []
3372 self.handle.sendline( str( hostName ) + " ip a" )
3373 self.handle.expect( "mininet>" )
3374 ipa = self.handle.before
3375 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3376 ipList += re.findall( ipv4Pattern, ipa )
3377 # It's tricky to make regex for IPv6 addresses and this one is simplified
3378 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})/'
3379 ipList += re.findall( ipv6Pattern, ipa )
3380 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3381 if not ipList:
3382 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3383 else:
3384 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3385 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3386 else:
3387 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3388 hostList.remove( hostName )
3389 return main.FALSE if hostList else main.TRUE
3390 except KeyError:
3391 main.log.exception( self.name + ": host data not as expected: " + hosts )
3392 return None
3393 except pexpect.EOF:
3394 main.log.error( self.name + ": EOF exception found" )
3395 main.log.error( self.name + ": " + self.handle.before )
3396 main.cleanAndExit()
3397 except Exception:
3398 main.log.exception( self.name + ": Uncaught exception" )
3399 return None
3400
Jon Hallafa8a472015-06-12 14:02:42 -07003401 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003402 """
3403 Returns a list of all hosts
3404 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003405 try:
3406 self.handle.sendline( "" )
3407 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003408
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003409 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3410 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003411
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003412 handlePy = self.handle.before
3413 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3414 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003415
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003416 self.handle.sendline( "" )
3417 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003418
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003419 hostStr = handlePy.replace( "]", "" )
3420 hostStr = hostStr.replace( "'", "" )
3421 hostStr = hostStr.replace( "[", "" )
3422 hostStr = hostStr.replace( " ", "" )
3423 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003424
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 return hostList
3426 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003427 main.log.error( self.name + ": TIMEOUT exception found" )
3428 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003429 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003430 except pexpect.EOF:
3431 main.log.error( self.name + ": EOF exception found" )
3432 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003433 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003434 except Exception:
3435 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003436 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003437
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003438 def getSwitch( self ):
3439 """
3440 Returns a list of all switches
3441 Again, don't ask question just use it...
3442 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003443 try:
3444 # get host list...
3445 hostList = self.getHosts()
3446 # Make host set
3447 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003448
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 # Getting all the nodes in mininet
3450 self.handle.sendline( "" )
3451 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003452
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003453 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3454 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003455
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003456 handlePy = self.handle.before
3457 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3458 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003459
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003460 self.handle.sendline( "" )
3461 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003462
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003463 nodesStr = handlePy.replace( "]", "" )
3464 nodesStr = nodesStr.replace( "'", "" )
3465 nodesStr = nodesStr.replace( "[", "" )
3466 nodesStr = nodesStr.replace( " ", "" )
3467 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003468
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003469 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003470 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003471 nodesSet.discard( 'c0' )
3472 nodesSet.discard( 'c1' )
3473 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003474
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003475 switchSet = nodesSet - hostSet
3476 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003477
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003478 return switchList
3479 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003480 main.log.error( self.name + ": TIMEOUT exception found" )
3481 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003482 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 except pexpect.EOF:
3484 main.log.error( self.name + ": EOF exception found" )
3485 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003486 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003487 except Exception:
3488 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003489 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003490
You Wang7d14d642019-01-23 15:10:08 -08003491 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003492 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003493 """
3494 Return a dictionary which describes the latest Mininet topology data as a
3495 graph.
3496 An example of the dictionary:
3497 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3498 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3499 Each vertex should at least have an 'edges' attribute which describes the
3500 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003501 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003502 list of attributes.
3503 An example of the edges dictionary:
3504 'edges': { vertex2: { 'port': ..., 'weight': ... },
3505 vertex3: { 'port': ..., 'weight': ... } }
3506 If useId == True, dpid/mac will be used instead of names to identify
3507 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3508 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003509 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003510 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003511 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3512 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003513 Note that link or switch that are brought down by 'link x x down' or 'switch
3514 x down' commands still show in the output of Mininet CLI commands such as
3515 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3516 recommended to use delLink() or delSwitch functions to simulate link/switch
3517 down, and addLink() or addSwitch to add them back.
3518 """
3519 graphDict = {}
3520 try:
You Wang7d14d642019-01-23 15:10:08 -08003521 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003522 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003523 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003524 if includeHost:
3525 hosts = self.getHosts()
3526 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003527 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003528 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3529 continue
3530 nodeName1 = link[ 'node1' ]
3531 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003532 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3533 # The device is probably offline
3534 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003535 port1 = link[ 'port1' ]
3536 port2 = link[ 'port2' ]
3537 # Loop for two nodes
3538 for i in range( 2 ):
3539 # Get port index from OVS
3540 # The index extracted from port name may be inconsistent with ONOS
3541 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003542 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003543 portList = self.getOVSPorts( nodeName1 )
3544 if len( portList ) == 0:
3545 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3546 return None
3547 portDict[ nodeName1 ] = portList
3548 for port in portDict[ nodeName1 ]:
3549 if port[ 'port' ] == port1:
3550 portIndex = port[ 'index' ]
3551 break
3552 if portIndex == -1:
3553 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3554 return None
3555 if useId:
3556 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3557 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3558 else:
3559 node1 = nodeName1
3560 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003561 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003562 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003563 graphDict[ node1 ] = { 'edges': {},
3564 'dpid': switches[ nodeName1 ][ 'dpid' ],
3565 'name': nodeName1,
3566 'ports': switches[ nodeName1 ][ 'ports' ],
3567 'swClass': switches[ nodeName1 ][ 'swClass' ],
3568 'pid': switches[ nodeName1 ][ 'pid' ],
3569 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003570 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003571 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003572 else:
3573 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003574 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3575 pass
3576 for port in switches[ nodeName1 ][ 'ports' ]:
3577 if port[ 'of_port' ] == str( portIndex ):
3578 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003579 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003580 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3581 else:
3582 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003583 # Swap two nodes/ports
3584 nodeName1, nodeName2 = nodeName2, nodeName1
3585 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003586 # Remove links with disabled ports
3587 linksToRemove = []
3588 for node, edges in graphDict.items():
3589 for neighbor, port in edges[ 'edges' ].items():
3590 if port[ 'port' ] == -1:
3591 linksToRemove.append( ( node, neighbor ) )
3592 for node1, node2 in linksToRemove:
3593 for i in range( 2 ):
3594 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3595 graphDict[ node1 ][ 'edges' ].pop( node2 )
3596 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003597 return graphDict
3598 except KeyError:
3599 main.log.exception( self.name + ": KeyError exception found" )
3600 return None
3601 except AssertionError:
3602 main.log.exception( self.name + ": AssertionError exception found" )
3603 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003604 except pexpect.EOF:
3605 main.log.error( self.name + ": EOF exception found" )
3606 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003607 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003608 except Exception:
3609 main.log.exception( self.name + ": Uncaught exception" )
3610 return None
3611
Devin Lima7cfdbd2017-09-29 15:02:22 -07003612 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003613 """
3614 updates the port address and status information for
3615 each port in mn"""
3616 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003617 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003618 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003619 self.handle.sendline( "" )
3620 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003621
Jon Hall7eb38402015-01-08 17:19:54 -08003622 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003623 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003624
Jon Hall7eb38402015-01-08 17:19:54 -08003625 self.handle.sendline( "" )
3626 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003627
Jon Hallb1290e82014-11-18 16:17:48 -05003628 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003629 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003630 main.log.error( self.name + ": TIMEOUT exception found" )
3631 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003632 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003633 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003634 main.log.error( self.name + ": EOF exception found" )
3635 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003636 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003637 except Exception:
3638 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003639 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003640
Jon Halld80cc142015-07-06 13:36:05 -07003641 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003642 """
3643 Add vlan tag to a host.
3644 Dependencies:
3645 This class depends on the "vlan" package
3646 $ sudo apt-get install vlan
3647 Configuration:
3648 Load the 8021q module into the kernel
3649 $sudo modprobe 8021q
3650
3651 To make this setup permanent:
3652 $ sudo su -c 'echo "8021q" >> /etc/modules'
3653 """
3654 if self.handle:
3655 try:
Jon Halld80cc142015-07-06 13:36:05 -07003656 # get the ip address of the host
3657 main.log.info( "Get the ip address of the host" )
3658 ipaddr = self.getIPAddress( host )
3659 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003660
Jon Halld80cc142015-07-06 13:36:05 -07003661 # remove IP from interface intf
3662 # Ex: h1 ifconfig h1-eth0 inet 0
3663 main.log.info( "Remove IP from interface " )
3664 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3665 self.handle.sendline( cmd2 )
3666 self.handle.expect( "mininet>" )
3667 response = self.handle.before
3668 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003669
Jon Halld80cc142015-07-06 13:36:05 -07003670 # create VLAN interface
3671 # Ex: h1 vconfig add h1-eth0 100
3672 main.log.info( "Create Vlan" )
3673 cmd3 = host + " vconfig add " + intf + " " + vlan
3674 self.handle.sendline( cmd3 )
3675 self.handle.expect( "mininet>" )
3676 response = self.handle.before
3677 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003678
Jon Halld80cc142015-07-06 13:36:05 -07003679 # assign the host's IP to the VLAN interface
3680 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3681 main.log.info( "Assign the host IP to the vlan interface" )
3682 vintf = intf + "." + vlan
3683 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3684 self.handle.sendline( cmd4 )
3685 self.handle.expect( "mininet>" )
3686 response = self.handle.before
3687 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003688
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003689 # update Mininet node variables
3690 main.log.info( "Update Mininet node variables" )
3691 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3692 self.handle.sendline( cmd5 )
3693 self.handle.expect( "mininet>" )
3694 response = self.handle.before
3695 main.log.info( "====> %s ", response )
3696
3697 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3698 self.handle.sendline( cmd6 )
3699 self.handle.expect( "mininet>" )
3700 response = self.handle.before
3701 main.log.info( "====> %s ", response )
3702
3703 return main.TRUE
3704 except pexpect.TIMEOUT:
3705 main.log.error( self.name + ": TIMEOUT exception found" )
3706 main.log.error( self.name + ": " + self.handle.before )
3707 main.cleanAndExit()
3708 except pexpect.EOF:
3709 main.log.error( self.name + ": EOF exception found" )
3710 main.log.error( self.name + ": " + self.handle.before )
3711 return main.FALSE
3712 except Exception:
3713 main.log.exception( self.name + ": Uncaught exception!" )
3714 return main.FALSE
3715
3716 def removeVLAN( self, host, intf ):
3717 """
3718 Remove vlan tag from a host.
3719 Dependencies:
3720 This class depends on the "vlan" package
3721 $ sudo apt-get install vlan
3722 Configuration:
3723 Load the 8021q module into the kernel
3724 $sudo modprobe 8021q
3725
3726 To make this setup permanent:
3727 $ sudo su -c 'echo "8021q" >> /etc/modules'
3728 """
3729 if self.handle:
3730 try:
3731 # get the ip address of the host
3732 main.log.info( "Get the ip address of the host" )
3733 ipaddr = self.getIPAddress( host )
3734
3735 # remove VLAN interface
3736 # Ex: h1 vconfig rem h1-eth0.100
3737 main.log.info( "Remove Vlan interface" )
3738 cmd2 = host + " vconfig rem " + intf
3739 self.handle.sendline( cmd2 )
3740 self.handle.expect( "mininet>" )
3741 response = self.handle.before
3742 main.log.info( "====> %s ", response )
3743
3744 # assign the host's IP to the original interface
3745 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3746 main.log.info( "Assign the host IP to the original interface" )
3747 original_intf = intf.split(".")[0]
3748 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3749 self.handle.sendline( cmd3 )
3750 self.handle.expect( "mininet>" )
3751 response = self.handle.before
3752 main.log.info( "====> %s ", response )
3753
3754 # update Mininet node variables
3755 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3756 self.handle.sendline( cmd4 )
3757 self.handle.expect( "mininet>" )
3758 response = self.handle.before
3759 main.log.info( "====> %s ", response )
3760
3761 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3762 self.handle.sendline( cmd5 )
3763 self.handle.expect( "mininet>" )
3764 response = self.handle.before
3765 main.log.info( "====> %s ", response )
3766
kaouthera3f13ca22015-05-05 15:01:41 -07003767 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003768 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003769 main.log.error( self.name + ": TIMEOUT exception found" )
3770 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003771 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003772 except pexpect.EOF:
3773 main.log.error( self.name + ": EOF exception found" )
3774 main.log.error( self.name + ": " + self.handle.before )
3775 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003776 except Exception:
3777 main.log.exception( self.name + ": Uncaught exception!" )
3778 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003779
Jon Hall892818c2015-10-20 17:58:34 -07003780 def createHostComponent( self, name ):
3781 """
3782 Creates a new mininet cli component with the same parameters as self.
3783 This new component is intended to be used to login to the hosts created
3784 by mininet.
3785
3786 Arguments:
3787 name - The string of the name of this component. The new component
3788 will be assigned to main.<name> .
3789 In addition, main.<name>.name = str( name )
3790 """
3791 try:
3792 # look to see if this component already exists
3793 getattr( main, name )
3794 except AttributeError:
3795 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003796 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3797 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003798 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003799 except pexpect.EOF:
3800 main.log.error( self.name + ": EOF exception found" )
3801 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003802 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003803 except Exception:
3804 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003805 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003806 else:
3807 # namespace is not clear!
3808 main.log.error( name + " component already exists!" )
3809 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003810 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003811
3812 def removeHostComponent( self, name ):
3813 """
3814 Remove host component
3815 Arguments:
3816 name - The string of the name of the component to delete.
3817 """
3818 try:
3819 # Get host component
3820 component = getattr( main, name )
3821 except AttributeError:
3822 main.log.error( "Component " + name + " does not exist." )
3823 return
3824 try:
3825 # Disconnect from component
3826 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003827 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003828 # Delete component
3829 delattr( main, name )
3830 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003831 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003832 except StandardError:
3833 self.log.exception( "Exception while closing log files for " + name )
3834 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003835 except pexpect.EOF:
3836 main.log.error( self.name + ": EOF exception found" )
3837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003838 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003839 except Exception:
3840 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003841 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003842
3843 def startHostCli( self, host=None ):
3844 """
3845 Use the mininet m utility to connect to the host's cli
3846 """
3847 # These are fields that can be used by scapy packets. Initialized to None
3848 self.hostIp = None
3849 self.hostMac = None
3850 try:
3851 if not host:
3852 host = self.name
3853 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003854 self.handle.sendline( "cd" )
3855 self.handle.expect( self.hostPrompt )
3856 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003857 self.handle.expect( self.hostPrompt )
3858 return main.TRUE
3859 except pexpect.TIMEOUT:
3860 main.log.exception( self.name + ": Command timed out" )
3861 return main.FALSE
3862 except pexpect.EOF:
3863 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003865 except Exception:
3866 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003867 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003868
YPZhang801d46d2016-08-08 13:26:28 -07003869 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003870 '''
3871
YPZhang801d46d2016-08-08 13:26:28 -07003872 Args:
3873 devicename: switch name
3874 intf: port name on switch
3875 status: up or down
3876
3877 Returns: boolean to show success change status
3878
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003879 '''
YPZhang801d46d2016-08-08 13:26:28 -07003880 if status == "down" or status == "up":
3881 try:
3882 cmd = devicename + " ifconfig " + intf + " " + status
3883 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003884 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003885 return main.TRUE
3886 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003887 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003888 return main.FALSE
3889 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003890 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003891 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003892 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003893 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003894 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003895 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003896 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003897 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003898 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003899 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003900 return main.FALSE
3901
You Wang6e5b48e2018-07-23 16:17:38 -07003902 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003903 """
You Wang6e5b48e2018-07-23 16:17:38 -07003904 Moves a host from one switch to another on the fly
3905 Optional:
3906 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3907 prefixLen: length of the host IP prefix
3908 ipv6: move an IPv6 host if True
3909 intfSuffix: suffix of the new interface after host movement
3910 vlan: vlan ID of the host. Use None for non-vlan host
3911 Note: The intf between host and oldSw when detached
3912 using detach(), will still show up in the 'net'
3913 cmd, because switch.detach() doesn't affect switch.intfs[]
3914 ( which is correct behavior since the interfaces
3915 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003916 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003917 if self.handle:
3918 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003919 newIntf = "%s-%s" % ( host, intfSuffix )
3920 commands = [
3921 # Bring link between oldSw-host down
3922 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3923 # Determine hostintf and Oldswitchintf
3924 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3925 ]
3926 # Determine ip address of the host-oldSw interface
3927 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3928 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3929 commands += [
3930 # Determine mac address of the host-oldSw interface
3931 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3932 # Detach interface between oldSw-host
3933 "px " + oldSw + ".detach( sintf )",
3934 # Add link between host-newSw
3935 "py net.addLink(" + host + "," + newSw + ")",
3936 # Determine hostintf and Newswitchintf
3937 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3938 # Attach interface between newSw-host
3939 "px " + newSw + ".attach( sintf )",
3940 ]
3941 if vlan:
3942 vlanIntf = "%s.%s" % ( newIntf, vlan )
3943 commands += [
3944 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3945 host + " ip link set up %s" % vlanIntf,
3946 "px hintf.name = '" + vlanIntf + "'",
3947 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3948 ]
3949 newIntf = vlanIntf
3950 commands += [
3951 # Set mac address of the host-newSw interface
3952 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3953 # Set IP address of the host-newSw interface
3954 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3955 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3956 ]
3957 if ipv6:
3958 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3959 commands += [
3960 "net",
3961 host + " ifconfig"
3962 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003963 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003964 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003965 self.handle.sendline( cmd )
3966 self.handle.expect( "mininet>" )
3967 main.log.info( "====> %s ", self.handle.before )
3968 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003969 except pexpect.TIMEOUT:
3970 main.log.error( self.name + ": TIMEOUT exception found" )
3971 main.log.error( self.name + ": " + self.handle.before )
3972 main.cleanAndExit()
3973 except pexpect.EOF:
3974 main.log.error( self.name + ": EOF exception found" )
3975 main.log.error( self.name + ": " + self.handle.before )
3976 return main.FALSE
3977 except Exception:
3978 main.log.exception( self.name + ": Uncaught exception!" )
3979 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003980
You Wang6e5b48e2018-07-23 16:17:38 -07003981 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3982 macAddr=None, prefixLen=None, ipv6=False,
3983 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003984 """
You Wang6e5b48e2018-07-23 16:17:38 -07003985 Moves a dual-homed host from one switch-pair to another pair on the fly
3986 Optional:
3987 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3988 prefixLen: length of the host IP prefix
3989 ipv6: move an IPv6 host if True
3990 intfSuffix1: suffix of the first new interface
3991 intfSuffix2: suffix of the second new interface
3992 bondSuffix: suffix of the new bond interface
3993 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003994 """
You Wang7ea90582018-07-19 15:27:58 -07003995 if self.handle:
3996 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003997 bondIntf = "%s-%s" % ( host, bondSuffix )
3998 newIntf = "%s-%s" % ( host, intfSuffix1 )
3999 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07004000 commands = [
4001 # Bring link between oldSw-host down
4002 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4003 # Bring link between oldPairSw-host down
4004 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4005 # Determine hostintf and Oldswitchintf
4006 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07004007 ]
4008 # Determine ip address of the host-oldSw interface
4009 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4010 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4011 commands += [
4012 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07004013 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4014 # Detach interface between oldSw-host
4015 "px " + oldSw + ".detach( sintf )",
4016 # Determine hostintf and Oldpairswitchintf
4017 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4018 # Detach interface between oldPairSw-host
4019 "px " + oldPairSw + ".detach( sintfpair )",
4020 # Add link between host-newSw
4021 "py net.addLink(" + host + "," + newSw + ", 2)",
4022 # Add link between host-newPairSw
4023 "py net.addLink(" + host + "," + newPairSw + ")",
4024 # Determine hostintf and Newswitchintf
4025 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4026 # Determine hostintf and NewPairswitchintf
4027 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4028 # Attach interface between newSw-host
4029 "px " + newSw + ".attach( sintf )",
4030 # Attach interface between newPairSw-host
4031 "px " + newPairSw + ".attach( sintfpair )",
4032 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004033 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004034 host + ' ip link set %s down' % newIntf,
4035 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004036 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4037 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004038 host + ' ip addr flush dev %s' % newIntf,
4039 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004040 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004041 "px lowestIntf = min( [ hintf, hintfpair ] )",
4042 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004043 "px lowestIntf.name = '" + bondIntf + "'",
4044 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004045 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4046 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004047 ]
4048 if vlan:
4049 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4050 commands += [
4051 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4052 host + " ip link set up %s" % vlanIntf,
4053 "px lowestIntf.name = '" + vlanIntf + "'",
4054 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4055 ]
4056 bondIntf = vlanIntf
4057 commands += [
4058 # Set macaddress of the host-newSw interface
4059 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004060 # Set ipaddress of the host-newSw interface
4061 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4062 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004063 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004064 if ipv6:
4065 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4066 commands += [
4067 "net",
4068 host + " ifconfig"
4069 ]
You Wang7ea90582018-07-19 15:27:58 -07004070 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004071 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004072 self.handle.sendline( cmd )
4073 self.handle.expect( "mininet>" )
4074 main.log.info( "====> %s ", self.handle.before )
4075 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004076 except pexpect.TIMEOUT:
4077 main.log.error( self.name + ": TIMEOUT exception found" )
4078 main.log.error( self.name + ": " + self.handle.before )
4079 main.cleanAndExit()
4080 except pexpect.EOF:
4081 main.log.error( self.name + ": EOF exception found" )
4082 main.log.error( self.name + ": " + self.handle.before )
4083 return main.FALSE
4084 except Exception:
4085 main.log.exception( self.name + ": Uncaught exception!" )
4086 return main.FALSE
4087
adminbae64d82013-08-01 10:50:15 -07004088if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004089 sys.modules[ __name__ ] = MininetCliDriver()