blob: 75417804176f4bb1ae7a578eea573bf96e039d4f [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()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700601 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700605 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
606 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
607 else:
608 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
609 discoveryResult = main.FALSE
610 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700611 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700612 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700613 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700615 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700616 except pexpect.TIMEOUT:
617 main.log.exception( self.name + ": TIMEOUT exception" )
618 response = self.handle.before
619 # NOTE: Send ctrl-c to make sure command is stopped
620 self.handle.send( "\x03" )
621 self.handle.expect( "Interrupt" )
622 response += self.handle.before + self.handle.after
623 self.handle.expect( "mininet>" )
624 response += self.handle.before + self.handle.after
625 main.log.debug( response )
626 return main.FALSE
627 except pexpect.EOF:
628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
630 main.cleanAndExit()
631 except Exception:
632 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800633 main.cleanAndExit()
634
635 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
636 """
637 Verify ping from each host in srcList to each host in dstList
638
639 acceptableFailed: max number of acceptable failed pings
640
641 Returns main.TRUE if all src hosts can reach all dst hosts
642 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
643 """
644 try:
645 main.log.info( "Verifying ping from each src host to each dst host" )
646 isReachable = main.TRUE
647 wait = int( wait )
648 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
649 pingResponse = "Ping output:\n"
650 failedPingsTotal = 0
651 for host in srcList:
652 pingResponse += str( str( host ) + " -> " )
653 for temp in dstList:
654 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700655 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
656 assert dstIP, "Not able to get IP address of host {}".format( temp )
657 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800658 while failedPings <= acceptableFailed:
659 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
660 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700661 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800662 response = self.handle.before
663 if re.search( ',\s0\%\spacket\sloss', response ):
664 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800665 break
666 else:
667 failedPings += 1
668 time.sleep(1)
669 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700670 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800671 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800673 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700674 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800675 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700676 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700677 except AssertionError:
678 main.log.exception( "" )
679 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700680 except pexpect.TIMEOUT:
681 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 response = self.handle.before
683 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700684 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800685 self.handle.expect( "Interrupt" )
686 response += self.handle.before + self.handle.after
687 self.handle.expect( "mininet>" )
688 response += self.handle.before + self.handle.after
689 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 except pexpect.EOF:
692 main.log.error( self.name + ": EOF exception found" )
693 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700697 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700698
Jon Hall7eb38402015-01-08 17:19:54 -0800699 def pingHost( self, **pingParams ):
700 """
Jon Hall3b489db2015-10-05 14:38:37 -0700701 Ping from one mininet host to another
702 Currently the only supported Params: SRC, TARGET, and WAIT
703 """
704 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700705 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700706 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800707 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700708 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700709 try:
Jon Hall61282e32015-03-19 11:34:11 -0700710 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800711 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700712 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700713 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700714 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.error(
716 self.name +
717 ": timeout when waiting for response from mininet" )
718 main.log.error( "response: " + str( self.handle.before ) )
719 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error(
722 self.name +
723 ": timeout when waiting for response from mininet" )
724 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 if re.search( ',\s0\%\spacket\sloss', response ):
727 main.log.info( self.name + ": no packets lost, host is reachable" )
728 return main.TRUE
729 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800730 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 self.name +
732 ": PACKET LOST, HOST IS NOT REACHABLE" )
733 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738 except Exception:
739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700741
742 def ping6pair( self, **pingParams ):
743 """
GlennRC2cf7d952015-09-11 16:32:13 -0700744 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700745 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700747 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
748 """
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700750 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700751 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530752 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700753 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 try:
755 main.log.info( "Sending: " + command )
756 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700757 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700758 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 if i == 1:
760 main.log.error(
761 self.name +
762 ": timeout when waiting for response from mininet" )
763 main.log.error( "response: " + str( self.handle.before ) )
764 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
765 if i == 1:
766 main.log.error(
767 self.name +
768 ": timeout when waiting for response from mininet" )
769 main.log.error( "response: " + str( self.handle.before ) )
770 response = self.handle.before
771 main.log.info( self.name + ": Ping Response: " + response )
772 if re.search( ',\s0\%\spacket\sloss', response ):
773 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700774 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 else:
alisone4121a92016-11-22 16:31:36 -0800776 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 self.name +
778 ": PACKET LOST, HOST IS NOT REACHABLE" )
779 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 except pexpect.EOF:
781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700784 except Exception:
785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800787
You Wangdb927a52016-02-26 11:03:28 -0800788 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
789 """
790 Description:
791 Ping a set of destination host from host CLI.
792 Logging into a Mininet host CLI is required before calling this funtion.
793 Params:
794 dstIPList is a list of destination ip addresses
795 Returns:
796 main.TRUE if the destination host is reachable
797 main.FALSE otherwise
798 """
799 isReachable = main.TRUE
800 wait = int( wait )
801 cmd = "ping"
802 if IPv6:
803 cmd = cmd + "6"
804 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
805 try:
806 for dstIP in dstIPList:
807 pingCmd = cmd + " " + dstIP
808 self.handle.sendline( pingCmd )
809 i = self.handle.expect( [ self.hostPrompt,
810 '\*\*\* Unknown command: ' + pingCmd,
811 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700812 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700813 # For some reason we need to send something
814 # Otherwise ping results won't be read by handle
815 self.handle.sendline( "" )
816 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800817 if i == 0:
818 response = self.handle.before
819 if not re.search( ',\s0\%\spacket\sloss', response ):
820 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
821 isReachable = main.FALSE
822 elif i == 1:
823 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800825 elif i == 2:
826 main.log.error( self.name + ": timeout when waiting for response" )
827 isReachable = main.FALSE
828 else:
829 main.log.error( self.name + ": unknown response: " + self.handle.before )
830 isReachable = main.FALSE
831 except pexpect.TIMEOUT:
832 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangb65d2372018-08-17 15:37:59 -0700833 self.exitFromCmd( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800834 isReachable = main.FALSE
835 except pexpect.EOF:
836 main.log.error( self.name + ": EOF exception found" )
837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700838 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800839 except Exception:
840 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700841 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800842 return isReachable
843
Jon Hall7eb38402015-01-08 17:19:54 -0800844 def checkIP( self, host ):
845 """
846 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700847 try:
848 if self.handle:
849 try:
850 response = self.execute(
851 cmd=host +
852 " ifconfig",
853 prompt="mininet>",
854 timeout=10 )
855 except pexpect.EOF:
856 main.log.error( self.name + ": EOF exception found" )
857 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700858 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700859
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700860 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
861 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
862 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
863 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
864 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
865 "[0-9]|25[0-5]|[0-9]{1,2})"
866 # pattern = "inet addr:10.0.0.6"
867 if re.search( pattern, response ):
868 main.log.info( self.name + ": Host Ip configured properly" )
869 return main.TRUE
870 else:
871 main.log.error( self.name + ": Host IP not found" )
872 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700873 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700874 main.log.error( self.name + ": Connection failed to the host" )
875 except Exception:
876 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700877 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800878
Jon Hall7eb38402015-01-08 17:19:54 -0800879 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800880 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700881 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 response = self.execute(
883 cmd="h1 /usr/sbin/sshd -D&",
884 prompt="mininet>",
885 timeout=10 )
886 response = self.execute(
887 cmd="h4 /usr/sbin/sshd -D&",
888 prompt="mininet>",
889 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700890 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 vars( self )[ key ] = connectargs[ key ]
892 response = self.execute(
893 cmd="xterm h1 h4 ",
894 prompt="mininet>",
895 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800896 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800897 main.log.error( self.name + ": EOF exception found" )
898 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700899 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700900 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800901 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700902 if self.flag == 0:
903 self.flag = 1
904 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800905 else:
adminbae64d82013-08-01 10:50:15 -0700906 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800907
Jon Hall7eb38402015-01-08 17:19:54 -0800908 def changeIP( self, host, intf, newIP, newNetmask ):
909 """
910 Changes the ip address of a host on the fly
911 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800912 if self.handle:
913 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 cmd = host + " ifconfig " + intf + " " + \
915 newIP + " " + 'netmask' + " " + newNetmask
916 self.handle.sendline( cmd )
917 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800918 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800919 main.log.info( "response = " + response )
920 main.log.info(
921 "Ip of host " +
922 host +
923 " changed to new IP " +
924 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800925 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700926 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700927 main.log.error( self.name + ": TIMEOUT exception found" )
928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700929 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800931 main.log.error( self.name + ": EOF exception found" )
932 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800933 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700934 except Exception:
935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700936 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800937
Jon Hall7eb38402015-01-08 17:19:54 -0800938 def changeDefaultGateway( self, host, newGW ):
939 """
940 Changes the default gateway of a host
941 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800942 if self.handle:
943 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 cmd = host + " route add default gw " + newGW
945 self.handle.sendline( cmd )
946 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800947 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800948 main.log.info( "response = " + response )
949 main.log.info(
950 "Default gateway of host " +
951 host +
952 " changed to " +
953 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800954 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700955 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700956 main.log.error( self.name + ": TIMEOUT exception found" )
957 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700958 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800960 main.log.error( self.name + ": EOF exception found" )
961 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800962 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700963 except Exception:
964 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700965 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800966
You Wange24d6272018-03-27 21:18:50 -0700967 def addRoute( self, host, dstIP, interface, ipv6=False ):
968 """
969 Add a route to host
970 Ex: h1 route add -host 224.2.0.1 h1-eth0
971 """
972 if self.handle:
973 try:
974 cmd = str( host )
975 if ipv6:
976 cmd += " route -A inet6 add "
977 else:
978 cmd += " route add -host "
979 cmd += str( dstIP ) + " " + str( interface )
980 self.handle.sendline( cmd )
981 self.handle.expect( "mininet>" )
982 response = self.handle.before
983 main.log.debug( "response = " + response )
984 return main.TRUE
985 except pexpect.TIMEOUT:
986 main.log.error( self.name + ": TIMEOUT exception found" )
987 main.log.error( self.name + ": " + self.handle.before )
988 main.cleanAndExit()
989 except pexpect.EOF:
990 main.log.error( self.name + ": EOF exception found" )
991 main.log.error( self.name + ": " + self.handle.before )
992 return main.FALSE
993 except Exception:
994 main.log.exception( self.name + ": Uncaught exception!" )
995 main.cleanAndExit()
996
Jon Hall7eb38402015-01-08 17:19:54 -0800997 def addStaticMACAddress( self, host, GW, macaddr ):
998 """
Jon Hallefbd9792015-03-05 16:11:36 -0800999 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001000 if self.handle:
1001 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001002 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1003 cmd = host + " arp -s " + GW + " " + macaddr
1004 self.handle.sendline( cmd )
1005 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001006 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001007 main.log.info( "response = " + response )
1008 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001009 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001010 GW +
1011 " changed to " +
1012 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001013 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001014 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001015 main.log.error( self.name + ": TIMEOUT exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001017 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001018 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001019 main.log.error( self.name + ": EOF exception found" )
1020 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001021 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001022 except Exception:
1023 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001024 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001025
Jon Hall7eb38402015-01-08 17:19:54 -08001026 def verifyStaticGWandMAC( self, host ):
1027 """
1028 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001029 if self.handle:
1030 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001031 # h1 arp -an
1032 cmd = host + " arp -an "
1033 self.handle.sendline( cmd )
1034 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001035 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001036 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001037 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001038 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001039 main.log.error( self.name + ": TIMEOUT exception found" )
1040 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001041 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001042 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001043 main.log.error( self.name + ": EOF exception found" )
1044 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001045 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001046 except Exception:
1047 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001048 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001049
Jon Hall7eb38402015-01-08 17:19:54 -08001050 def getMacAddress( self, host ):
1051 """
1052 Verifies the host's ip configured or not."""
1053 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001054 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001055 response = self.execute(
1056 cmd=host +
1057 " ifconfig",
1058 prompt="mininet>",
1059 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001063 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001064 except Exception:
1065 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001066 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001067
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001068 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001069 macAddressSearch = re.search( pattern, response, re.I )
1070 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001071 main.log.info(
1072 self.name +
1073 ": Mac-Address of Host " +
1074 host +
1075 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 macAddress )
1077 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001078 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001079 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001080
Jon Hall7eb38402015-01-08 17:19:54 -08001081 def getInterfaceMACAddress( self, host, interface ):
1082 """
1083 Return the IP address of the interface on the given host"""
1084 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001085 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001086 response = self.execute( cmd=host + " ifconfig " + interface,
1087 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001088 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001089 main.log.error( self.name + ": EOF exception found" )
1090 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001091 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001092 except Exception:
1093 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001094 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001095
1096 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 macAddressSearch = re.search( pattern, response, re.I )
1098 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001099 main.log.info( "No mac address found in %s" % response )
1100 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001101 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001102 main.log.info(
1103 "Mac-Address of " +
1104 host +
1105 ":" +
1106 interface +
1107 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 macAddress )
1109 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001110 else:
1111 main.log.error( "Connection failed to the host" )
1112
You Wang5da39c82018-04-26 22:55:08 -07001113 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001114 """
1115 Verifies the host's ip configured or not."""
1116 if self.handle:
1117 try:
1118 response = self.execute(
1119 cmd=host +
1120 " ifconfig",
1121 prompt="mininet>",
1122 timeout=10 )
1123 except pexpect.EOF:
1124 main.log.error( self.name + ": EOF exception found" )
1125 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001126 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001127 except Exception:
1128 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001129 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001130
sathishmad953462015-12-03 17:42:07 +05301131 pattern = ''
1132 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001133 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301134 else:
Jon Hall439c8912016-04-15 02:22:03 -07001135 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001136 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001137 if not ipAddressSearch:
1138 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001139 main.log.info(
1140 self.name +
1141 ": IP-Address of Host " +
1142 host +
1143 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001144 ipAddressSearch.group( 1 ) )
1145 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001146 else:
1147 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001148
Jon Hall7eb38402015-01-08 17:19:54 -08001149 def getSwitchDPID( self, switch ):
1150 """
1151 return the datapath ID of the switch"""
1152 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001153 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001154 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001155 response = self.execute(
1156 cmd=cmd,
1157 prompt="mininet>",
1158 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001159 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001160 main.log.error( self.name + ": EOF exception found" )
1161 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001162 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001163 except Exception:
1164 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001165 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001166 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001167 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001168 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001169 main.log.info(
1170 "Couldn't find DPID for switch %s, found: %s" %
1171 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001173 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001174 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176
Jon Hall7eb38402015-01-08 17:19:54 -08001177 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001178 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001179 self.handle.sendline( "" )
1180 self.expect( "mininet>" )
1181 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001182 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001183 response = self.execute(
1184 cmd=cmd,
1185 prompt="mininet>",
1186 timeout=10 )
1187 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001188 response = self.handle.before
1189 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001190 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001191 main.log.error( self.name + ": TIMEOUT exception found" )
1192 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001193 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001194 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001195 main.log.error( self.name + ": EOF exception found" )
1196 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001197 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001198 except Exception:
1199 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001200 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001201
Jon Hall7eb38402015-01-08 17:19:54 -08001202 def getInterfaces( self, node ):
1203 """
1204 return information dict about interfaces connected to the node"""
1205 if self.handle:
1206 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001207 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001208 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001209 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 response = self.execute(
1211 cmd=cmd,
1212 prompt="mininet>",
1213 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001214 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001215 main.log.error( self.name + ": EOF exception found" )
1216 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001217 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001218 except Exception:
1219 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001221 return response
1222 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001223 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001224
Jon Hall7eb38402015-01-08 17:19:54 -08001225 def dump( self ):
1226 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001227 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001228 response = self.execute(
1229 cmd='dump',
1230 prompt='mininet>',
1231 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001232 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001233 main.log.error( self.name + ": EOF exception found" )
1234 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001235 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001236 except Exception:
1237 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001238 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001239 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001240
Jon Hall7eb38402015-01-08 17:19:54 -08001241 def intfs( self ):
1242 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001243 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001244 response = self.execute(
1245 cmd='intfs',
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()
Jon Hall668ed802014-04-08 17:17:59 -07001255 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001256
Jon Hall7eb38402015-01-08 17:19:54 -08001257 def net( self ):
1258 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001259 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001260 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001261 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 main.log.error( self.name + ": EOF exception found" )
1263 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001264 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001265 except Exception:
1266 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001267 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001268 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001269
Devin Lima7cfdbd2017-09-29 15:02:22 -07001270 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001271 main.log.info( self.name + ": List network links" )
1272 try:
1273 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001274 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001275 except pexpect.EOF:
1276 main.log.error( self.name + ": EOF exception found" )
1277 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001278 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001279 except Exception:
1280 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001281 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001282 return response
1283
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001284 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001285 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001286 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001287
kelvin-onlab7cce9382015-07-17 10:21:03 -07001288 @parm:
1289 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1290 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001291 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001292 try:
1293 for host1 in hosts:
1294 for host2 in hosts:
1295 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001296 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1297 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001298 except Exception:
1299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001300 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001301
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001302 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001303 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001304 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1305 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001306
kelvin-onlab7cce9382015-07-17 10:21:03 -07001307 @parm:
1308 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1309 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001310 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001311 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1312 try:
1313 # Setup the mininet command
1314 cmd1 = 'iperf ' + host1 + " " + host2
1315 self.handle.sendline( cmd1 )
1316 outcome = self.handle.expect( "mininet>", timeout )
1317 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001318
kelvin-onlab7cce9382015-07-17 10:21:03 -07001319 # checks if there are results in the mininet response
1320 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001321 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001322 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001323 response = response.split( "\r\n" )
1324 response = response[ len( response )-2 ]
1325 response = response.split( ": " )
1326 response = response[ len( response )-1 ]
1327 response = response.replace( "[", "" )
1328 response = response.replace( "]", "" )
1329 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001330
kelvin-onlab7cce9382015-07-17 10:21:03 -07001331 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001332 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001333
kelvin-onlab7cce9382015-07-17 10:21:03 -07001334 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001335 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001336 if len( bandwidth ) == 2:
1337 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001338 return main.TRUE
1339 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001340 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001342 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001343 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001344 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001345 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001346 main.log.error( self.name + ": TIMEOUT exception found" )
1347 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001348 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001349 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001350 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001351 self.handle.expect( "Interrupt" )
1352 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001353 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001354 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001355 main.log.error( self.name + ": EOF exception found" )
1356 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001357 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001358 except Exception:
1359 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001361
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001362 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001363 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1364 try:
1365 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001366 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001367 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 outcome1 = self.handle.expect( "mininet>" )
1369 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001370 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001371 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001372 response1 = self.handle.before
1373 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 print response1, response2
1375 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001376 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001378 return main.TRUE
1379 else:
1380 main.log.error( self.name + ": iperf test failed" )
1381 return main.FALSE
1382 except pexpect.TIMEOUT:
1383 main.log.error( self.name + ": TIMEOUT exception found" )
1384 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001385 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001386 self.handle.expect( "Interrupt" )
1387 self.handle.expect( "mininet>" )
1388 return main.FALSE
1389 except pexpect.EOF:
1390 main.log.error( self.name + ": EOF exception found" )
1391 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001392 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001393 except Exception:
1394 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001395 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001396
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001397 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001398 '''
GlennRC61321f22015-07-16 13:36:54 -07001399 Runs the iperfudp function with a given set of hosts and specified
1400 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001401
GlennRC61321f22015-07-16 13:36:54 -07001402 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001403 bandwidth: the targeted bandwidth, in megabits ('M')
1404 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001405 try:
1406 for host1 in hosts:
1407 for host2 in hosts:
1408 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001409 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1410 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001411 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001412 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001413 return main.FALSE
1414 except Exception:
1415 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001416 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001417
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001419 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001420 Creates an iperf UDP test with a specific bandwidth.
1421 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001422
kelvin-onlab7cce9382015-07-17 10:21:03 -07001423 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001424 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1425 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001426 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001427 try:
1428 # setup the mininet command
1429 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001430 self.handle.sendline( cmd )
1431 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001432 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001433
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 # check if there are in results in the mininet response
1435 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001436 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001437 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001438 response = response.split( "\r\n" )
1439 response = response[ len( response )-2 ]
1440 response = response.split( ": " )
1441 response = response[ len( response )-1 ]
1442 response = response.replace( "[", "" )
1443 response = response.replace( "]", "" )
1444 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001445
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001447
kelvin-onlab7cce9382015-07-17 10:21:03 -07001448 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001449 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001450 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 # if one entry is blank then something is wrong
1452 for item in mnBandwidth:
1453 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001454 main.log.error( self.name + ": Could not parse iperf output" )
1455 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001456 return main.FALSE
1457 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001458 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001459 return main.TRUE
1460 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001463
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001464 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001465 main.log.error( self.name + ": TIMEOUT exception found" )
1466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001467 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 except pexpect.EOF:
1469 main.log.error( self.name + ": EOF exception found" )
1470 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001471 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001472 except Exception:
1473 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001474 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001475
Jon Hall7eb38402015-01-08 17:19:54 -08001476 def nodes( self ):
1477 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001478 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 response = self.execute(
1480 cmd='nodes',
1481 prompt='mininet>',
1482 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001483 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error( self.name + ": EOF exception found" )
1485 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001486 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001487 except Exception:
1488 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001489 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001490 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001491
Jon Hall7eb38402015-01-08 17:19:54 -08001492 def pingpair( self ):
1493 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001494 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 response = self.execute(
1496 cmd='pingpair',
1497 prompt='mininet>',
1498 timeout=20 )
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 Hallfbc828e2015-01-06 17:30:19 -08001506
Jon Hall7eb38402015-01-08 17:19:54 -08001507 if re.search( ',\s0\%\spacket\sloss', response ):
1508 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001509 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001510 else:
alisone4121a92016-11-22 16:31:36 -08001511 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001512 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001513
Jon Hall7eb38402015-01-08 17:19:54 -08001514 def link( self, **linkargs ):
1515 """
GlennRCed771242016-01-13 17:02:47 -08001516 Bring link( s ) between two nodes up or down
1517 """
Jon Hall6094a362014-04-11 14:46:56 -07001518 try:
GlennRCed771242016-01-13 17:02:47 -08001519 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1520 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1521 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1522 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1523
1524 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1525 cmd = "link {} {} {}".format( end1, end2, option )
1526 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001527 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001528 response = self.handle.before
1529 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001530 if "not in network" in response:
1531 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1532 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001533 return main.TRUE
1534 except pexpect.TIMEOUT:
1535 main.log.exception( self.name + ": Command timed out" )
1536 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001537 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001538 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001539 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001540 except Exception:
1541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001542 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001543
pingping-lin8244a3b2015-09-16 13:36:56 -07001544 def switch( self, **switchargs ):
1545 """
1546 start/stop a switch
1547 """
1548 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1549 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1550 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1551 command = "switch " + str( sw ) + " " + str( option )
1552 main.log.info( command )
1553 try:
1554 self.handle.sendline( command )
1555 self.handle.expect( "mininet>" )
1556 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001557 main.log.error( self.name + ": TIMEOUT exception found" )
1558 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001559 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001560 except pexpect.EOF:
1561 main.log.error( self.name + ": EOF exception found" )
1562 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001563 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001564 return main.TRUE
1565
pingping-lin5bb663b2015-09-24 11:47:50 -07001566 def node( self, nodeName, commandStr ):
1567 """
1568 Carry out a command line on a given node
1569 @parm:
1570 nodeName: the node name in Mininet testbed
1571 commandStr: the command line will be carried out on the node
1572 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1573 """
1574 command = str( nodeName ) + " " + str( commandStr )
1575 main.log.info( command )
1576
1577 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001578 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001579 if re.search( "Unknown command", response ):
1580 main.log.warn( response )
1581 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001582 if re.search( "Permission denied", response ):
1583 main.log.warn( response )
1584 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001585 except pexpect.EOF:
1586 main.log.error( self.name + ": EOF exception found" )
1587 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001588 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001589 main.log.info( " response is :" )
1590 main.log.info( response )
1591 return response
1592
Jon Hall7eb38402015-01-08 17:19:54 -08001593 def yank( self, **yankargs ):
1594 """
1595 yank a mininet switch interface to a host"""
1596 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001597 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001598 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1599 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001600 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001601 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 response = self.execute(
1603 cmd=command,
1604 prompt="mininet>",
1605 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001606 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001607 main.log.error( self.name + ": EOF exception found" )
1608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001610 except Exception:
1611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001613 return main.TRUE
1614
Jon Hall7eb38402015-01-08 17:19:54 -08001615 def plug( self, **plugargs ):
1616 """
1617 plug the yanked mininet switch interface to a switch"""
1618 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001619 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001620 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1621 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001622 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001623 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001624 response = self.execute(
1625 cmd=command,
1626 prompt="mininet>",
1627 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001628 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001629 main.log.error( self.name + ": EOF exception found" )
1630 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001631 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001632 except Exception:
1633 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001634 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001635 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001636
Jon Hall7eb38402015-01-08 17:19:54 -08001637 def dpctl( self, **dpctlargs ):
1638 """
1639 Run dpctl command on all switches."""
1640 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001641 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001642 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1643 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1644 command = "dpctl " + cmd + " " + str( cmdargs )
1645 try:
1646 response = self.execute(
1647 cmd=command,
1648 prompt="mininet>",
1649 timeout=10 )
1650 except pexpect.EOF:
1651 main.log.error( self.name + ": EOF exception found" )
1652 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001653 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001654 except Exception:
1655 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001656 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001657 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001658
kelvin-onlabd3b64892015-01-20 13:26:24 -08001659 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001660 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001661 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001662 try:
1663 fileInput = path + '/lib/Mininet/INSTALL'
1664 version = super( Mininet, self ).getVersion()
1665 pattern = 'Mininet\s\w\.\w\.\w\w*'
1666 for line in open( fileInput, 'r' ).readlines():
1667 result = re.match( pattern, line )
1668 if result:
1669 version = result.group( 0 )
1670 return version
1671 except Exception:
1672 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001673 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001674
kelvin-onlabd3b64892015-01-20 13:26:24 -08001675 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001676 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001677 Parameters:
1678 sw: The name of an OVS switch. Example "s1"
1679 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 The output of the command from the mininet cli
1681 or main.FALSE on timeout"""
1682 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001683 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001684 response = self.execute(
1685 cmd=command,
1686 prompt="mininet>",
1687 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001688 if response:
Jon Hallab611372018-02-21 15:26:05 -08001689 if "no bridge named" in response:
1690 main.log.error( self.name + ": Error in getSwController: " +
1691 self.handle.before )
1692 return main.FALSE
1693 else:
1694 return response
admin2a9548d2014-06-17 14:08:07 -07001695 else:
1696 return main.FALSE
1697 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001698 main.log.error( self.name + ": EOF exception found" )
1699 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001700 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001701 except Exception:
1702 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001704
Charles Chan029be652015-08-24 01:46:10 +08001705 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001706 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001707 Description:
1708 Assign switches to the controllers ( for ovs use only )
1709 Required:
1710 sw - Name of the switch. This can be a list or a string.
1711 ip - Ip addresses of controllers. This can be a list or a string.
1712 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001713 port - ONOS use port 6653, if no list of ports is passed, then
1714 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001715 ptcp - ptcp number, This can be a string or a list that has
1716 the same length as switch. This is optional and not required
1717 when using ovs switches.
1718 NOTE: If switches and ptcp are given in a list type they should have the
1719 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1720 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001721
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001722 Return:
1723 Returns main.TRUE if mininet correctly assigned switches to
1724 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001725 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001726 """
1727 assignResult = main.TRUE
1728 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001729 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001730 command = "sh ovs-vsctl set-controller "
1731 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 try:
1733 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001734 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001735 if isinstance( port, types.StringType ) or \
1736 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001737 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001738 elif isinstance( port, types.ListType ):
1739 main.log.error( self.name + ": Only one controller " +
1740 "assigned and a list of ports has" +
1741 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001742 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001743 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001744 main.log.error( self.name + ": Invalid controller port " +
1745 "number. Please specify correct " +
1746 "controller port" )
1747 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001748
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001749 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001750 if isinstance( port, types.StringType ) or \
1751 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001752 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001753 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1754 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 elif isinstance( port, types.ListType ):
1756 if ( len( ip ) != len( port ) ):
1757 main.log.error( self.name + ": Port list = " +
1758 str( len( port ) ) +
1759 "should be the same as controller" +
1760 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001761 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001762 else:
1763 onosIp = ""
1764 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001765 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1766 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001767 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001768 main.log.error( self.name + ": Invalid controller port " +
1769 "number. Please specify correct " +
1770 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001771 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001772 else:
1773 main.log.error( self.name + ": Invalid ip address" )
1774 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001775
1776 if isinstance( sw, types.StringType ):
1777 command += sw + " "
1778 if ptcp:
1779 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001780 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001781 elif isinstance( ptcp, types.ListType ):
1782 main.log.error( self.name + ": Only one switch is " +
1783 "being set and multiple PTCP is " +
1784 "being passed " )
1785 else:
1786 main.log.error( self.name + ": Invalid PTCP" )
1787 ptcp = ""
1788 command += onosIp
1789 commandList.append( command )
1790
1791 elif isinstance( sw, types.ListType ):
1792 if ptcp:
1793 if isinstance( ptcp, types.ListType ):
1794 if len( ptcp ) != len( sw ):
1795 main.log.error( self.name + ": PTCP length = " +
1796 str( len( ptcp ) ) +
1797 " is not the same as switch" +
1798 " length = " +
1799 str( len( sw ) ) )
1800 return main.FALSE
1801 else:
1802 for switch, ptcpNum in zip( sw, ptcp ):
1803 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001804 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001805 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001806 tempCmd += onosIp
1807 commandList.append( tempCmd )
1808 else:
1809 main.log.error( self.name + ": Invalid PTCP" )
1810 return main.FALSE
1811 else:
1812 for switch in sw:
1813 tempCmd = "sh ovs-vsctl set-controller "
1814 tempCmd += switch + " " + onosIp
1815 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001816 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001817 main.log.error( self.name + ": Invalid switch type " )
1818 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001819
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001820 for cmd in commandList:
1821 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001823 if "no bridge named" in self.handle.before:
1824 main.log.error( self.name + ": Error in assignSwController: " +
1825 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001826 except pexpect.TIMEOUT:
1827 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1828 return main.FALSE
1829 except pexpect.EOF:
1830 main.log.error( self.name + ": EOF exception found" )
1831 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001832 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001833 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001834 except pexpect.EOF:
1835 main.log.error( self.name + ": EOF exception found" )
1836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001837 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001838 except Exception:
1839 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001840 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001841
kelvin-onlabd3b64892015-01-20 13:26:24 -08001842 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001843 """
1844 Removes the controller target from sw"""
1845 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001846 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001847 response = self.execute(
1848 cmd=command,
1849 prompt="mininet>",
1850 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001851 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001852 main.log.error( self.name + ": EOF exception found" )
1853 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001854 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001855 except Exception:
1856 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001857 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001858 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001859 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001860
kelvin-onlabd3b64892015-01-20 13:26:24 -08001861 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001862 """
Jon Hallb1290e82014-11-18 16:17:48 -05001863 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001864 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001865 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001866 NOTE: cannot currently specify what type of switch
1867 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001868 sw = name of the new switch as a string
1869 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001870 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001871 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001872 """
1873 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001874 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001875 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001876 response = self.execute(
1877 cmd=command,
1878 prompt="mininet>",
1879 timeout=10 )
1880 if re.search( "already exists!", response ):
1881 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001882 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001883 elif re.search( "Error", response ):
1884 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001885 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001886 elif re.search( "usage:", response ):
1887 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 return main.FALSE
1889 else:
1890 return main.TRUE
1891 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001893 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001894 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001895 except Exception:
1896 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001897 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001898
kelvin-onlabd3b64892015-01-20 13:26:24 -08001899 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001900 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001901 delete a switch from the mininet topology
1902 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001903 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001904 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001905 sw = name of the switch as a string
1906 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001907 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001908 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001909 response = self.execute(
1910 cmd=command,
1911 prompt="mininet>",
1912 timeout=10 )
1913 if re.search( "no switch named", response ):
1914 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001915 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001916 elif re.search( "Error", response ):
1917 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001919 elif re.search( "usage:", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
1922 else:
1923 return main.TRUE
1924 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001925 main.log.error( self.name + ": EOF exception found" )
1926 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001927 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001928 except Exception:
1929 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001930 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001931
You Wangdb8cd0a2016-05-26 15:19:45 -07001932 def getSwitchRandom( self, timeout=60, nonCut=True ):
1933 """
1934 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001935 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001936 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001937 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001938 it just randomly returns one switch from all current switches in
1939 Mininet.
1940 Returns the name of the chosen switch.
1941 """
1942 import random
1943 candidateSwitches = []
1944 try:
1945 if not nonCut:
1946 switches = self.getSwitches( timeout=timeout )
1947 assert len( switches ) != 0
1948 for switchName in switches.keys():
1949 candidateSwitches.append( switchName )
1950 else:
1951 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001952 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001953 return None
1954 self.graph.update( graphDict )
1955 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001956 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001957 return None
1958 elif len( candidateSwitches ) == 0:
1959 main.log.info( self.name + ": No candidate switch for deletion" )
1960 return None
1961 else:
1962 switch = random.sample( candidateSwitches, 1 )
1963 return switch[ 0 ]
1964 except KeyError:
1965 main.log.exception( self.name + ": KeyError exception found" )
1966 return None
1967 except AssertionError:
1968 main.log.exception( self.name + ": AssertionError exception found" )
1969 return None
1970 except Exception:
1971 main.log.exception( self.name + ": Uncaught exception" )
1972 return None
1973
1974 def delSwitchRandom( self, timeout=60, nonCut=True ):
1975 """
1976 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001977 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001978 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001979 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001980 otherwise it just randomly delete one switch from all current
1981 switches in Mininet.
1982 Returns the name of the deleted switch
1983 """
1984 try:
1985 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001986 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001987 return None
1988 else:
1989 deletionResult = self.delSwitch( switch )
1990 if deletionResult:
1991 return switch
1992 else:
1993 return None
1994 except Exception:
1995 main.log.exception( self.name + ": Uncaught exception" )
1996 return None
1997
kelvin-onlabd3b64892015-01-20 13:26:24 -08001998 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001999 """
2000 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002001 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002002 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002003 NOTE: cannot currently specify what type of link
2004 required params:
2005 node1 = the string node name of the first endpoint of the link
2006 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002007 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002008 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002009 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002010 response = self.execute(
2011 cmd=command,
2012 prompt="mininet>",
2013 timeout=10 )
2014 if re.search( "doesnt exist!", response ):
2015 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002016 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002017 elif re.search( "Error", response ):
2018 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002019 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002020 elif re.search( "usage:", response ):
2021 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002022 return main.FALSE
2023 else:
2024 return main.TRUE
2025 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002026 main.log.error( self.name + ": EOF exception found" )
2027 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002028 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002029 except Exception:
2030 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002031 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002032
kelvin-onlabd3b64892015-01-20 13:26:24 -08002033 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002034 """
2035 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002036 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002037 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002038 required params:
2039 node1 = the string node name of the first endpoint of the link
2040 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002041 returns: main.FALSE on an error, else main.TRUE
2042 """
Jon Hallffb386d2014-11-21 13:43:38 -08002043 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002044 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002045 response = self.execute(
2046 cmd=command,
2047 prompt="mininet>",
2048 timeout=10 )
2049 if re.search( "no node named", response ):
2050 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002052 elif re.search( "Error", response ):
2053 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002054 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002055 elif re.search( "usage:", response ):
2056 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002057 return main.FALSE
2058 else:
2059 return main.TRUE
2060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002061 main.log.error( self.name + ": EOF exception found" )
2062 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002063 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002064 except Exception:
2065 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002066 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002067
You Wangdb8cd0a2016-05-26 15:19:45 -07002068 def getLinkRandom( self, timeout=60, nonCut=True ):
2069 """
2070 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002071 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002072 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002073 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002074 it just randomly returns one link from all current links in
2075 Mininet.
2076 Returns the link as a list, e.g. [ 's1', 's2' ]
2077 """
2078 import random
2079 candidateLinks = []
2080 try:
2081 if not nonCut:
2082 links = self.getLinks( timeout=timeout )
2083 assert len( links ) != 0
2084 for link in links:
2085 # Exclude host-switch link
2086 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2087 continue
2088 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2089 else:
2090 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002091 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002092 return None
2093 self.graph.update( graphDict )
2094 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002095 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002096 return None
2097 elif len( candidateLinks ) == 0:
2098 main.log.info( self.name + ": No candidate link for deletion" )
2099 return None
2100 else:
2101 link = random.sample( candidateLinks, 1 )
2102 return link[ 0 ]
2103 except KeyError:
2104 main.log.exception( self.name + ": KeyError exception found" )
2105 return None
2106 except AssertionError:
2107 main.log.exception( self.name + ": AssertionError exception found" )
2108 return None
2109 except Exception:
2110 main.log.exception( self.name + ": Uncaught exception" )
2111 return None
2112
2113 def delLinkRandom( self, timeout=60, nonCut=True ):
2114 """
2115 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002116 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002117 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002118 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002119 otherwise it just randomly delete one link from all current links
2120 in Mininet.
2121 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2122 """
2123 try:
2124 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002125 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002126 return None
2127 else:
2128 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2129 if deletionResult:
2130 return link
2131 else:
2132 return None
2133 except Exception:
2134 main.log.exception( self.name + ": Uncaught exception" )
2135 return None
2136
kelvin-onlabd3b64892015-01-20 13:26:24 -08002137 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002138 """
Jon Hallb1290e82014-11-18 16:17:48 -05002139 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002140 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002141 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002142 NOTE: cannot currently specify what type of host
2143 required params:
2144 hostname = the string hostname
2145 optional key-value params
2146 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002147 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002148 """
2149 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002150 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002151 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002152 response = self.execute(
2153 cmd=command,
2154 prompt="mininet>",
2155 timeout=10 )
2156 if re.search( "already exists!", response ):
2157 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002158 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002159 elif re.search( "doesnt exists!", response ):
2160 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002161 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002162 elif re.search( "Error", response ):
2163 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002164 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002165 elif re.search( "usage:", response ):
2166 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002167 return main.FALSE
2168 else:
2169 return main.TRUE
2170 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002171 main.log.error( self.name + ": EOF exception found" )
2172 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002173 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002174 except Exception:
2175 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002176 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002177
kelvin-onlabd3b64892015-01-20 13:26:24 -08002178 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002179 """
2180 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002181 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002182 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002183 NOTE: this uses a custom mn function
2184 required params:
2185 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002186 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002187 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002189 response = self.execute(
2190 cmd=command,
2191 prompt="mininet>",
2192 timeout=10 )
2193 if re.search( "no host named", response ):
2194 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002195 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002196 elif re.search( "Error", response ):
2197 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002198 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002199 elif re.search( "usage:", response ):
2200 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002201 return main.FALSE
2202 else:
2203 return main.TRUE
2204 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002205 main.log.error( self.name + ": EOF exception found" )
2206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002207 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002208 except Exception:
2209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002210 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002211
Jon Hall7eb38402015-01-08 17:19:54 -08002212 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002213 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002214 Called at the end of the test to stop the mininet and
2215 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002216 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002217 try:
2218 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002219 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002220 timeout=2 )
2221 response = main.TRUE
2222 if i == 0:
2223 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002224 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002225 return main.TRUE
2226 # print "Disconnecting Mininet"
2227 if self.handle:
2228 self.handle.sendline( "exit" )
2229 self.handle.expect( "exit" )
2230 self.handle.expect( "(.*)" )
2231 else:
2232 main.log.error( "Connection failed to the host" )
2233 return response
2234 except pexpect.EOF:
2235 main.log.error( self.name + ": EOF exception found" )
2236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002237 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002238 except Exception:
2239 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002240 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002241
Devin Lima7cfdbd2017-09-29 15:02:22 -07002242 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002243 """
Jon Hall21270ac2015-02-16 17:59:55 -08002244 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002245 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002246 main.FALSE if the pexpect handle does not exist.
2247
Jon Halld61331b2015-02-17 16:35:47 -08002248 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002249 """
Jon Halld61331b2015-02-17 16:35:47 -08002250 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002251 response = ''
2252 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002253 try:
Jon Halld80cc142015-07-06 13:36:05 -07002254 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002255 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002256 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002257 pexpect.EOF,
2258 pexpect.TIMEOUT ],
2259 timeout )
2260 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002261 main.log.info( "Exiting mininet.." )
2262 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002263 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002264 prompt=self.prompt,
2265 timeout=exitTimeout )
2266 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002267 self.handle.sendline( "sudo mn -c" )
2268 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002269
Jeremyd9e4eb12016-04-13 12:09:06 -07002270 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002271 main.log.info( " Mininet trying to exit while not " +
2272 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002273 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002274 elif i == 2:
2275 main.log.error( "Something went wrong exiting mininet" )
2276 elif i == 3: # timeout
2277 main.log.error( "Something went wrong exiting mininet " +
2278 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002279
You Wang18db8592018-04-02 13:52:03 -07002280 self.handle.sendline( "" )
2281 self.handle.expect( self.prompt )
2282 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2283
Hari Krishnab35c6d02015-03-18 11:13:51 -07002284 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002285 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002286 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002287 self.handle.sendline(
2288 "sudo kill -9 \`ps -ef | grep \"" +
2289 fileName +
2290 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002291 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002292 main.log.error( self.name + ": TIMEOUT exception found" )
2293 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002294 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002295 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002296 main.log.error( self.name + ": EOF exception found" )
2297 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002298 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002299 except Exception:
2300 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002301 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002302 else:
2303 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002304 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002305 return response
2306
YPZhang26a139e2016-04-25 14:01:55 -07002307 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002308 """
2309 Description:
2310 Sends arp message from mininet host for hosts discovery
2311 Required:
2312 host - hosts name
2313 Optional:
2314 ip - ip address that does not exist in the network so there would
2315 be no reply.
2316 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002317 if ethDevice:
2318 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002319 cmd = srcHost + " arping -c1 "
2320 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002321 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 -07002322 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002323 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002324 if output:
2325 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002326 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002327 i = self.handle.expect( [ "mininet>", "arping: " ] )
2328 if i == 0:
2329 return main.TRUE
2330 elif i == 1:
2331 response = self.handle.before + self.handle.after
2332 self.handle.expect( "mininet>" )
2333 response += self.handle.before + self.handle.after
2334 main.log.warn( "Error sending arping, output was: " +
2335 response )
2336 return main.FALSE
2337 except pexpect.TIMEOUT:
2338 main.log.error( self.name + ": TIMEOUT exception found" )
2339 main.log.warn( self.handle.before )
2340 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002341 except pexpect.EOF:
2342 main.log.error( self.name + ": EOF exception found" )
2343 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002344 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002345 except Exception:
2346 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002347 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002348
Jon Hall7eb38402015-01-08 17:19:54 -08002349 def decToHex( self, num ):
2350 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002351
Jon Hall7eb38402015-01-08 17:19:54 -08002352 def getSwitchFlowCount( self, switch ):
2353 """
2354 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002355 if self.handle:
2356 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2357 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002358 response = self.execute(
2359 cmd=cmd,
2360 prompt="mininet>",
2361 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002362 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002363 main.log.error( self.name + ": EOF exception found" )
2364 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002365 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002366 except Exception:
2367 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002368 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002369 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002370 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002371 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002372 main.log.info(
2373 "Couldn't find flows on switch %s, found: %s" %
2374 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002375 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002376 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002377 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002378 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002379
Jon Hall9ed8f372016-02-24 17:34:07 -08002380 def checkFlows( self, sw, dumpFormat=None ):
2381 if dumpFormat:
2382 command = "sh ovs-ofctl -F " + \
2383 dumpFormat + " dump-flows " + str( sw )
2384 else:
2385 command = "sh ovs-ofctl dump-flows " + str( sw )
2386 try:
2387 response = self.execute(
2388 cmd=command,
2389 prompt="mininet>",
2390 timeout=10 )
2391 return response
2392 except pexpect.EOF:
2393 main.log.error( self.name + ": EOF exception found" )
2394 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002395 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002396 except Exception:
2397 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002398 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002399
GlennRC68467eb2015-11-16 18:01:01 -08002400 def flowTableComp( self, flowTable1, flowTable2 ):
2401 # This function compares the selctors and treatments of each flow
2402 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002403 assert flowTable1, "flowTable1 is empty or None"
2404 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002405 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002406 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002407 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002408 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002409 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2410 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002411 for field in dFields:
2412 try:
2413 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002414 except KeyError:
2415 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002416 try:
2417 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002418 except KeyError:
2419 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002420 for i in range( len( flowTable1 ) ):
2421 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002422 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002423 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002424 returnValue = main.FALSE
2425 break
2426 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002427 except AssertionError:
2428 main.log.exception( "Nothing to compare" )
2429 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002430 except Exception:
2431 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002432 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002433
GlennRC528ad292015-11-12 10:38:18 -08002434 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002435 '''
GlennRC956ea742015-11-05 16:14:15 -08002436 Discription: Parses flows into json format.
2437 NOTE: this can parse any string thats separated with commas
2438 Arguments:
2439 Required:
2440 flows: a list of strings that represnt flows
2441 Optional:
2442 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2443 debug: prints out the final result
2444 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002445 '''
GlennRC528ad292015-11-12 10:38:18 -08002446 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002447 try:
2448 for flow in flowTable:
2449 jsonFlow = {}
2450 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002451 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002452 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002453 for i in range( len( parsedFlow ) ):
2454 item = parsedFlow[ i ]
2455 if item[ 0 ] == " ":
2456 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002457 # grab the selector and treatment from the parsed flow
2458 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002459 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002460 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002461 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002462 index = 0
2463 # parse the flags
2464 # NOTE: This only parses one flag
2465 flag = {}
2466 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002467 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002468 index += 1
2469 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002470 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002471 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002472 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002473 # the priority is stuck in the selecter so put it back
2474 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002475 if 'priority' in sel[0]:
2476 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002477 # parse selector
2478 criteria = []
2479 for item in sel:
2480 # this is the type of the packet e.g. "arp"
2481 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002482 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002483 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 field = item.split( "=" )
2485 criteria.append( { field[ 0 ]: field[ 1 ] } )
2486 selector = { "selector": { "criteria": sorted( criteria ) } }
2487 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002488 # get rid of the action part e.g. "action=output:2"
2489 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002490 treat = treat.split( "=" )
2491 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002492 # parse treatment
2493 action = []
2494 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002495 if ":" in item:
2496 field = item.split( ":" )
2497 action.append( { field[ 0 ]: field[ 1 ] } )
2498 else:
2499 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2500 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002501 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002502 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002503 # parse the rest of the flow
2504 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002505 field = item.split( "=" )
2506 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002507 # add the treatment and the selector to the json flow
2508 jsonFlow.update( selector )
2509 jsonFlow.update( treatment )
2510 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002511
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002512 if debug:
2513 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002514
You Wang91c37cf2016-05-23 09:39:42 -07002515 # add the json flow to the json flow table
2516 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002517
You Wang91c37cf2016-05-23 09:39:42 -07002518 return jsonFlowTable
2519
2520 except IndexError:
2521 main.log.exception( self.name + ": IndexError found" )
2522 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002523 except pexpect.EOF:
2524 main.log.error( self.name + ": EOF exception found" )
2525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002526 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002527 except Exception:
2528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002529 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002530
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002531 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002532 '''
2533 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002534 Each element is a flow.
2535 Arguments:
2536 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002537 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002538 a list of switches.
2539 Optional:
2540 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2541 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002542 '''
GlennRC956ea742015-11-05 16:14:15 -08002543 try:
2544 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002545 if isinstance( sw, list ):
2546 switches.extend( sw )
2547 else:
2548 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002549
2550 flows = []
2551 for s in switches:
2552 cmd = "sh ovs-ofctl dump-flows " + s
2553
GlennRC528ad292015-11-12 10:38:18 -08002554 if "1.0" == version:
2555 cmd += " -F OpenFlow10-table_id"
2556 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002557 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002558
2559 main.log.info( "Sending: " + cmd )
2560 self.handle.sendline( cmd )
2561 self.handle.expect( "mininet>" )
2562 response = self.handle.before
2563 response = response.split( "\r\n" )
2564 # dump the first two elements and the last
2565 # the first element is the command that was sent
2566 # the second is the table header
2567 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002568 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002569 flows.extend( response )
2570
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002571 if debug:
2572 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002573
GlennRC528ad292015-11-12 10:38:18 -08002574 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002575
GlennRC956ea742015-11-05 16:14:15 -08002576 except pexpect.EOF:
2577 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002578 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002579 except Exception:
2580 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002581 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002582
2583 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002584 '''
GlennRC956ea742015-11-05 16:14:15 -08002585 Discription: Checks whether the ID provided matches a flow ID in Mininet
2586 Arguments:
2587 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002588 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002589 a list of switches.
2590 flowId: the flow ID in hex format. Can also be a list of IDs
2591 Optional:
2592 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2593 debug: prints out the final result
2594 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2595 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002596 '''
GlennRC956ea742015-11-05 16:14:15 -08002597 try:
2598 main.log.info( "Getting flows from Mininet" )
2599 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002600 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002601 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002602
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002603 if debug:
2604 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002605
2606 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002607 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002608 result = False
2609 for f in flows:
2610 if flowId in f.get( 'cookie' ):
2611 result = True
2612 break
2613 # flowId is a list
2614 else:
2615 result = True
2616 # Get flow IDs from Mininet
2617 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2618 # Save the IDs that are not in Mininet
2619 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2620
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002621 if debug:
2622 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002623
2624 # Print out the IDs that are not in Mininet
2625 if absentIds:
2626 main.log.warn( "Absent ids: {}".format( absentIds ) )
2627 result = False
2628
2629 return main.TRUE if result else main.FALSE
2630
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002631 except pexpect.EOF:
2632 main.log.error( self.name + ": EOF exception found" )
2633 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002634 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002635 except Exception:
2636 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002637 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002638
Charles Chan029be652015-08-24 01:46:10 +08002639 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002640 """
Jon Hallefbd9792015-03-05 16:11:36 -08002641 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002642 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002643 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002644 self.handle.sendline( "" )
2645 self.handle.expect( "mininet>" )
2646 self.handle.sendline(
2647 "sh sudo tcpdump -n -i " +
2648 intf +
2649 " " +
2650 port +
2651 " -w " +
2652 filename.strip() +
2653 " &" )
2654 self.handle.sendline( "" )
2655 i = self.handle.expect( [ 'No\ssuch\device',
2656 'listening\son',
2657 pexpect.TIMEOUT,
2658 "mininet>" ],
2659 timeout=10 )
2660 main.log.warn( self.handle.before + self.handle.after )
2661 self.handle.sendline( "" )
2662 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002663 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002664 main.log.error(
2665 self.name +
2666 ": tcpdump - No such device exists. " +
2667 "tcpdump attempted on: " +
2668 intf )
admin2a9548d2014-06-17 14:08:07 -07002669 return main.FALSE
2670 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002671 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002672 return main.TRUE
2673 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002674 main.log.error(
2675 self.name +
2676 ": tcpdump command timed out! Check interface name," +
2677 " given interface was: " +
2678 intf )
admin2a9548d2014-06-17 14:08:07 -07002679 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002680 elif i == 3:
2681 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002682 return main.TRUE
2683 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002684 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002685 return main.FALSE
2686 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002687 main.log.error( self.name + ": EOF exception found" )
2688 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002689 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002690 except Exception:
2691 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002692 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002693
kelvin-onlabd3b64892015-01-20 13:26:24 -08002694 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002695 """
2696 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002697 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002698 self.handle.sendline( "sh sudo pkill tcpdump" )
2699 self.handle.expect( "mininet>" )
2700 self.handle.sendline( "" )
2701 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002702 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002703 main.log.error( self.name + ": TIMEOUT exception found" )
2704 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002705 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002706 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002707 main.log.error( self.name + ": EOF exception found" )
2708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002709 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002710 except Exception:
2711 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002712 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002713
Jon Halld80cc142015-07-06 13:36:05 -07002714 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002715 """
2716 Read ports from a Mininet switch.
2717
2718 Returns a json structure containing information about the
2719 ports of the given switch.
2720 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002721 try:
2722 response = self.getInterfaces( nodeName )
2723 # TODO: Sanity check on response. log if no such switch exists
2724 ports = []
2725 for line in response.split( "\n" ):
2726 if not line.startswith( "name=" ):
2727 continue
2728 portVars = {}
2729 for var in line.split( "," ):
2730 key, value = var.split( "=" )
2731 portVars[ key ] = value
2732 isUp = portVars.pop( 'enabled', "True" )
2733 isUp = "True" in isUp
2734 if verbose:
2735 main.log.info( "Reading switch port %s(%s)" %
2736 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2737 mac = portVars[ 'mac' ]
2738 if mac == 'None':
2739 mac = None
2740 ips = []
2741 ip = portVars[ 'ip' ]
2742 if ip == 'None':
2743 ip = None
2744 ips.append( ip )
2745 name = portVars[ 'name' ]
2746 if name == 'None':
2747 name = None
2748 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2749 if name == 'lo':
2750 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2751 else:
2752 portNo = re.search( portRe, name ).group( 'port' )
2753 ports.append( { 'of_port': portNo,
2754 'mac': str( mac ).replace( '\'', '' ),
2755 'name': name,
2756 'ips': ips,
2757 'enabled': isUp } )
2758 return ports
2759 except pexpect.EOF:
2760 main.log.error( self.name + ": EOF exception found" )
2761 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002762 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002763 except Exception:
2764 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002765 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002766
You Wangdb8cd0a2016-05-26 15:19:45 -07002767 def getOVSPorts( self, nodeName ):
2768 """
2769 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2770
2771 Returns a list of dictionaries containing information about each
2772 port of the given switch.
2773 """
2774 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2775 try:
2776 response = self.execute(
2777 cmd=command,
2778 prompt="mininet>",
2779 timeout=10 )
2780 ports = []
2781 if response:
2782 for line in response.split( "\n" ):
2783 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2784 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002785 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002786 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2787 result = re.search( pattern, line )
2788 if result:
2789 index = result.group( 'index' )
2790 name = result.group( 'name' )
2791 # This port number is extracted from port name
2792 port = result.group( 'port' )
2793 mac = result.group( 'mac' )
2794 ports.append( { 'index': index,
2795 'name': name,
2796 'port': port,
2797 'mac': mac } )
2798 return ports
2799 except pexpect.EOF:
2800 main.log.error( self.name + ": EOF exception found" )
2801 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002802 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002803 except Exception:
2804 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002805 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002806
Devin Lima7cfdbd2017-09-29 15:02:22 -07002807 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002808 """
2809 Read switches from Mininet.
2810
2811 Returns a dictionary whose keys are the switch names and the value is
2812 a dictionary containing information about the switch.
2813 """
Jon Halla22481b2015-07-28 17:46:01 -07002814 # NOTE: To support new Mininet switch classes, just append the new
2815 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002816
Jon Halla22481b2015-07-28 17:46:01 -07002817 # Regex patterns to parse 'dump' output
2818 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002819 # <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 -07002820 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002821 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2822 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2823 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002824 try:
2825 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2826 swRE = r"<(?P<class>" + switchClasses + r")" +\
2827 r"(?P<options>\{.*\})?\s" +\
2828 r"(?P<name>[^:]+)\:\s" +\
2829 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2830 r"\spid=(?P<pid>(\d)+)"
2831 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002832 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002833 output = {}
2834 dump = self.dump().split( "\n" )
2835 for line in dump:
2836 result = re.search( swRE, line, re.I )
2837 if result:
2838 name = result.group( 'name' )
2839 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2840 pid = result.group( 'pid' )
2841 swClass = result.group( 'class' )
2842 options = result.group( 'options' )
2843 if verbose:
2844 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2845 ports = self.getPorts( name )
2846 output[ name ] = { "dpid": dpid,
2847 "ports": ports,
2848 "swClass": swClass,
2849 "pid": pid,
2850 "options": options }
2851 return output
2852 except pexpect.EOF:
2853 main.log.error( self.name + ": EOF exception found" )
2854 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002855 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002856 except Exception:
2857 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002858 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002859
You Wangd66de192018-04-30 17:30:12 -07002860 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002861 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2862 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002863 """
2864 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002865 Optional:
2866 hostClass: it is used to match the class of the mininet host. It
2867 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002868 Returns a dictionary whose keys are the host names and the value is
2869 a dictionary containing information about the host.
2870 """
2871 # Regex patterns to parse dump output
2872 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002873 # <Host h1: pid=12725>
2874 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2875 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2876 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002877 # NOTE: Does not correctly match hosts with multi-links
2878 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2879 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002880 try:
You Wang53dba1e2018-02-02 17:45:44 -08002881 if not isinstance( hostClass, types.ListType ):
2882 hostClass = [ str( hostClass ) ]
2883 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002884 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2885 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2886 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002887 if update:
2888 # update mn port info
2889 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002890 # Get mininet dump
2891 dump = self.dump().split( "\n" )
2892 hosts = {}
2893 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002894 result = re.search( hostRE, line )
2895 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002896 name = result.group( 'name' )
2897 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002898 if getInterfaces:
2899 response = self.getInterfaces( name )
2900 # Populate interface info
2901 for line in response.split( "\n" ):
2902 if line.startswith( "name=" ):
2903 portVars = {}
2904 for var in line.split( "," ):
2905 key, value = var.split( "=" )
2906 portVars[ key ] = value
2907 isUp = portVars.pop( 'enabled', "True" )
2908 isUp = "True" in isUp
2909 if verbose:
2910 main.log.info( "Reading host port %s(%s)" %
2911 ( portVars[ 'name' ],
2912 portVars[ 'mac' ] ) )
2913 mac = portVars[ 'mac' ]
2914 if mac == 'None':
2915 mac = None
2916 ips = []
2917 ip = portVars[ 'ip' ]
2918 if ip == 'None':
2919 ip = None
2920 ips.append( ip )
2921 intfName = portVars[ 'name' ]
2922 if name == 'None':
2923 name = None
2924 interfaces.append( {
2925 "name": intfName,
2926 "ips": ips,
2927 "mac": str( mac ),
2928 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002929 hosts[ name ] = { "interfaces": interfaces }
2930 return hosts
2931 except pexpect.EOF:
2932 main.log.error( self.name + ": EOF exception found" )
2933 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002934 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002935 except Exception:
2936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002937 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002938
Devin Lima7cfdbd2017-09-29 15:02:22 -07002939 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002940 """
2941 Gathers information about current Mininet links. These links may not
2942 be up if one of the ports is down.
2943
2944 Returns a list of dictionaries with link endpoints.
2945
2946 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002947 { 'node1': str( node1 name )
2948 'node2': str( node2 name )
2949 'port1': str( port1 of_port )
2950 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002951 Note: The port number returned is the eth#, not necessarily the of_port
2952 number. In Mininet, for OVS switch, these should be the same. For
2953 hosts, this is just the eth#.
2954 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002955 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002956 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002957 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002958
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002959 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002960 # s1-eth3<->s2-eth1 (OK OK)
2961 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002962 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2963 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2964 links = []
2965 for line in response:
2966 match = re.search( linkRE, line )
2967 if match:
2968 node1 = match.group( 'node1' )
2969 node2 = match.group( 'node2' )
2970 port1 = match.group( 'port1' )
2971 port2 = match.group( 'port2' )
2972 links.append( { 'node1': node1,
2973 'node2': node2,
2974 'port1': port1,
2975 'port2': port2 } )
2976 return links
2977
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
2986 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002987 """
2988 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002989 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002990
Jon Hallafa8a472015-06-12 14:02:42 -07002991 Dependencies:
2992 1. numpy - "sudo pip install numpy"
2993 """
2994 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002995 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002996 try:
2997 mnDPIDs = []
2998 for swName, switch in switches.iteritems():
2999 mnDPIDs.append( switch[ 'dpid' ].lower() )
3000 mnDPIDs.sort()
3001 if switchesJson == "": # if rest call fails
3002 main.log.error(
3003 self.name +
3004 ".compareSwitches(): Empty JSON object given from ONOS" )
3005 return main.FALSE
3006 onos = switchesJson
3007 onosDPIDs = []
3008 for switch in onos:
3009 if switch[ 'available' ]:
3010 onosDPIDs.append(
3011 switch[ 'id' ].replace(
3012 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003013 '' ).replace(
3014 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003015 '' ).lower() )
3016 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003017
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003018 if mnDPIDs != onosDPIDs:
3019 switchResults = main.FALSE
3020 main.log.error( "Switches in MN but not in ONOS:" )
3021 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3022 main.log.error( str( list1 ) )
3023 main.log.error( "Switches in ONOS but not in MN:" )
3024 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3025 main.log.error( str( list2 ) )
3026 else: # list of dpid's match in onos and mn
3027 switchResults = main.TRUE
3028 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003029
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003030 # FIXME: this does not look for extra ports in ONOS, only checks that
3031 # ONOS has what is in MN
3032 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003033
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003034 # PORTS
3035 for name, mnSwitch in switches.iteritems():
3036 mnPorts = []
3037 onosPorts = []
3038 switchResult = main.TRUE
3039 for port in mnSwitch[ 'ports' ]:
3040 if port[ 'enabled' ]:
3041 mnPorts.append( int( port[ 'of_port' ] ) )
3042 for onosSwitch in portsJson:
3043 if onosSwitch[ 'device' ][ 'available' ]:
3044 if onosSwitch[ 'device' ][ 'id' ].replace(
3045 ':',
3046 '' ).replace(
3047 "of",
3048 '' ) == mnSwitch[ 'dpid' ]:
3049 for port in onosSwitch[ 'ports' ]:
3050 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003051 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003052 # onosPorts.append( 'local' )
3053 onosPorts.append( long( uint64( -2 ) ) )
3054 else:
3055 onosPorts.append( int( port[ 'port' ] ) )
3056 break
3057 mnPorts.sort( key=float )
3058 onosPorts.sort( key=float )
3059
3060 mnPortsLog = mnPorts
3061 onosPortsLog = onosPorts
3062 mnPorts = [ x for x in mnPorts ]
3063 onosPorts = [ x for x in onosPorts ]
3064
3065 # TODO: handle other reserved port numbers besides LOCAL
3066 # NOTE: Reserved ports
3067 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3068 # long( uint64( -2 ) )
3069 for mnPort in mnPortsLog:
3070 if mnPort in onosPorts:
3071 # don't set results to true here as this is just one of
3072 # many checks and it might override a failure
3073 mnPorts.remove( mnPort )
3074 onosPorts.remove( mnPort )
3075
3076 # NOTE: OVS reports this as down since there is no link
3077 # So ignoring these for now
3078 # TODO: Come up with a better way of handling these
3079 if 65534 in mnPorts:
3080 mnPorts.remove( 65534 )
3081 if long( uint64( -2 ) ) in onosPorts:
3082 onosPorts.remove( long( uint64( -2 ) ) )
3083 if len( mnPorts ): # the ports of this switch don't match
3084 switchResult = main.FALSE
3085 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3086 if len( onosPorts ): # the ports of this switch don't match
3087 switchResult = main.FALSE
3088 main.log.warn(
3089 "Ports in ONOS but not MN: " +
3090 str( onosPorts ) )
3091 if switchResult == main.FALSE:
3092 main.log.error(
3093 "The list of ports for switch %s(%s) does not match:" %
3094 ( name, mnSwitch[ 'dpid' ] ) )
3095 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3096 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3097 portsResults = portsResults and switchResult
3098 finalResults = finalResults and portsResults
3099 return finalResults
3100 except pexpect.EOF:
3101 main.log.error( self.name + ": EOF exception found" )
3102 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003103 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003104 except Exception:
3105 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003106 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003107
Jon Hallafa8a472015-06-12 14:02:42 -07003108 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003109 """
3110 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003111 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003112
Jon Hallafa8a472015-06-12 14:02:42 -07003113 """
Jon Hall7eb38402015-01-08 17:19:54 -08003114 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003115 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003116 try:
3117 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003118
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003119 mnLinks = []
3120 for l in links:
3121 try:
3122 node1 = switches[ l[ 'node1' ] ]
3123 node2 = switches[ l[ 'node2' ] ]
3124 enabled = True
3125 for port in node1[ 'ports' ]:
3126 if port[ 'of_port' ] == l[ 'port1' ]:
3127 enabled = enabled and port[ 'enabled' ]
3128 for port in node2[ 'ports' ]:
3129 if port[ 'of_port' ] == l[ 'port2' ]:
3130 enabled = enabled and port[ 'enabled' ]
3131 if enabled:
3132 mnLinks.append( l )
3133 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003134 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003135 if 2 * len( mnLinks ) == len( onos ):
3136 linkResults = main.TRUE
3137 else:
3138 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003139 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003140 "Mininet has " + str( len( mnLinks ) ) +
3141 " bidirectional links and ONOS has " +
3142 str( len( onos ) ) + " unidirectional links" )
3143
3144 # iterate through MN links and check if an ONOS link exists in
3145 # both directions
3146 for link in mnLinks:
3147 # TODO: Find a more efficient search method
3148 node1 = None
3149 port1 = None
3150 node2 = None
3151 port2 = None
3152 firstDir = main.FALSE
3153 secondDir = main.FALSE
3154 for swName, switch in switches.iteritems():
3155 if swName == link[ 'node1' ]:
3156 node1 = switch[ 'dpid' ]
3157 for port in switch[ 'ports' ]:
3158 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3159 port1 = port[ 'of_port' ]
3160 if node1 is not None and node2 is not None:
3161 break
3162 if swName == link[ 'node2' ]:
3163 node2 = switch[ 'dpid' ]
3164 for port in switch[ 'ports' ]:
3165 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3166 port2 = port[ 'of_port' ]
3167 if node1 is not None and node2 is not None:
3168 break
3169
3170 for onosLink in onos:
3171 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3172 ":", '' ).replace( "of", '' )
3173 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3174 ":", '' ).replace( "of", '' )
3175 onosPort1 = onosLink[ 'src' ][ 'port' ]
3176 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3177
3178 # check onos link from node1 to node2
3179 if str( onosNode1 ) == str( node1 ) and str(
3180 onosNode2 ) == str( node2 ):
3181 if int( onosPort1 ) == int( port1 ) and int(
3182 onosPort2 ) == int( port2 ):
3183 firstDir = main.TRUE
3184 else:
Jon Hallab611372018-02-21 15:26:05 -08003185 # The right switches, but wrong ports, could be
3186 # another link between these devices, or onos
3187 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003188 main.log.warn(
3189 'The port numbers do not match for ' +
3190 str( link ) +
3191 ' between ONOS and MN. When checking ONOS for ' +
3192 'link %s/%s -> %s/%s' %
3193 ( node1, port1, node2, port2 ) +
3194 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003195 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3196 '. This could be another link between these devices' +
3197 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003198
3199 # check onos link from node2 to node1
3200 elif ( str( onosNode1 ) == str( node2 ) and
3201 str( onosNode2 ) == str( node1 ) ):
3202 if ( int( onosPort1 ) == int( port2 )
3203 and int( onosPort2 ) == int( port1 ) ):
3204 secondDir = main.TRUE
3205 else:
Jon Hallab611372018-02-21 15:26:05 -08003206 # The right switches, but wrong ports, could be
3207 # another link between these devices, or onos
3208 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003209 main.log.warn(
3210 'The port numbers do not match for ' +
3211 str( link ) +
3212 ' between ONOS and MN. When checking ONOS for ' +
3213 'link %s/%s -> %s/%s' %
3214 ( node1, port1, node2, port2 ) +
3215 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003216 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3217 '. This could be another link between these devices' +
3218 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003219 else: # this is not the link you're looking for
3220 pass
3221 if not firstDir:
3222 main.log.error(
3223 'ONOS does not have the link %s/%s -> %s/%s' %
3224 ( node1, port1, node2, port2 ) )
3225 if not secondDir:
3226 main.log.error(
3227 'ONOS does not have the link %s/%s -> %s/%s' %
3228 ( node2, port2, node1, port1 ) )
3229 linkResults = linkResults and firstDir and secondDir
3230 return linkResults
3231 except pexpect.EOF:
3232 main.log.error( self.name + ": EOF exception found" )
3233 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003234 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003235 except Exception:
3236 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003237 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003238
Jon Hallafa8a472015-06-12 14:02:42 -07003239 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003240 """
Jon Hallafa8a472015-06-12 14:02:42 -07003241 Compare mn and onos Hosts.
3242 Since Mininet hosts are quiet, ONOS will only know of them when they
3243 speak. For this reason, we will only check that the hosts in ONOS
3244 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003245
Jon Hallafa8a472015-06-12 14:02:42 -07003246 Arguments:
3247 hostsJson: parsed json object from the onos hosts api
3248 Returns:
3249 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003250 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003251 try:
3252 hostResults = main.TRUE
3253 for onosHost in hostsJson:
3254 onosMAC = onosHost[ 'mac' ].lower()
3255 match = False
3256 for mnHost, info in hosts.iteritems():
3257 for mnIntf in info[ 'interfaces' ]:
3258 if onosMAC == mnIntf[ 'mac' ].lower():
3259 match = True
3260 for ip in mnIntf[ 'ips' ]:
3261 if ip in onosHost[ 'ipAddresses' ]:
3262 pass # all is well
3263 else:
3264 # misssing ip
3265 main.log.error( "ONOS host " +
3266 onosHost[ 'id' ] +
3267 " has a different IP(" +
3268 str( onosHost[ 'ipAddresses' ] ) +
3269 ") than the Mininet host(" +
3270 str( ip ) +
3271 ")." )
3272 output = json.dumps(
3273 onosHost,
3274 sort_keys=True,
3275 indent=4,
3276 separators=( ',', ': ' ) )
3277 main.log.info( output )
3278 hostResults = main.FALSE
3279 if not match:
3280 hostResults = main.FALSE
3281 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3282 "corresponding Mininet host." )
3283 output = json.dumps( onosHost,
3284 sort_keys=True,
3285 indent=4,
3286 separators=( ',', ': ' ) )
3287 main.log.info( output )
3288 return hostResults
3289 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003290 main.log.error( self.name + ": EOF exception found" )
3291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003292 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003293 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003295 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003296
You Wangd66de192018-04-30 17:30:12 -07003297 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003298 """
3299 Description:
3300 Verify that all hosts have IP address assigned to them
3301 Optional:
3302 hostList: If specified, verifications only happen to the hosts
3303 in hostList
3304 prefix: at least one of the ip address assigned to the host
3305 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003306 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003307 Returns:
3308 main.TRUE if all hosts have specific IP address assigned;
3309 main.FALSE otherwise
3310 """
3311 try:
You Wangd66de192018-04-30 17:30:12 -07003312 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003313 if not hostList:
3314 hostList = hosts.keys()
3315 for hostName in hosts.keys():
3316 if hostName not in hostList:
3317 continue
3318 ipList = []
3319 self.handle.sendline( str( hostName ) + " ip a" )
3320 self.handle.expect( "mininet>" )
3321 ipa = self.handle.before
3322 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3323 ipList += re.findall( ipv4Pattern, ipa )
3324 # It's tricky to make regex for IPv6 addresses and this one is simplified
3325 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})/'
3326 ipList += re.findall( ipv6Pattern, ipa )
3327 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3328 if not ipList:
3329 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3330 else:
3331 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3332 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3333 else:
3334 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3335 hostList.remove( hostName )
3336 return main.FALSE if hostList else main.TRUE
3337 except KeyError:
3338 main.log.exception( self.name + ": host data not as expected: " + hosts )
3339 return None
3340 except pexpect.EOF:
3341 main.log.error( self.name + ": EOF exception found" )
3342 main.log.error( self.name + ": " + self.handle.before )
3343 main.cleanAndExit()
3344 except Exception:
3345 main.log.exception( self.name + ": Uncaught exception" )
3346 return None
3347
Jon Hallafa8a472015-06-12 14:02:42 -07003348 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003349 """
3350 Returns a list of all hosts
3351 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003352 try:
3353 self.handle.sendline( "" )
3354 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003355
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003356 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3357 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003358
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003359 handlePy = self.handle.before
3360 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3361 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003362
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003363 self.handle.sendline( "" )
3364 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003365
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003366 hostStr = handlePy.replace( "]", "" )
3367 hostStr = hostStr.replace( "'", "" )
3368 hostStr = hostStr.replace( "[", "" )
3369 hostStr = hostStr.replace( " ", "" )
3370 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003371
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003372 return hostList
3373 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003374 main.log.error( self.name + ": TIMEOUT exception found" )
3375 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003376 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003377 except pexpect.EOF:
3378 main.log.error( self.name + ": EOF exception found" )
3379 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003380 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003381 except Exception:
3382 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003383 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003384
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003385 def getSwitch( self ):
3386 """
3387 Returns a list of all switches
3388 Again, don't ask question just use it...
3389 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003390 try:
3391 # get host list...
3392 hostList = self.getHosts()
3393 # Make host set
3394 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003395
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003396 # Getting all the nodes in mininet
3397 self.handle.sendline( "" )
3398 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003399
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003400 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3401 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003402
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003403 handlePy = self.handle.before
3404 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3405 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003406
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003407 self.handle.sendline( "" )
3408 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003409
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003410 nodesStr = handlePy.replace( "]", "" )
3411 nodesStr = nodesStr.replace( "'", "" )
3412 nodesStr = nodesStr.replace( "[", "" )
3413 nodesStr = nodesStr.replace( " ", "" )
3414 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003415
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003416 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003417 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003418 nodesSet.discard( 'c0' )
3419 nodesSet.discard( 'c1' )
3420 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003421
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003422 switchSet = nodesSet - hostSet
3423 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003424
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 return switchList
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()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003437
You Wangdb8cd0a2016-05-26 15:19:45 -07003438 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3439 """
3440 Return a dictionary which describes the latest Mininet topology data as a
3441 graph.
3442 An example of the dictionary:
3443 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3444 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3445 Each vertex should at least have an 'edges' attribute which describes the
3446 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003447 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003448 list of attributes.
3449 An example of the edges dictionary:
3450 'edges': { vertex2: { 'port': ..., 'weight': ... },
3451 vertex3: { 'port': ..., 'weight': ... } }
3452 If useId == True, dpid/mac will be used instead of names to identify
3453 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3454 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003455 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003456 in topology data.
3457 Note that link or switch that are brought down by 'link x x down' or 'switch
3458 x down' commands still show in the output of Mininet CLI commands such as
3459 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3460 recommended to use delLink() or delSwitch functions to simulate link/switch
3461 down, and addLink() or addSwitch to add them back.
3462 """
3463 graphDict = {}
3464 try:
3465 links = self.getLinks( timeout=timeout )
3466 portDict = {}
3467 if useId:
3468 switches = self.getSwitches()
3469 if includeHost:
3470 hosts = self.getHosts()
3471 for link in links:
3472 # FIXME: support 'includeHost' argument
3473 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3474 continue
3475 nodeName1 = link[ 'node1' ]
3476 nodeName2 = link[ 'node2' ]
3477 port1 = link[ 'port1' ]
3478 port2 = link[ 'port2' ]
3479 # Loop for two nodes
3480 for i in range( 2 ):
3481 # Get port index from OVS
3482 # The index extracted from port name may be inconsistent with ONOS
3483 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003484 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003485 portList = self.getOVSPorts( nodeName1 )
3486 if len( portList ) == 0:
3487 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3488 return None
3489 portDict[ nodeName1 ] = portList
3490 for port in portDict[ nodeName1 ]:
3491 if port[ 'port' ] == port1:
3492 portIndex = port[ 'index' ]
3493 break
3494 if portIndex == -1:
3495 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3496 return None
3497 if useId:
3498 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3499 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3500 else:
3501 node1 = nodeName1
3502 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003503 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003504 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003505 graphDict[ node1 ] = { 'edges': {},
3506 'dpid': switches[ nodeName1 ][ 'dpid' ],
3507 'name': nodeName1,
3508 'ports': switches[ nodeName1 ][ 'ports' ],
3509 'swClass': switches[ nodeName1 ][ 'swClass' ],
3510 'pid': switches[ nodeName1 ][ 'pid' ],
3511 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003512 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003513 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003514 else:
3515 # Assert node2 is not connected to any current links of node1
3516 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003517 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003518 # Swap two nodes/ports
3519 nodeName1, nodeName2 = nodeName2, nodeName1
3520 port1, port2 = port2, port1
3521 return graphDict
3522 except KeyError:
3523 main.log.exception( self.name + ": KeyError exception found" )
3524 return None
3525 except AssertionError:
3526 main.log.exception( self.name + ": AssertionError exception found" )
3527 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003528 except pexpect.EOF:
3529 main.log.error( self.name + ": EOF exception found" )
3530 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003531 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003532 except Exception:
3533 main.log.exception( self.name + ": Uncaught exception" )
3534 return None
3535
Devin Lima7cfdbd2017-09-29 15:02:22 -07003536 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003537 """
3538 updates the port address and status information for
3539 each port in mn"""
3540 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003541 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003542 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003543 self.handle.sendline( "" )
3544 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003545
Jon Hall7eb38402015-01-08 17:19:54 -08003546 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003547 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003548
Jon Hall7eb38402015-01-08 17:19:54 -08003549 self.handle.sendline( "" )
3550 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003551
Jon Hallb1290e82014-11-18 16:17:48 -05003552 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003553 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003554 main.log.error( self.name + ": TIMEOUT exception found" )
3555 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003556 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003557 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003558 main.log.error( self.name + ": EOF exception found" )
3559 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003560 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003561 except Exception:
3562 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003563 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003564
Jon Halld80cc142015-07-06 13:36:05 -07003565 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003566 """
3567 Add vlan tag to a host.
3568 Dependencies:
3569 This class depends on the "vlan" package
3570 $ sudo apt-get install vlan
3571 Configuration:
3572 Load the 8021q module into the kernel
3573 $sudo modprobe 8021q
3574
3575 To make this setup permanent:
3576 $ sudo su -c 'echo "8021q" >> /etc/modules'
3577 """
3578 if self.handle:
3579 try:
Jon Halld80cc142015-07-06 13:36:05 -07003580 # get the ip address of the host
3581 main.log.info( "Get the ip address of the host" )
3582 ipaddr = self.getIPAddress( host )
3583 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003584
Jon Halld80cc142015-07-06 13:36:05 -07003585 # remove IP from interface intf
3586 # Ex: h1 ifconfig h1-eth0 inet 0
3587 main.log.info( "Remove IP from interface " )
3588 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3589 self.handle.sendline( cmd2 )
3590 self.handle.expect( "mininet>" )
3591 response = self.handle.before
3592 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003593
Jon Halld80cc142015-07-06 13:36:05 -07003594 # create VLAN interface
3595 # Ex: h1 vconfig add h1-eth0 100
3596 main.log.info( "Create Vlan" )
3597 cmd3 = host + " vconfig add " + intf + " " + vlan
3598 self.handle.sendline( cmd3 )
3599 self.handle.expect( "mininet>" )
3600 response = self.handle.before
3601 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003602
Jon Halld80cc142015-07-06 13:36:05 -07003603 # assign the host's IP to the VLAN interface
3604 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3605 main.log.info( "Assign the host IP to the vlan interface" )
3606 vintf = intf + "." + vlan
3607 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3608 self.handle.sendline( cmd4 )
3609 self.handle.expect( "mininet>" )
3610 response = self.handle.before
3611 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003612
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003613 # update Mininet node variables
3614 main.log.info( "Update Mininet node variables" )
3615 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3616 self.handle.sendline( cmd5 )
3617 self.handle.expect( "mininet>" )
3618 response = self.handle.before
3619 main.log.info( "====> %s ", response )
3620
3621 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3622 self.handle.sendline( cmd6 )
3623 self.handle.expect( "mininet>" )
3624 response = self.handle.before
3625 main.log.info( "====> %s ", response )
3626
3627 return main.TRUE
3628 except pexpect.TIMEOUT:
3629 main.log.error( self.name + ": TIMEOUT exception found" )
3630 main.log.error( self.name + ": " + self.handle.before )
3631 main.cleanAndExit()
3632 except pexpect.EOF:
3633 main.log.error( self.name + ": EOF exception found" )
3634 main.log.error( self.name + ": " + self.handle.before )
3635 return main.FALSE
3636 except Exception:
3637 main.log.exception( self.name + ": Uncaught exception!" )
3638 return main.FALSE
3639
3640 def removeVLAN( self, host, intf ):
3641 """
3642 Remove vlan tag from a host.
3643 Dependencies:
3644 This class depends on the "vlan" package
3645 $ sudo apt-get install vlan
3646 Configuration:
3647 Load the 8021q module into the kernel
3648 $sudo modprobe 8021q
3649
3650 To make this setup permanent:
3651 $ sudo su -c 'echo "8021q" >> /etc/modules'
3652 """
3653 if self.handle:
3654 try:
3655 # get the ip address of the host
3656 main.log.info( "Get the ip address of the host" )
3657 ipaddr = self.getIPAddress( host )
3658
3659 # remove VLAN interface
3660 # Ex: h1 vconfig rem h1-eth0.100
3661 main.log.info( "Remove Vlan interface" )
3662 cmd2 = host + " vconfig rem " + intf
3663 self.handle.sendline( cmd2 )
3664 self.handle.expect( "mininet>" )
3665 response = self.handle.before
3666 main.log.info( "====> %s ", response )
3667
3668 # assign the host's IP to the original interface
3669 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3670 main.log.info( "Assign the host IP to the original interface" )
3671 original_intf = intf.split(".")[0]
3672 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3673 self.handle.sendline( cmd3 )
3674 self.handle.expect( "mininet>" )
3675 response = self.handle.before
3676 main.log.info( "====> %s ", response )
3677
3678 # update Mininet node variables
3679 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3680 self.handle.sendline( cmd4 )
3681 self.handle.expect( "mininet>" )
3682 response = self.handle.before
3683 main.log.info( "====> %s ", response )
3684
3685 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3686 self.handle.sendline( cmd5 )
3687 self.handle.expect( "mininet>" )
3688 response = self.handle.before
3689 main.log.info( "====> %s ", response )
3690
kaouthera3f13ca22015-05-05 15:01:41 -07003691 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003692 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003693 main.log.error( self.name + ": TIMEOUT exception found" )
3694 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003695 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003696 except pexpect.EOF:
3697 main.log.error( self.name + ": EOF exception found" )
3698 main.log.error( self.name + ": " + self.handle.before )
3699 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003700 except Exception:
3701 main.log.exception( self.name + ": Uncaught exception!" )
3702 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003703
Jon Hall892818c2015-10-20 17:58:34 -07003704 def createHostComponent( self, name ):
3705 """
3706 Creates a new mininet cli component with the same parameters as self.
3707 This new component is intended to be used to login to the hosts created
3708 by mininet.
3709
3710 Arguments:
3711 name - The string of the name of this component. The new component
3712 will be assigned to main.<name> .
3713 In addition, main.<name>.name = str( name )
3714 """
3715 try:
3716 # look to see if this component already exists
3717 getattr( main, name )
3718 except AttributeError:
3719 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003720 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3721 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003722 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003723 except pexpect.EOF:
3724 main.log.error( self.name + ": EOF exception found" )
3725 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003726 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003727 except Exception:
3728 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003729 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003730 else:
3731 # namespace is not clear!
3732 main.log.error( name + " component already exists!" )
3733 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003734 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003735
3736 def removeHostComponent( self, name ):
3737 """
3738 Remove host component
3739 Arguments:
3740 name - The string of the name of the component to delete.
3741 """
3742 try:
3743 # Get host component
3744 component = getattr( main, name )
3745 except AttributeError:
3746 main.log.error( "Component " + name + " does not exist." )
3747 return
3748 try:
3749 # Disconnect from component
3750 component.disconnect()
3751 # Delete component
3752 delattr( main, name )
3753 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003754 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003755 except pexpect.EOF:
3756 main.log.error( self.name + ": EOF exception found" )
3757 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003758 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003759 except Exception:
3760 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003761 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003762
3763 def startHostCli( self, host=None ):
3764 """
3765 Use the mininet m utility to connect to the host's cli
3766 """
3767 # These are fields that can be used by scapy packets. Initialized to None
3768 self.hostIp = None
3769 self.hostMac = None
3770 try:
3771 if not host:
3772 host = self.name
3773 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003774 self.handle.sendline( "cd" )
3775 self.handle.expect( self.hostPrompt )
3776 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003777 self.handle.expect( self.hostPrompt )
3778 return main.TRUE
3779 except pexpect.TIMEOUT:
3780 main.log.exception( self.name + ": Command timed out" )
3781 return main.FALSE
3782 except pexpect.EOF:
3783 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003784 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003785 except Exception:
3786 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003787 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003788
YPZhang801d46d2016-08-08 13:26:28 -07003789 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003790 '''
3791
YPZhang801d46d2016-08-08 13:26:28 -07003792 Args:
3793 devicename: switch name
3794 intf: port name on switch
3795 status: up or down
3796
3797 Returns: boolean to show success change status
3798
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003799 '''
YPZhang801d46d2016-08-08 13:26:28 -07003800 if status == "down" or status == "up":
3801 try:
3802 cmd = devicename + " ifconfig " + intf + " " + status
3803 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003804 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003805 return main.TRUE
3806 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003807 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003808 return main.FALSE
3809 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003810 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003811 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003812 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003813 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003814 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003815 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003816 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003817 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003818 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003819 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003820 return main.FALSE
3821
You Wang6e5b48e2018-07-23 16:17:38 -07003822 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003823 """
You Wang6e5b48e2018-07-23 16:17:38 -07003824 Moves a host from one switch to another on the fly
3825 Optional:
3826 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3827 prefixLen: length of the host IP prefix
3828 ipv6: move an IPv6 host if True
3829 intfSuffix: suffix of the new interface after host movement
3830 vlan: vlan ID of the host. Use None for non-vlan host
3831 Note: The intf between host and oldSw when detached
3832 using detach(), will still show up in the 'net'
3833 cmd, because switch.detach() doesn't affect switch.intfs[]
3834 ( which is correct behavior since the interfaces
3835 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003836 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003837 if self.handle:
3838 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003839 newIntf = "%s-%s" % ( host, intfSuffix )
3840 commands = [
3841 # Bring link between oldSw-host down
3842 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3843 # Determine hostintf and Oldswitchintf
3844 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3845 ]
3846 # Determine ip address of the host-oldSw interface
3847 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3848 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3849 commands += [
3850 # Determine mac address of the host-oldSw interface
3851 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3852 # Detach interface between oldSw-host
3853 "px " + oldSw + ".detach( sintf )",
3854 # Add link between host-newSw
3855 "py net.addLink(" + host + "," + newSw + ")",
3856 # Determine hostintf and Newswitchintf
3857 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3858 # Attach interface between newSw-host
3859 "px " + newSw + ".attach( sintf )",
3860 ]
3861 if vlan:
3862 vlanIntf = "%s.%s" % ( newIntf, vlan )
3863 commands += [
3864 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3865 host + " ip link set up %s" % vlanIntf,
3866 "px hintf.name = '" + vlanIntf + "'",
3867 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3868 ]
3869 newIntf = vlanIntf
3870 commands += [
3871 # Set mac address of the host-newSw interface
3872 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3873 # Set IP address of the host-newSw interface
3874 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3875 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3876 ]
3877 if ipv6:
3878 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3879 commands += [
3880 "net",
3881 host + " ifconfig"
3882 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003883 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003884 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003885 self.handle.sendline( cmd )
3886 self.handle.expect( "mininet>" )
3887 main.log.info( "====> %s ", self.handle.before )
3888 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003889 except pexpect.TIMEOUT:
3890 main.log.error( self.name + ": TIMEOUT exception found" )
3891 main.log.error( self.name + ": " + self.handle.before )
3892 main.cleanAndExit()
3893 except pexpect.EOF:
3894 main.log.error( self.name + ": EOF exception found" )
3895 main.log.error( self.name + ": " + self.handle.before )
3896 return main.FALSE
3897 except Exception:
3898 main.log.exception( self.name + ": Uncaught exception!" )
3899 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003900
You Wang6e5b48e2018-07-23 16:17:38 -07003901 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3902 macAddr=None, prefixLen=None, ipv6=False,
3903 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003904 """
You Wang6e5b48e2018-07-23 16:17:38 -07003905 Moves a dual-homed host from one switch-pair to another pair on the fly
3906 Optional:
3907 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3908 prefixLen: length of the host IP prefix
3909 ipv6: move an IPv6 host if True
3910 intfSuffix1: suffix of the first new interface
3911 intfSuffix2: suffix of the second new interface
3912 bondSuffix: suffix of the new bond interface
3913 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003914 """
You Wang7ea90582018-07-19 15:27:58 -07003915 if self.handle:
3916 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003917 bondIntf = "%s-%s" % ( host, bondSuffix )
3918 newIntf = "%s-%s" % ( host, intfSuffix1 )
3919 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003920 commands = [
3921 # Bring link between oldSw-host down
3922 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3923 # Bring link between oldPairSw-host down
3924 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3925 # Determine hostintf and Oldswitchintf
3926 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003927 ]
3928 # Determine ip address of the host-oldSw interface
3929 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3930 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3931 commands += [
3932 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003933 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3934 # Detach interface between oldSw-host
3935 "px " + oldSw + ".detach( sintf )",
3936 # Determine hostintf and Oldpairswitchintf
3937 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3938 # Detach interface between oldPairSw-host
3939 "px " + oldPairSw + ".detach( sintfpair )",
3940 # Add link between host-newSw
3941 "py net.addLink(" + host + "," + newSw + ", 2)",
3942 # Add link between host-newPairSw
3943 "py net.addLink(" + host + "," + newPairSw + ")",
3944 # Determine hostintf and Newswitchintf
3945 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3946 # Determine hostintf and NewPairswitchintf
3947 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3948 # Attach interface between newSw-host
3949 "px " + newSw + ".attach( sintf )",
3950 # Attach interface between newPairSw-host
3951 "px " + newPairSw + ".attach( sintfpair )",
3952 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07003953 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003954 host + ' ip link set %s down' % newIntf,
3955 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003956 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
3957 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07003958 host + ' ip addr flush dev %s' % newIntf,
3959 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003960 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003961 "px lowestIntf = min( [ hintf, hintfpair ] )",
3962 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07003963 "px lowestIntf.name = '" + bondIntf + "'",
3964 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07003965 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
3966 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07003967 ]
3968 if vlan:
3969 vlanIntf = "%s.%s" % ( bondIntf, vlan )
3970 commands += [
3971 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
3972 host + " ip link set up %s" % vlanIntf,
3973 "px lowestIntf.name = '" + vlanIntf + "'",
3974 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
3975 ]
3976 bondIntf = vlanIntf
3977 commands += [
3978 # Set macaddress of the host-newSw interface
3979 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07003980 # Set ipaddress of the host-newSw interface
3981 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
3982 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07003983 ]
You Wang6e5b48e2018-07-23 16:17:38 -07003984 if ipv6:
3985 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
3986 commands += [
3987 "net",
3988 host + " ifconfig"
3989 ]
You Wang7ea90582018-07-19 15:27:58 -07003990 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003991 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07003992 self.handle.sendline( cmd )
3993 self.handle.expect( "mininet>" )
3994 main.log.info( "====> %s ", self.handle.before )
3995 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07003996 except pexpect.TIMEOUT:
3997 main.log.error( self.name + ": TIMEOUT exception found" )
3998 main.log.error( self.name + ": " + self.handle.before )
3999 main.cleanAndExit()
4000 except pexpect.EOF:
4001 main.log.error( self.name + ": EOF exception found" )
4002 main.log.error( self.name + ": " + self.handle.before )
4003 return main.FALSE
4004 except Exception:
4005 main.log.exception( self.name + ": Uncaught exception!" )
4006 return main.FALSE
4007
adminbae64d82013-08-01 10:50:15 -07004008if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004009 sys.modules[ __name__ ] = MininetCliDriver()