1
2 """
3 Created on 26-Oct-2012
4
5 author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
6
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 ( at your option ) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20
21 MininetCliDriver is the basic driver which will handle the Mininet functions
22
23 Some functions rely on a modified version of Mininet. These functions
24 should all be noted in the comments. To get this MN version run these commands
25 from within your Mininet folder:
26 git remote add jhall11 https://github.com/jhall11/mininet.git
27 git fetch jhall11
28 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
29 git pull
30
31
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
33 changed when switching branches."""
34 import pexpect
35 import re
36 import sys
37 import types
38 import os
39 from math import pow
40 from drivers.common.cli.emulatordriver import Emulator
41
42
44
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
49 super( Emulator, self ).__init__()
50 self.handle = self
51 self.name = None
52 self.wrapped = sys.modules[ __name__ ]
53 self.flag = 0
54
55 - def connect( self, **connectargs ):
56 """
57 Here the main is the TestON instance after creating
58 all the log handles."""
59 try:
60 for key in connectargs:
61 vars( self )[ key ] = connectargs[ key ]
62
63 self.name = self.options[ 'name' ]
64
65 try:
66 if os.getenv( str( self.ip_address ) ) != None:
67 self.ip_address = os.getenv( str( self.ip_address ) )
68 else:
69 main.log.info( self.name +
70 ": Trying to connect to " +
71 self.ip_address )
72
73 except KeyError:
74 main.log.info( "Invalid host name," +
75 " connecting to local host instead" )
76 self.ip_address = 'localhost'
77 except Exception as inst:
78 main.log.error( "Uncaught exception: " + str( inst ) )
79
80 self.handle = super(
81 MininetCliDriver,
82 self ).connect(
83 user_name=self.user_name,
84 ip_address=self.ip_address,
85 port=None,
86 pwd=self.pwd )
87
88 if self.handle:
89 main.log.info( "Connection successful to the host " +
90 self.user_name +
91 "@" +
92 self.ip_address )
93 return main.TRUE
94 else:
95 main.log.error( "Connection failed to the host " +
96 self.user_name +
97 "@" +
98 self.ip_address )
99 main.log.error( "Failed to connect to the Mininet CLI" )
100 return main.FALSE
101 except pexpect.EOF:
102 main.log.error( self.name + ": EOF exception found" )
103 main.log.error( self.name + ": " + self.handle.before )
104 main.cleanup()
105 main.exit()
106 except Exception:
107 main.log.exception( self.name + ": Uncaught exception!" )
108 main.cleanup()
109 main.exit()
110
111 - def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
112 """
113 Description:
114 Starts Mininet accepts a topology(.py) file and/or an optional
115 argument, to start the mininet, as a parameter.
116 Can also send regular mininet command to load up desired topology.
117 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
118 Options:
119 topoFile = file path for topology file (.py)
120 args = extra option added when starting the topology from the file
121 mnCmd = Mininet command use to start topology
122 Returns:
123 main.TRUE if the mininet starts successfully, main.FALSE
124 otherwise
125 """
126 if self.handle:
127
128 main.log.info( self.name +
129 ": Clearing any residual state or processes" )
130 self.handle.sendline( "sudo mn -c" )
131 i = self.handle.expect( [ 'password\sfor\s',
132 'Cleanup\scomplete',
133 pexpect.EOF,
134 pexpect.TIMEOUT ],
135 timeout )
136 if i == 0:
137
138 main.log.info( self.name + ": Sending sudo password" )
139 self.handle.sendline( self.pwd )
140 i = self.handle.expect( [ '%s:' % self.user,
141 '\$',
142 pexpect.EOF,
143 pexpect.TIMEOUT ],
144 timeout )
145 if i == 1:
146 main.log.info( self.name + ": Clean" )
147 elif i == 2:
148 main.log.error( self.name + ": Connection terminated" )
149 elif i == 3:
150 main.log.error( self.name + ": Something while cleaning " +
151 "Mininet took too long... " )
152
153 cmdString = "sudo "
154 if not mnCmd:
155 if topoFile is None or topoFile == '':
156 main.log.info( self.name + ": building fresh Mininet" )
157 cmdString += "mn "
158 if args is None or args == '':
159
160 args = self.options[ 'arg1' ] +\
161 " " + self.options[ 'arg2' ] +\
162 " --mac --controller " +\
163 self.options[ 'controller' ] + " " +\
164 self.options[ 'arg3' ]
165 else:
166 pass
167
168 else:
169 main.log.info(
170 "Starting Mininet from topo file " +
171 topoFile )
172 cmdString += topoFile + " "
173 if args is None:
174 args = ''
175
176 cmdString += args
177 else:
178 main.log.info( "Starting Mininet topology using '" + mnCmd +
179 "' command" )
180 cmdString += mnCmd
181
182 self.handle.sendline( "" )
183 self.handle.expect( '\$' )
184 main.log.info( "Sending '" + cmdString + "' to " + self.name )
185 self.handle.sendline( cmdString )
186 while True:
187 i = self.handle.expect( [ 'mininet>',
188 'Exception',
189 '\*\*\*',
190 pexpect.EOF,
191 pexpect.TIMEOUT ],
192 timeout )
193 if i == 0:
194 main.log.info( self.name + ": Mininet built" )
195 return main.TRUE
196 elif i == 1:
197 response = str( self.handle.before +
198 self.handle.after )
199 self.handle.expect( '\$' )
200 response += str( self.handle.before +
201 self.handle.after )
202 main.log.error(
203 self.name +
204 ": Launching Mininet failed: " + response )
205 return main.FALSE
206 elif i == 2:
207 self.handle.expect( [ "\n",
208 pexpect.EOF,
209 pexpect.TIMEOUT ],
210 timeout )
211 main.log.info( self.handle.before )
212 elif i == 3:
213 main.log.error( self.name + ": Connection timeout" )
214 return main.FALSE
215 elif i == 4:
216 main.log.error(
217 self.name +
218 ": Something took too long... " )
219 return main.FALSE
220
221 main.log.error( "startNet did not return correctly" )
222 return main.FASLE
223 else:
224 main.log.error( self.name + ": Connection failed to the host " +
225 self.user_name + "@" + self.ip_address )
226 main.log.error( self.name + ": Failed to connect to the Mininet" )
227 return main.FALSE
228
230 if topoType == 'tree':
231
232 if fanout is None:
233 fanout = 2
234 k = 0
235 count = 0
236 while( k <= depth - 1 ):
237 count = count + pow( fanout, k )
238 k = k + 1
239 numSwitches = count
240 while( k <= depth - 2 ):
241
242
243
244 count = count + pow( fanout, k )
245 k = k + 1
246 numLinks = count * fanout
247
248
249
250 elif topoType == 'linear':
251
252
253 if fanout is None:
254 fanout = 1
255 numSwitches = depth
256 numHostsPerSw = fanout
257 totalNumHosts = numSwitches * numHostsPerSw
258 numLinks = totalNumHosts + ( numSwitches - 1 )
259 print "num_switches for %s(%d,%d) = %d and links=%d" %\
260 ( topoType, depth, fanout, numSwitches, numLinks )
261 topoDict = { "num_switches": int( numSwitches ),
262 "num_corelinks": int( numLinks ) }
263 return topoDict
264
266 """
267 Calculate the number of switches and links in a topo."""
268
269 argList = self.options[ 'arg1' ].split( "," )
270 topoArgList = argList[ 0 ].split( " " )
271 argList = map( int, argList[ 1: ] )
272 topoArgList = topoArgList[ 1: ] + argList
273
274 topoDict = self.numSwitchesNlinks( *topoArgList )
275 return topoDict
276
277 - def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0 ):
278 """
279 Verifies the reachability of the hosts using pingall command.
280 Optional parameter timeout allows you to specify how long to
281 wait for pingall to complete
282 Optional:
283 timeout( seconds ) - How long to wait before breaking the pingall
284 shortCircuit - Break the pingall based on the number of failed hosts
285 ping
286 acceptableFailed - Set the number of acceptable failed pings for the
287 function to still return main.TRUE
288 Returns:
289 main.TRUE if pingall completes with no pings dropped
290 otherwise main.FALSE
291 """
292 import time
293 try:
294 timeout = int( timeout )
295 if self.handle:
296 main.log.info(
297 self.name +
298 ": Checking reachabilty to the hosts using pingall" )
299 response = ""
300 failedPings = 0
301 returnValue = main.TRUE
302 self.handle.sendline( "pingall" )
303 startTime = time.time()
304 while True:
305 i = self.handle.expect( [ "mininet>", "X",
306 pexpect.EOF,
307 pexpect.TIMEOUT ],
308 timeout )
309 if i == 0:
310 main.log.info( self.name + ": pingall finished" )
311 response += self.handle.before
312 break
313 elif i == 1:
314 response += self.handle.before + self.handle.after
315 failedPings = failedPings + 1
316 if failedPings > acceptableFailed:
317 returnValue = main.FALSE
318 if shortCircuit:
319 main.log.error( self.name +
320 ": Aborting pingall - "
321 + str( failedPings ) +
322 " pings failed" )
323 break
324 if ( time.time() - startTime ) > timeout:
325 returnValue = main.FALSE
326 main.log.error( self.name +
327 ": Aborting pingall - " +
328 "Function took too long " )
329 break
330 elif i == 2:
331 main.log.error( self.name +
332 ": EOF exception found" )
333 main.log.error( self.name + ": " +
334 self.handle.before )
335 main.cleanup()
336 main.exit()
337 elif i == 3:
338 response += self.handle.before
339 main.log.error( self.name +
340 ": TIMEOUT exception found" )
341 main.log.error( self.name +
342 ": " +
343 str( response ) )
344
345 self.handle.sendline( "\x03" )
346 self.handle.expect( "Interrupt" )
347 self.handle.expect( "mininet>" )
348 break
349 pattern = "Results\:"
350 main.log.info( "Pingall output: " + str( response ) )
351 if re.search( pattern, response ):
352 main.log.info( self.name + ": Pingall finished with "
353 + str( failedPings ) + " failed pings" )
354 return returnValue
355 else:
356
357 self.handle.sendline( "\x03" )
358 self.handle.expect( "Interrupt" )
359 self.handle.expect( "mininet>" )
360 return main.FALSE
361 else:
362 main.log.error( self.name + ": Connection failed to the host" )
363 main.cleanup()
364 main.exit()
365 except pexpect.TIMEOUT:
366 if response:
367 main.log.info( "Pingall output: " + str( response ) )
368 main.log.error( self.name + ": pexpect.TIMEOUT found" )
369 return main.FALSE
370 except pexpect.EOF:
371 main.log.error( self.name + ": EOF exception found" )
372 main.log.error( self.name + ": " + self.handle.before )
373 main.cleanup()
374 main.exit()
375
377 """
378 Uses the fping package for faster pinging...
379 *requires fping to be installed on machine running mininet"""
380 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
381 command = args[ "SRC" ] + \
382 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
383 self.handle.sendline( command )
384 self.handle.expect(
385 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
386 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
387 response = self.handle.before
388 if re.search( ":\s-", response ):
389 main.log.info( self.name + ": Ping fail" )
390 return main.FALSE
391 elif re.search( ":\s\d{1,2}\.\d\d", response ):
392 main.log.info( self.name + ": Ping good!" )
393 return main.TRUE
394 main.log.info( self.name + ": Install fping on mininet machine... " )
395 main.log.info( self.name + ": \n---\n" + response )
396 return main.FALSE
397
399 """
400 Ping all specified IPv4 hosts
401
402 Acceptable hostList:
403 - [ 'h1','h2','h3','h4' ]
404
405 Returns main.TRUE if all hosts specified can reach
406 each other
407
408 Returns main.FALSE if one or more of hosts specified
409 cannot reach each other"""
410
411 cmd = " ping -c 1 -i 1 -W 8 "
412
413 try:
414 main.log.info( "Testing reachability between specified hosts" )
415
416 isReachable = main.TRUE
417
418 for host in hostList:
419 listIndex = hostList.index( host )
420
421 pingList = hostList[ :listIndex ] + \
422 hostList[ ( listIndex + 1 ): ]
423
424 for temp in pingList:
425
426 pingCmd = str( host ) + cmd + str( temp )
427 self.handle.sendline( pingCmd )
428 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
429 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
430 response = self.handle.before
431 if re.search( ',\s0\%\spacket\sloss', response ):
432 main.log.info( str( host ) + " -> " + str( temp ) )
433 else:
434 main.log.info(
435 str( host ) + " -> X (" + str( temp ) + ") "
436 " Destination Unreachable" )
437
438 isReachable = main.FALSE
439
440 return isReachable
441
442 except pexpect.EOF:
443 main.log.error( self.name + ": EOF exception found" )
444 main.log.error( self.name + ": " + self.handle.before )
445 main.cleanup()
446 main.exit()
447
449 """
450 IPv6 ping all hosts in hostList. If no prefix passed this will use
451 default prefix of 1000::
452
453 Returns main.TRUE if all hosts specified can reach each other
454
455 Returns main.FALSE if one or more of hosts specified cannot reach each other
456 """
457 try:
458 main.log.info( "Testing reachability between specified IPv6 hosts" )
459 isReachable = main.TRUE
460 cmd = " ping6 -c 1 -i 1 -W 8 "
461 for host in hostList:
462 listIndex = hostList.index( host )
463
464 pingList = hostList[ :listIndex ] + \
465 hostList[ ( listIndex + 1 ): ]
466
467 for temp in pingList:
468
469 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
470 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
471 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
472 response = self.handle.before
473 if re.search( ',\s0\%\spacket\sloss', response ):
474 main.log.info( str( host ) + " -> " + str( temp ) )
475 else:
476 main.log.info(
477 str( host ) + " -> X (" + str( temp ) + ") "
478 " Destination Unreachable" )
479 main.log.error( "Response from Mininet: " + str( response ) )
480
481 isReachable = main.FALSE
482 return isReachable
483
484 except pexpect.EOF:
485 main.log.error( self.name + ": EOF exception found" )
486 main.log.error( self.name + ": " + self.handle.before )
487 main.cleanup()
488 main.exit()
489
491 """
492 Ping from one mininet host to another
493 Currently the only supported Params: SRC and TARGET"""
494 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
495 command = args[ "SRC" ] + " ping " + \
496 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
497 try:
498 main.log.info( "Sending: " + command )
499 self.handle.sendline( command )
500 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
501 if i == 1:
502 main.log.error(
503 self.name +
504 ": timeout when waiting for response from mininet" )
505 main.log.error( "response: " + str( self.handle.before ) )
506 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
507 if i == 1:
508 main.log.error(
509 self.name +
510 ": timeout when waiting for response from mininet" )
511 main.log.error( "response: " + str( self.handle.before ) )
512 response = self.handle.before
513 except pexpect.EOF:
514 main.log.error( self.name + ": EOF exception found" )
515 main.log.error( self.name + ": " + self.handle.before )
516 main.cleanup()
517 main.exit()
518 main.log.info( self.name + ": Ping Response: " + response )
519 if re.search( ',\s0\%\spacket\sloss', response ):
520 main.log.info( self.name + ": no packets lost, host is reachable" )
521 main.lastResult = main.TRUE
522 return main.TRUE
523 else:
524 main.log.error(
525 self.name +
526 ": PACKET LOST, HOST IS NOT REACHABLE" )
527 main.lastResult = main.FALSE
528 return main.FALSE
529
531 """
532 Verifies the host's ip configured or not."""
533 if self.handle:
534 try:
535 response = self.execute(
536 cmd=host +
537 " ifconfig",
538 prompt="mininet>",
539 timeout=10 )
540 except pexpect.EOF:
541 main.log.error( self.name + ": EOF exception found" )
542 main.log.error( self.name + ": " + self.handle.before )
543 main.cleanup()
544 main.exit()
545
546 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
547 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
548 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
549 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
550 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
551 "[0-9]|25[0-5]|[0-9]{1,2})"
552
553 if re.search( pattern, response ):
554 main.log.info( self.name + ": Host Ip configured properly" )
555 return main.TRUE
556 else:
557 main.log.error( self.name + ": Host IP not found" )
558 return main.FALSE
559 else:
560 main.log.error( self.name + ": Connection failed to the host" )
561
563
564 try:
565 response = self.execute(
566 cmd="h1 /usr/sbin/sshd -D&",
567 prompt="mininet>",
568 timeout=10 )
569 response = self.execute(
570 cmd="h4 /usr/sbin/sshd -D&",
571 prompt="mininet>",
572 timeout=10 )
573 for key in connectargs:
574 vars( self )[ key ] = connectargs[ key ]
575 response = self.execute(
576 cmd="xterm h1 h4 ",
577 prompt="mininet>",
578 timeout=10 )
579 except pexpect.EOF:
580 main.log.error( self.name + ": EOF exception found" )
581 main.log.error( self.name + ": " + self.handle.before )
582 main.cleanup()
583 main.exit()
584 import time
585 time.sleep( 20 )
586 if self.flag == 0:
587 self.flag = 1
588 return main.FALSE
589 else:
590 return main.TRUE
591
592 - def moveHost( self, host, oldSw, newSw, ):
593 """
594 Moves a host from one switch to another on the fly
595 Note: The intf between host and oldSw when detached
596 using detach(), will still show up in the 'net'
597 cmd, because switch.detach() doesn't affect switch.intfs[]
598 ( which is correct behavior since the interfaces
599 haven't moved ).
600 """
601 if self.handle:
602 try:
603
604 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
605 "'," + "'down')"
606 print "cmd1= ", cmd
607 response = self.execute( cmd=cmd,
608 prompt="mininet>",
609 timeout=10 )
610
611
612 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
613 ")[0]"
614 print "cmd2= ", cmd
615 self.handle.sendline( cmd )
616 self.handle.expect( "mininet>" )
617
618
619 cmd = "px ipaddr = hintf.IP()"
620 print "cmd3= ", cmd
621 self.handle.sendline( cmd )
622 self.handle.expect( "mininet>" )
623
624 cmd = "px macaddr = hintf.MAC()"
625 print "cmd3= ", cmd
626 self.handle.sendline( cmd )
627 self.handle.expect( "mininet>" )
628
629
630 cmd = "px " + oldSw + ".detach( sintf )"
631 print "cmd4= ", cmd
632 self.handle.sendline( cmd )
633 self.handle.expect( "mininet>" )
634
635
636 cmd = "py net.addLink(" + host + "," + newSw + ")"
637 print "cmd5= ", cmd
638 self.handle.sendline( cmd )
639 self.handle.expect( "mininet>" )
640
641
642 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
643 ")[0]"
644 print "cmd6= ", cmd
645 self.handle.sendline( cmd )
646 self.handle.expect( "mininet>" )
647
648
649 cmd = "px " + newSw + ".attach( sintf )"
650 print "cmd3= ", cmd
651 self.handle.sendline( cmd )
652 self.handle.expect( "mininet>" )
653
654
655 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
656 print "cmd7 = ", cmd
657 self.handle.sendline( cmd )
658 self.handle.expect( "mininet>" )
659
660
661 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
662 print "cmd8 = ", cmd
663 self.handle.sendline( cmd )
664 self.handle.expect( "mininet>" )
665
666 cmd = "net"
667 print "cmd9 = ", cmd
668 self.handle.sendline( cmd )
669 self.handle.expect( "mininet>" )
670 print "output = ", self.handle.before
671
672
673 cmd = host + " ifconfig"
674 print "cmd10= ", cmd
675 self.handle.sendline( cmd )
676 self.handle.expect( "mininet>" )
677 print "ifconfig o/p = ", self.handle.before
678
679 return main.TRUE
680 except pexpect.EOF:
681 main.log.error( self.name + ": EOF exception found" )
682 main.log.error( self.name + ": " + self.handle.before )
683 return main.FALSE
684
685 - def changeIP( self, host, intf, newIP, newNetmask ):
686 """
687 Changes the ip address of a host on the fly
688 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
689 if self.handle:
690 try:
691 cmd = host + " ifconfig " + intf + " " + \
692 newIP + " " + 'netmask' + " " + newNetmask
693 self.handle.sendline( cmd )
694 self.handle.expect( "mininet>" )
695 response = self.handle.before
696 main.log.info( "response = " + response )
697 main.log.info(
698 "Ip of host " +
699 host +
700 " changed to new IP " +
701 newIP )
702 return main.TRUE
703 except pexpect.EOF:
704 main.log.error( self.name + ": EOF exception found" )
705 main.log.error( self.name + ": " + self.handle.before )
706 return main.FALSE
707
709 """
710 Changes the default gateway of a host
711 Ex: h1 route add default gw 10.0.1.2"""
712 if self.handle:
713 try:
714 cmd = host + " route add default gw " + newGW
715 self.handle.sendline( cmd )
716 self.handle.expect( "mininet>" )
717 response = self.handle.before
718 main.log.info( "response = " + response )
719 main.log.info(
720 "Default gateway of host " +
721 host +
722 " changed to " +
723 newGW )
724 return main.TRUE
725 except pexpect.EOF:
726 main.log.error( self.name + ": EOF exception found" )
727 main.log.error( self.name + ": " + self.handle.before )
728 return main.FALSE
729
731 """
732 Changes the mac address of a gateway host"""
733 if self.handle:
734 try:
735
736 cmd = host + " arp -s " + GW + " " + macaddr
737 self.handle.sendline( cmd )
738 self.handle.expect( "mininet>" )
739 response = self.handle.before
740 main.log.info( "response = " + response )
741 main.log.info(
742 "Mac address of gateway " +
743 GW +
744 " changed to " +
745 macaddr )
746 return main.TRUE
747 except pexpect.EOF:
748 main.log.error( self.name + ": EOF exception found" )
749 main.log.error( self.name + ": " + self.handle.before )
750 return main.FALSE
751
753 """
754 Verify if the static gateway and mac address assignment"""
755 if self.handle:
756 try:
757
758 cmd = host + " arp -an "
759 self.handle.sendline( cmd )
760 self.handle.expect( "mininet>" )
761 response = self.handle.before
762 main.log.info( host + " arp -an = " + response )
763 return main.TRUE
764 except pexpect.EOF:
765 main.log.error( self.name + ": EOF exception found" )
766 main.log.error( self.name + ": " + self.handle.before )
767 return main.FALSE
768
770 """
771 Verifies the host's ip configured or not."""
772 if self.handle:
773 try:
774 response = self.execute(
775 cmd=host +
776 " ifconfig",
777 prompt="mininet>",
778 timeout=10 )
779 except pexpect.EOF:
780 main.log.error( self.name + ": EOF exception found" )
781 main.log.error( self.name + ": " + self.handle.before )
782 main.cleanup()
783 main.exit()
784
785 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
786 macAddressSearch = re.search( pattern, response, re.I )
787 macAddress = macAddressSearch.group().split( " " )[ 1 ]
788 main.log.info(
789 self.name +
790 ": Mac-Address of Host " +
791 host +
792 " is " +
793 macAddress )
794 return macAddress
795 else:
796 main.log.error( self.name + ": Connection failed to the host" )
797
799 """
800 Return the IP address of the interface on the given host"""
801 if self.handle:
802 try:
803 response = self.execute( cmd=host + " ifconfig " + interface,
804 prompt="mininet>", timeout=10 )
805 except pexpect.EOF:
806 main.log.error( self.name + ": EOF exception found" )
807 main.log.error( self.name + ": " + self.handle.before )
808 main.cleanup()
809 main.exit()
810
811 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
812 macAddressSearch = re.search( pattern, response, re.I )
813 if macAddressSearch is None:
814 main.log.info( "No mac address found in %s" % response )
815 return main.FALSE
816 macAddress = macAddressSearch.group().split( " " )[ 1 ]
817 main.log.info(
818 "Mac-Address of " +
819 host +
820 ":" +
821 interface +
822 " is " +
823 macAddress )
824 return macAddress
825 else:
826 main.log.error( "Connection failed to the host" )
827
829 """
830 Verifies the host's ip configured or not."""
831 if self.handle:
832 try:
833 response = self.execute(
834 cmd=host +
835 " ifconfig",
836 prompt="mininet>",
837 timeout=10 )
838 except pexpect.EOF:
839 main.log.error( self.name + ": EOF exception found" )
840 main.log.error( self.name + ": " + self.handle.before )
841 main.cleanup()
842 main.exit()
843
844 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
845 ipAddressSearch = re.search( pattern, response )
846 main.log.info(
847 self.name +
848 ": IP-Address of Host " +
849 host +
850 " is " +
851 ipAddressSearch.group( 1 ) )
852 return ipAddressSearch.group( 1 )
853 else:
854 main.log.error( self.name + ": Connection failed to the host" )
855
857 """
858 return the datapath ID of the switch"""
859 if self.handle:
860 cmd = "py %s.dpid" % switch
861 try:
862 response = self.execute(
863 cmd=cmd,
864 prompt="mininet>",
865 timeout=10 )
866 except pexpect.EOF:
867 main.log.error( self.name + ": EOF exception found" )
868 main.log.error( self.name + ": " + self.handle.before )
869 main.cleanup()
870 main.exit()
871 pattern = r'^(?P<dpid>\w)+'
872 result = re.search( pattern, response, re.MULTILINE )
873 if result is None:
874 main.log.info(
875 "Couldn't find DPID for switch %s, found: %s" %
876 ( switch, response ) )
877 return main.FALSE
878 return str( result.group( 0 ) ).lower()
879 else:
880 main.log.error( "Connection failed to the host" )
881
883 if self.handle:
884 self.handle.sendline( "" )
885 self.expect( "mininet>" )
886 cmd = "py %s.dpid" % switch
887 try:
888 response = self.execute(
889 cmd=cmd,
890 prompt="mininet>",
891 timeout=10 )
892 self.handle.expect( "mininet>" )
893 response = self.handle.before
894 return response
895 except pexpect.EOF:
896 main.log.error( self.name + ": EOF exception found" )
897 main.log.error( self.name + ": " + self.handle.before )
898 main.cleanup()
899 main.exit()
900
902 """
903 return information dict about interfaces connected to the node"""
904 if self.handle:
905 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
906 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
907 cmd += ' for i in %s.intfs.values()])' % node
908 try:
909 response = self.execute(
910 cmd=cmd,
911 prompt="mininet>",
912 timeout=10 )
913 except pexpect.EOF:
914 main.log.error( self.name + ": EOF exception found" )
915 main.log.error( self.name + ": " + self.handle.before )
916 main.cleanup()
917 main.exit()
918 return response
919 else:
920 main.log.error( "Connection failed to the node" )
921
923 main.log.info( self.name + ": Dump node info" )
924 try:
925 response = self.execute(
926 cmd='dump',
927 prompt='mininet>',
928 timeout=10 )
929 except pexpect.EOF:
930 main.log.error( self.name + ": EOF exception found" )
931 main.log.error( self.name + ": " + self.handle.before )
932 main.cleanup()
933 main.exit()
934 return response
935
937 main.log.info( self.name + ": List interfaces" )
938 try:
939 response = self.execute(
940 cmd='intfs',
941 prompt='mininet>',
942 timeout=10 )
943 except pexpect.EOF:
944 main.log.error( self.name + ": EOF exception found" )
945 main.log.error( self.name + ": " + self.handle.before )
946 main.cleanup()
947 main.exit()
948 return response
949
951 main.log.info( self.name + ": List network connections" )
952 try:
953 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
954 except pexpect.EOF:
955 main.log.error( self.name + ": EOF exception found" )
956 main.log.error( self.name + ": " + self.handle.before )
957 main.cleanup()
958 main.exit()
959 return response
960
962 main.log.info( self.name + ": List network links" )
963 try:
964 response = self.execute( cmd='links', prompt='mininet>',
965 timeout=10 )
966 except pexpect.EOF:
967 main.log.error( self.name + ": EOF exception found" )
968 main.log.error( self.name + ": " + self.handle.before )
969 main.cleanup()
970 main.exit()
971 return response
972
974 '''
975 Runs the iperftcp function with a given set of hosts and specified timeout.
976
977 @parm:
978 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
979 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
980 '''
981 for host1 in hosts:
982 for host2 in hosts:
983 if host1 != host2:
984 if self.iperftcp(host1, host2, timeout) == main.FALSE:
985 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
986
987 - def iperftcp(self, host1="h1", host2="h2", timeout=6):
988 '''
989 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
990 are valid.
991
992 @parm:
993 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
994 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
995 '''
996 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
997 try:
998
999 cmd1 = 'iperf ' + host1 + " " + host2
1000 self.handle.sendline( cmd1 )
1001 outcome = self.handle.expect( "mininet>", timeout )
1002 response = self.handle.before
1003
1004
1005 if "Results:" in response:
1006 main.log.report(self.name + ": iperf test completed")
1007
1008 response = response.split("\r\n")
1009 response = response[len(response)-2]
1010 response = response.split(": ")
1011 response = response[len(response)-1]
1012 response = response.replace("[", "")
1013 response = response.replace("]", "")
1014 response = response.replace("\'", "")
1015
1016
1017 bandwidth = response.split(", ")
1018
1019
1020
1021 if len(bandwidth) == 2:
1022 main.log.report(self.name + ": iperf test successful")
1023 return main.TRUE
1024 else:
1025 main.log.error(self.name + ": invalid iperf results")
1026 return main.FALSE
1027 else:
1028 main.log.error( self.name + ": iperf test failed" )
1029 return main.FALSE
1030
1031 except pexpect.TIMEOUT:
1032 main.log.error( self.name + ": TIMEOUT exception found")
1033 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1034 return main.FALSE
1035
1036 except pexpect.EOF:
1037 main.log.error( self.name + ": EOF exception found" )
1038 main.log.error( self.name + ": " + self.handle.before )
1039 main.cleanup()
1040 main.exit()
1041
1043 '''
1044 Runs the iperfudp function with a given set of hosts and specified
1045 bandwidth
1046
1047 @param:
1048 bandwidth: the targeted bandwidth, in megabits ('M')
1049 '''
1050 for host1 in hosts:
1051 for host2 in hosts:
1052 if host1 != host2:
1053 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1054 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1055
1056 - def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1057
1058 '''
1059 Creates an iperf UDP test with a specific bandwidth.
1060 Returns true if results are valid.
1061
1062 @param:
1063 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1064 '''
1065 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1066 try:
1067
1068 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1069 self.handle.sendline(cmd)
1070 self.handle.expect("mininet>")
1071 response = self.handle.before
1072
1073
1074 if "Results:" in response:
1075 main.log.report(self.name + ": iperfudp test completed")
1076
1077 response = response.split("\r\n")
1078 response = response[len(response)-2]
1079 response = response.split(": ")
1080 response = response[len(response)-1]
1081 response = response.replace("[", "")
1082 response = response.replace("]", "")
1083 response = response.replace("\'", "")
1084
1085 mnBandwidth = response.split(", ")
1086
1087
1088
1089 if len(mnBandwidth) == 3:
1090
1091 for item in mnBandwidth:
1092 if item == "":
1093 main.log.error(self.name + ": Could not parse iperf output")
1094 main.log.error(self.name + ": invalid iperfudp results")
1095 return main.FALSE
1096
1097 main.log.report(self.name + ": iperfudp test successful")
1098 return main.TRUE
1099 else:
1100 main.log.error(self.name + ": invalid iperfudp results")
1101 return main.FALSE
1102
1103 except pexpect.EOF:
1104 main.log.error( self.name + ": EOF exception found" )
1105 main.log.error( self.name + ": " + self.handle.before )
1106 main.cleanup()
1107 main.exit()
1108
1110 main.log.info( self.name + ": List all nodes." )
1111 try:
1112 response = self.execute(
1113 cmd='nodes',
1114 prompt='mininet>',
1115 timeout=10 )
1116 except pexpect.EOF:
1117 main.log.error( self.name + ": EOF exception found" )
1118 main.log.error( self.name + ": " + self.handle.before )
1119 main.cleanup()
1120 main.exit()
1121 return response
1122
1124 main.log.info( self.name + ": Ping between first two hosts" )
1125 try:
1126 response = self.execute(
1127 cmd='pingpair',
1128 prompt='mininet>',
1129 timeout=20 )
1130 except pexpect.EOF:
1131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
1133 main.cleanup()
1134 main.exit()
1135
1136 if re.search( ',\s0\%\spacket\sloss', response ):
1137 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
1138 main.lastResult = main.TRUE
1139 return main.TRUE
1140 else:
1141 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
1142 main.lastResult = main.FALSE
1143 return main.FALSE
1144
1145 - def link( self, **linkargs ):
1146 """
1147 Bring link( s ) between two nodes up or down"""
1148 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1149 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1150 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1151 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1152 main.log.info(
1153 "Bring link between '" +
1154 end1 +
1155 "' and '" +
1156 end2 +
1157 "' '" +
1158 option +
1159 "'" )
1160 command = "link " + \
1161 str( end1 ) + " " + str( end2 ) + " " + str( option )
1162 try:
1163 self.handle.sendline( command )
1164 self.handle.expect( "mininet>" )
1165 except pexpect.EOF:
1166 main.log.error( self.name + ": EOF exception found" )
1167 main.log.error( self.name + ": " + self.handle.before )
1168 main.cleanup()
1169 main.exit()
1170 return main.TRUE
1171
1172 - def yank( self, **yankargs ):
1173 """
1174 yank a mininet switch interface to a host"""
1175 main.log.info( 'Yank the switch interface attached to a host' )
1176 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
1177 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1178 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1179 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
1180 try:
1181 response = self.execute(
1182 cmd=command,
1183 prompt="mininet>",
1184 timeout=10 )
1185 except pexpect.EOF:
1186 main.log.error( self.name + ": EOF exception found" )
1187 main.log.error( self.name + ": " + self.handle.before )
1188 main.cleanup()
1189 main.exit()
1190 return main.TRUE
1191
1192 - def plug( self, **plugargs ):
1193 """
1194 plug the yanked mininet switch interface to a switch"""
1195 main.log.info( 'Plug the switch interface attached to a switch' )
1196 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
1197 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1198 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1199 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
1200 try:
1201 response = self.execute(
1202 cmd=command,
1203 prompt="mininet>",
1204 timeout=10 )
1205 except pexpect.EOF:
1206 main.log.error( self.name + ": EOF exception found" )
1207 main.log.error( self.name + ": " + self.handle.before )
1208 main.cleanup()
1209 main.exit()
1210 return main.TRUE
1211
1212 - def dpctl( self, **dpctlargs ):
1213 """
1214 Run dpctl command on all switches."""
1215 main.log.info( 'Run dpctl command on all switches' )
1216 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
1217 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1218 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1219 command = "dpctl " + cmd + " " + str( cmdargs )
1220 try:
1221 response = self.execute(
1222 cmd=command,
1223 prompt="mininet>",
1224 timeout=10 )
1225 except pexpect.EOF:
1226 main.log.error( self.name + ": EOF exception found" )
1227 main.log.error( self.name + ": " + self.handle.before )
1228 main.cleanup()
1229 main.exit()
1230 return main.TRUE
1231
1233
1234
1235 fileInput = path + '/lib/Mininet/INSTALL'
1236 version = super( Mininet, self ).getVersion()
1237 pattern = 'Mininet\s\w\.\w\.\w\w*'
1238 for line in open( fileInput, 'r' ).readlines():
1239 result = re.match( pattern, line )
1240 if result:
1241 version = result.group( 0 )
1242 return version
1243
1245 """
1246 Parameters:
1247 sw: The name of an OVS switch. Example "s1"
1248 Return:
1249 The output of the command from the mininet cli
1250 or main.FALSE on timeout"""
1251 command = "sh ovs-vsctl get-controller " + str( sw )
1252 try:
1253 response = self.execute(
1254 cmd=command,
1255 prompt="mininet>",
1256 timeout=10 )
1257 if response:
1258 return response
1259 else:
1260 return main.FALSE
1261 except pexpect.EOF:
1262 main.log.error( self.name + ": EOF exception found" )
1263 main.log.error( self.name + ": " + self.handle.before )
1264 main.cleanup()
1265 main.exit()
1266
1268 """
1269 Description:
1270 Assign switches to the controllers ( for ovs use only )
1271 Required:
1272 sw - Name of the switch. This can be a list or a string.
1273 ip - Ip addresses of controllers. This can be a list or a string.
1274 Optional:
1275 port - ONOS use port 6633, if no list of ports is passed, then
1276 the all the controller will use 6633 as their port number
1277 ptcp - ptcp number, This can be a string or a list that has
1278 the same length as switch. This is optional and not required
1279 when using ovs switches.
1280 NOTE: If switches and ptcp are given in a list type they should have the
1281 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1282 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
1283
1284 Return:
1285 Returns main.TRUE if mininet correctly assigned switches to
1286 controllers, otherwise it will return main.FALSE or an appropriate
1287 exception(s)
1288 """
1289 assignResult = main.TRUE
1290
1291 commandList = []
1292 command = "sh ovs-vsctl set-controller "
1293 onosIp = ""
1294 try:
1295 if isinstance( ip, types.StringType ):
1296 onosIp = "tcp:" + str( ip ) + ":"
1297 if isinstance( port, types.StringType ) or \
1298 isinstance( port, types.IntType ):
1299 onosIp += str( port )
1300 elif isinstance( port, types.ListType ):
1301 main.log.error( self.name + ": Only one controller " +
1302 "assigned and a list of ports has" +
1303 " been passed" )
1304 return main.FALSE
1305 else:
1306 main.log.error( self.name + ": Invalid controller port " +
1307 "number. Please specify correct " +
1308 "controller port" )
1309 return main.FALSE
1310
1311 elif isinstance( ip, types.ListType ):
1312 if isinstance( port, types.StringType ) or \
1313 isinstance( port, types.IntType ):
1314 for ipAddress in ip:
1315 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1316 str( port ) + " "
1317 elif isinstance( port, types.ListType ):
1318 if ( len( ip ) != len( port ) ):
1319 main.log.error( self.name + ": Port list = " +
1320 str( len( port ) ) +
1321 "should be the same as controller" +
1322 " ip list = " + str( len( ip ) ) )
1323 return main.FALSE
1324 else:
1325 onosIp = ""
1326 for ipAddress, portNum in zip( ip, port ):
1327 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1328 str( portNum ) + " "
1329 else:
1330 main.log.error( self.name + ": Invalid controller port " +
1331 "number. Please specify correct " +
1332 "controller port" )
1333 return main.FALSE
1334 else:
1335 main.log.error( self.name + ": Invalid ip address" )
1336 return main.FALSE
1337
1338 if isinstance( sw, types.StringType ):
1339 command += sw + " "
1340 if ptcp:
1341 if isinstance( ptcp, types.StringType ):
1342 command += "ptcp:" + str( ptcp ) + " "
1343 elif isinstance( ptcp, types.ListType ):
1344 main.log.error( self.name + ": Only one switch is " +
1345 "being set and multiple PTCP is " +
1346 "being passed " )
1347 else:
1348 main.log.error( self.name + ": Invalid PTCP" )
1349 ptcp = ""
1350 command += onosIp
1351 commandList.append( command )
1352
1353 elif isinstance( sw, types.ListType ):
1354 if ptcp:
1355 if isinstance( ptcp, types.ListType ):
1356 if len( ptcp ) != len( sw ):
1357 main.log.error( self.name + ": PTCP length = " +
1358 str( len( ptcp ) ) +
1359 " is not the same as switch" +
1360 " length = " +
1361 str( len( sw ) ) )
1362 return main.FALSE
1363 else:
1364 for switch, ptcpNum in zip( sw, ptcp ):
1365 tempCmd = "sh ovs-vsctl set-controller "
1366 tempCmd += switch + " ptcp:" + \
1367 str( ptcpNum ) + " "
1368 tempCmd += onosIp
1369 commandList.append( tempCmd )
1370 else:
1371 main.log.error( self.name + ": Invalid PTCP" )
1372 return main.FALSE
1373 else:
1374 for switch in sw:
1375 tempCmd = "sh ovs-vsctl set-controller "
1376 tempCmd += switch + " " + onosIp
1377 commandList.append( tempCmd )
1378 else:
1379 main.log.error( self.name + ": Invalid switch type " )
1380 return main.FALSE
1381
1382 for cmd in commandList:
1383 try:
1384 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
1385 except pexpect.TIMEOUT:
1386 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1387 return main.FALSE
1388 except pexpect.EOF:
1389 main.log.error( self.name + ": EOF exception found" )
1390 main.log.error( self.name + ": " + self.handle.before )
1391 main.cleanup()
1392 main.exit()
1393 return main.TRUE
1394 except Exception:
1395 main.log.exception( self.name + ": Uncaught exception!" )
1396 main.cleanup()
1397 main.exit()
1398
1400 """
1401 Removes the controller target from sw"""
1402 command = "sh ovs-vsctl del-controller " + str( sw )
1403 try:
1404 response = self.execute(
1405 cmd=command,
1406 prompt="mininet>",
1407 timeout=10 )
1408 except pexpect.EOF:
1409 main.log.error( self.name + ": EOF exception found" )
1410 main.log.error( self.name + ": " + self.handle.before )
1411 main.cleanup()
1412 main.exit()
1413 else:
1414 main.log.info( response )
1415
1417 """
1418 adds a switch to the mininet topology
1419 NOTE: This uses a custom mn function. MN repo should be on
1420 dynamic_topo branch
1421 NOTE: cannot currently specify what type of switch
1422 required params:
1423 sw = name of the new switch as a string
1424 optional keywords:
1425 dpid = "dpid"
1426 returns: main.FALSE on an error, else main.TRUE
1427 """
1428 dpid = kwargs.get( 'dpid', '' )
1429 command = "addswitch " + str( sw ) + " " + str( dpid )
1430 try:
1431 response = self.execute(
1432 cmd=command,
1433 prompt="mininet>",
1434 timeout=10 )
1435 if re.search( "already exists!", response ):
1436 main.log.warn( response )
1437 return main.FALSE
1438 elif re.search( "Error", response ):
1439 main.log.warn( response )
1440 return main.FALSE
1441 elif re.search( "usage:", response ):
1442 main.log.warn( response )
1443 return main.FALSE
1444 else:
1445 return main.TRUE
1446 except pexpect.EOF:
1447 main.log.error( self.name + ": EOF exception found" )
1448 main.log.error( self.name + ": " + self.handle.before )
1449 main.cleanup()
1450 main.exit()
1451
1453 """
1454 delete a switch from the mininet topology
1455 NOTE: This uses a custom mn function. MN repo should be on
1456 dynamic_topo branch
1457 required params:
1458 sw = name of the switch as a string
1459 returns: main.FALSE on an error, else main.TRUE"""
1460 command = "delswitch " + str( sw )
1461 try:
1462 response = self.execute(
1463 cmd=command,
1464 prompt="mininet>",
1465 timeout=10 )
1466 if re.search( "no switch named", response ):
1467 main.log.warn( response )
1468 return main.FALSE
1469 elif re.search( "Error", response ):
1470 main.log.warn( response )
1471 return main.FALSE
1472 elif re.search( "usage:", response ):
1473 main.log.warn( response )
1474 return main.FALSE
1475 else:
1476 return main.TRUE
1477 except pexpect.EOF:
1478 main.log.error( self.name + ": EOF exception found" )
1479 main.log.error( self.name + ": " + self.handle.before )
1480 main.cleanup()
1481 main.exit()
1482
1483 - def addLink( self, node1, node2 ):
1484 """
1485 add a link to the mininet topology
1486 NOTE: This uses a custom mn function. MN repo should be on
1487 dynamic_topo branch
1488 NOTE: cannot currently specify what type of link
1489 required params:
1490 node1 = the string node name of the first endpoint of the link
1491 node2 = the string node name of the second endpoint of the link
1492 returns: main.FALSE on an error, else main.TRUE"""
1493 command = "addlink " + str( node1 ) + " " + str( node2 )
1494 try:
1495 response = self.execute(
1496 cmd=command,
1497 prompt="mininet>",
1498 timeout=10 )
1499 if re.search( "doesnt exist!", response ):
1500 main.log.warn( response )
1501 return main.FALSE
1502 elif re.search( "Error", response ):
1503 main.log.warn( response )
1504 return main.FALSE
1505 elif re.search( "usage:", response ):
1506 main.log.warn( response )
1507 return main.FALSE
1508 else:
1509 return main.TRUE
1510 except pexpect.EOF:
1511 main.log.error( self.name + ": EOF exception found" )
1512 main.log.error( self.name + ": " + self.handle.before )
1513 main.cleanup()
1514 main.exit()
1515
1516 - def delLink( self, node1, node2 ):
1517 """
1518 delete a link from the mininet topology
1519 NOTE: This uses a custom mn function. MN repo should be on
1520 dynamic_topo branch
1521 required params:
1522 node1 = the string node name of the first endpoint of the link
1523 node2 = the string node name of the second endpoint of the link
1524 returns: main.FALSE on an error, else main.TRUE"""
1525 command = "dellink " + str( node1 ) + " " + str( node2 )
1526 try:
1527 response = self.execute(
1528 cmd=command,
1529 prompt="mininet>",
1530 timeout=10 )
1531 if re.search( "no node named", response ):
1532 main.log.warn( response )
1533 return main.FALSE
1534 elif re.search( "Error", response ):
1535 main.log.warn( response )
1536 return main.FALSE
1537 elif re.search( "usage:", response ):
1538 main.log.warn( response )
1539 return main.FALSE
1540 else:
1541 return main.TRUE
1542 except pexpect.EOF:
1543 main.log.error( self.name + ": EOF exception found" )
1544 main.log.error( self.name + ": " + self.handle.before )
1545 main.cleanup()
1546 main.exit()
1547
1548 - def addHost( self, hostname, **kwargs ):
1549 """
1550 Add a host to the mininet topology
1551 NOTE: This uses a custom mn function. MN repo should be on
1552 dynamic_topo branch
1553 NOTE: cannot currently specify what type of host
1554 required params:
1555 hostname = the string hostname
1556 optional key-value params
1557 switch = "switch name"
1558 returns: main.FALSE on an error, else main.TRUE
1559 """
1560 switch = kwargs.get( 'switch', '' )
1561 command = "addhost " + str( hostname ) + " " + str( switch )
1562 try:
1563 response = self.execute(
1564 cmd=command,
1565 prompt="mininet>",
1566 timeout=10 )
1567 if re.search( "already exists!", response ):
1568 main.log.warn( response )
1569 return main.FALSE
1570 elif re.search( "doesnt exists!", response ):
1571 main.log.warn( response )
1572 return main.FALSE
1573 elif re.search( "Error", response ):
1574 main.log.warn( response )
1575 return main.FALSE
1576 elif re.search( "usage:", response ):
1577 main.log.warn( response )
1578 return main.FALSE
1579 else:
1580 return main.TRUE
1581 except pexpect.EOF:
1582 main.log.error( self.name + ": EOF exception found" )
1583 main.log.error( self.name + ": " + self.handle.before )
1584 main.cleanup()
1585 main.exit()
1586
1588 """
1589 delete a host from the mininet topology
1590 NOTE: This uses a custom mn function. MN repo should be on
1591 dynamic_topo branch
1592 NOTE: this uses a custom mn function
1593 required params:
1594 hostname = the string hostname
1595 returns: main.FALSE on an error, else main.TRUE"""
1596 command = "delhost " + str( hostname )
1597 try:
1598 response = self.execute(
1599 cmd=command,
1600 prompt="mininet>",
1601 timeout=10 )
1602 if re.search( "no host named", response ):
1603 main.log.warn( response )
1604 return main.FALSE
1605 elif re.search( "Error", response ):
1606 main.log.warn( response )
1607 return main.FALSE
1608 elif re.search( "usage:", response ):
1609 main.log.warn( response )
1610 return main.FALSE
1611 else:
1612 return main.TRUE
1613 except pexpect.EOF:
1614 main.log.error( self.name + ": EOF exception found" )
1615 main.log.error( self.name + ": " + self.handle.before )
1616 main.cleanup()
1617 main.exit()
1618
1620 """
1621 Called at the end of the test to stop the mininet and
1622 disconnect the handle.
1623 """
1624 self.handle.sendline( '' )
1625 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
1626 timeout=2 )
1627 response = main.TRUE
1628 if i == 0:
1629 response = self.stopNet()
1630 elif i == 1:
1631 return main.TRUE
1632
1633 if self.handle:
1634 self.handle.sendline( "exit" )
1635 self.handle.expect( "exit" )
1636 self.handle.expect( "(.*)" )
1637 else:
1638 main.log.error( "Connection failed to the host" )
1639 return response
1640
1641 - def stopNet( self, fileName="", timeout=5 ):
1642 """
1643 Stops mininet.
1644 Returns main.TRUE if the mininet successfully stops and
1645 main.FALSE if the pexpect handle does not exist.
1646
1647 Will cleanup and exit the test if mininet fails to stop
1648 """
1649 main.log.info( self.name + ": Stopping mininet..." )
1650 response = ''
1651 if self.handle:
1652 try:
1653 self.handle.sendline( "" )
1654 i = self.handle.expect( [ 'mininet>',
1655 '\$',
1656 pexpect.EOF,
1657 pexpect.TIMEOUT ],
1658 timeout )
1659 if i == 0:
1660 main.log.info( "Exiting mininet..." )
1661 response = self.execute(
1662 cmd="exit",
1663 prompt="(.*)",
1664 timeout=120 )
1665 main.log.info( self.name + ": Stopped" )
1666 self.handle.sendline( "sudo mn -c" )
1667 response = main.TRUE
1668
1669 if i == 1:
1670 main.log.info( " Mininet trying to exit while not " +
1671 "in the mininet prompt" )
1672 elif i == 2:
1673 main.log.error( "Something went wrong exiting mininet" )
1674 elif i == 3:
1675 main.log.error( "Something went wrong exiting mininet " +
1676 "TIMEOUT" )
1677
1678 if fileName:
1679 self.handle.sendline( "" )
1680 self.handle.expect( '\$' )
1681 self.handle.sendline(
1682 "sudo kill -9 \`ps -ef | grep \"" +
1683 fileName +
1684 "\" | grep -v grep | awk '{print $2}'\`" )
1685 except pexpect.EOF:
1686 main.log.error( self.name + ": EOF exception found" )
1687 main.log.error( self.name + ": " + self.handle.before )
1688 main.cleanup()
1689 main.exit()
1690 else:
1691 main.log.error( self.name + ": Connection failed to the host" )
1692 response = main.FALSE
1693 return response
1694
1695 - def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
1696 """
1697 Description:
1698 Sends arp message from mininet host for hosts discovery
1699 Required:
1700 host - hosts name
1701 Optional:
1702 ip - ip address that does not exist in the network so there would
1703 be no reply.
1704 """
1705 if ethDevice:
1706 ethDevice = '-I ' + ethDevice + ' '
1707 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
1708 try:
1709 main.log.warn( "Sending: " + cmd )
1710 self.handle.sendline( cmd )
1711 response = self.handle.before
1712 self.handle.sendline( "" )
1713 self.handle.expect( "mininet>" )
1714 return main.TRUE
1715
1716 except pexpect.EOF:
1717 main.log.error( self.name + ": EOF exception found" )
1718 main.log.error( self.name + ": " + self.handle.before )
1719 main.cleanup()
1720 main.exit()
1721
1723 return hex( num ).split( 'x' )[ 1 ]
1724
1726 """
1727 return the Flow Count of the switch"""
1728 if self.handle:
1729 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1730 try:
1731 response = self.execute(
1732 cmd=cmd,
1733 prompt="mininet>",
1734 timeout=10 )
1735 except pexpect.EOF:
1736 main.log.error( self.name + ": EOF exception found" )
1737 main.log.error( self.name + " " + self.handle.before )
1738 main.cleanup()
1739 main.exit()
1740 pattern = "flow_count=(\d+)"
1741 result = re.search( pattern, response, re.MULTILINE )
1742 if result is None:
1743 main.log.info(
1744 "Couldn't find flows on switch %s, found: %s" %
1745 ( switch, response ) )
1746 return main.FALSE
1747 return result.group( 1 )
1748 else:
1749 main.log.error( "Connection failed to the Mininet host" )
1750
1752 if dumpFormat:
1753 command = "sh ovs-ofctl -F " + \
1754 dumpFormat + " dump-flows " + str( sw )
1755 else:
1756 command = "sh ovs-ofctl dump-flows " + str( sw )
1757 try:
1758 response = self.execute(
1759 cmd=command,
1760 prompt="mininet>",
1761 timeout=10 )
1762 return response
1763 except pexpect.EOF:
1764 main.log.error( self.name + ": EOF exception found" )
1765 main.log.error( self.name + ": " + self.handle.before )
1766 main.cleanup()
1767 main.exit()
1768
1770 """
1771 Returns certain fields of an OVS flow table. Will force output to
1772 either OF 1.0 or 1.3 format for consistency.
1773
1774 TODO add option to look at cookies. ignoring them for now
1775
1776 NOTE: Use format to force consistent flow table output across
1777 versions
1778 """
1779 try:
1780 self.handle.sendline( "" )
1781 self.handle.expect( "mininet>" )
1782 command = "sh ovs-ofctl dump-flows " + sw
1783 if protoVersion == 1.0:
1784 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1785 " print $1 $3 $6 $7 $8}' | "
1786 elif protoVersion == 1.3:
1787 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1788 " print $1 $3 $6 $7}' | "
1789 else:
1790 main.log.error(
1791 "Unknown protoVersion in getFlowTable(). given: (" +
1792 str( type( protoVersion ) ) +
1793 ") '" + str( protoVersion ) + "'" )
1794 return None
1795 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1796 self.handle.sendline( command )
1797 self.handle.expect( "sort" )
1798 self.handle.expect( "OFPST_FLOW" )
1799 response = self.handle.before
1800 return response
1801 except pexpect.EOF:
1802 main.log.error( self.name + ": EOF exception found" )
1803 main.log.error( self.name + ": " + self.handle.before )
1804 main.cleanup()
1805 main.exit()
1806 except pexpect.TIMEOUT:
1807 main.log.exception( self.name + ": Timeout exception: " )
1808 return None
1809
1811 if flow1 == flow2:
1812 return main.TRUE
1813 else:
1814 main.log.info( "Flow tables do not match, printing tables:" )
1815 main.log.info( "Flow Table 1:" )
1816 main.log.info( flow1 )
1817 main.log.info( "Flow Table 2:" )
1818 main.log.info( flow2 )
1819 return main.FALSE
1820
1821 - def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
1822 """
1823 Runs tpdump on an interface and saves the file
1824 intf can be specified, or the default eth0 is used"""
1825 try:
1826 self.handle.sendline( "" )
1827 self.handle.expect( "mininet>" )
1828 self.handle.sendline(
1829 "sh sudo tcpdump -n -i " +
1830 intf +
1831 " " +
1832 port +
1833 " -w " +
1834 filename.strip() +
1835 " &" )
1836 self.handle.sendline( "" )
1837 i = self.handle.expect( [ 'No\ssuch\device',
1838 'listening\son',
1839 pexpect.TIMEOUT,
1840 "mininet>" ],
1841 timeout=10 )
1842 main.log.warn( self.handle.before + self.handle.after )
1843 self.handle.sendline( "" )
1844 self.handle.expect( "mininet>" )
1845 if i == 0:
1846 main.log.error(
1847 self.name +
1848 ": tcpdump - No such device exists. " +
1849 "tcpdump attempted on: " +
1850 intf )
1851 return main.FALSE
1852 elif i == 1:
1853 main.log.info( self.name + ": tcpdump started on " + intf )
1854 return main.TRUE
1855 elif i == 2:
1856 main.log.error(
1857 self.name +
1858 ": tcpdump command timed out! Check interface name," +
1859 " given interface was: " +
1860 intf )
1861 return main.FALSE
1862 elif i == 3:
1863 main.log.info( self.name + ": " + self.handle.before )
1864 return main.TRUE
1865 else:
1866 main.log.error( self.name + ": tcpdump - unexpected response" )
1867 return main.FALSE
1868 except pexpect.EOF:
1869 main.log.error( self.name + ": EOF exception found" )
1870 main.log.error( self.name + ": " + self.handle.before )
1871 main.cleanup()
1872 main.exit()
1873 except Exception:
1874 main.log.exception( self.name + ": Uncaught exception!" )
1875 main.cleanup()
1876 main.exit()
1877
1879 """
1880 pkills tcpdump"""
1881 try:
1882 self.handle.sendline( "sh sudo pkill tcpdump" )
1883 self.handle.expect( "mininet>" )
1884 self.handle.sendline( "" )
1885 self.handle.expect( "mininet>" )
1886 except pexpect.EOF:
1887 main.log.error( self.name + ": EOF exception found" )
1888 main.log.error( self.name + ": " + self.handle.before )
1889 main.cleanup()
1890 main.exit()
1891 except Exception:
1892 main.log.exception( self.name + ": Uncaught exception!" )
1893 main.cleanup()
1894 main.exit()
1895
1896 - def getPorts( self, nodeName, verbose=False ):
1897 """
1898 Read ports from a Mininet switch.
1899
1900 Returns a json structure containing information about the
1901 ports of the given switch.
1902 """
1903 response = self.getInterfaces( nodeName )
1904
1905 ports = []
1906 for line in response.split( "\n" ):
1907 if not line.startswith( "name=" ):
1908 continue
1909 portVars = {}
1910 for var in line.split( "," ):
1911 key, value = var.split( "=" )
1912 portVars[ key ] = value
1913 isUp = portVars.pop( 'enabled', "True" )
1914 isUp = "True" in isUp
1915 if verbose:
1916 main.log.info( "Reading switch port %s(%s)" %
1917 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1918 mac = portVars[ 'mac' ]
1919 if mac == 'None':
1920 mac = None
1921 ips = []
1922 ip = portVars[ 'ip' ]
1923 if ip == 'None':
1924 ip = None
1925 ips.append( ip )
1926 name = portVars[ 'name' ]
1927 if name == 'None':
1928 name = None
1929 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1930 if name == 'lo':
1931 portNo = 0xfffe
1932 else:
1933 portNo = re.search( portRe, name ).group( 'port' )
1934 ports.append( { 'of_port': portNo,
1935 'mac': str( mac ).replace( '\'', '' ),
1936 'name': name,
1937 'ips': ips,
1938 'enabled': isUp } )
1939 return ports
1940
1942 """
1943 Read switches from Mininet.
1944
1945 Returns a dictionary whose keys are the switch names and the value is
1946 a dictionary containing information about the switch.
1947 """
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
1959 swRE = r"<(?P<class>" + switchClasses + r")" +\
1960 r"(?P<options>\{.*\})?\s" +\
1961 r"(?P<name>[^:]+)\:\s" +\
1962 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
1963 r"\spid=(?P<pid>(\d)+)"
1964
1965 self.update()
1966 output = {}
1967 dump = self.dump().split( "\n" )
1968 for line in dump:
1969 result = re.search( swRE, line, re.I )
1970 if result:
1971 name = result.group( 'name' )
1972 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1973 pid = result.group( 'pid' )
1974 swClass = result.group( 'class' )
1975 options = result.group( 'options' )
1976 if verbose:
1977 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1978 ports = self.getPorts( name )
1979 output[ name ] = { "dpid": dpid,
1980 "ports": ports,
1981 "swClass": swClass,
1982 "pid": pid,
1983 "options": options }
1984 return output
1985
1987 """
1988 Read hosts from Mininet.
1989
1990 Returns a dictionary whose keys are the host names and the value is
1991 a dictionary containing information about the host.
1992 """
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
2003 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
2004
2005 self.update()
2006
2007 dump = self.dump().split( "\n" )
2008 hosts = {}
2009 for line in dump:
2010 if "Host" in line :
2011 result = re.search( hostRE, line )
2012 name = result.group( 'name' )
2013 interfaces = []
2014 response = self.getInterfaces( name )
2015
2016 for line in response.split( "\n" ):
2017 if line.startswith( "name=" ):
2018 portVars = {}
2019 for var in line.split( "," ):
2020 key, value = var.split( "=" )
2021 portVars[ key ] = value
2022 isUp = portVars.pop( 'enabled', "True" )
2023 isUp = "True" in isUp
2024 if verbose:
2025 main.log.info( "Reading host port %s(%s)" %
2026 ( portVars[ 'name' ],
2027 portVars[ 'mac' ] ) )
2028 mac = portVars[ 'mac' ]
2029 if mac == 'None':
2030 mac = None
2031 ips = []
2032 ip = portVars[ 'ip' ]
2033 if ip == 'None':
2034 ip = None
2035 ips.append( ip )
2036 intfName = portVars[ 'name' ]
2037 if name == 'None':
2038 name = None
2039 interfaces.append( {
2040 "name": intfName,
2041 "ips": ips,
2042 "mac": str( mac ),
2043 "isUp": isUp } )
2044 hosts[ name ] = { "interfaces": interfaces }
2045 return hosts
2046
2048 """
2049 Gathers information about current Mininet links. These links may not
2050 be up if one of the ports is down.
2051
2052 Returns a list of dictionaries with link endpoints.
2053
2054 The dictionary structure is:
2055 { 'node1': str( node1 name )
2056 'node2': str( node2 name )
2057 'port1': str( port1 of_port )
2058 'port2': str( port2 of_port ) }
2059 Note: The port number returned is the eth#, not necessarily the of_port
2060 number. In Mininet, for OVS switch, these should be the same. For
2061 hosts, this is just the eth#.
2062 """
2063 self.update()
2064 response = self.links().split( '\n' )
2065
2066
2067
2068
2069 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2070 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2071 links = []
2072 for line in response:
2073 match = re.search( linkRE, line )
2074 if match:
2075 node1 = match.group( 'node1' )
2076 node2 = match.group( 'node2' )
2077 port1 = match.group( 'port1' )
2078 port2 = match.group( 'port2' )
2079 links.append( { 'node1': node1,
2080 'node2': node2,
2081 'port1': port1,
2082 'port2': port2 } )
2083 return links
2084
2086 """
2087 Compare mn and onos switches
2088 switchesJson: parsed json object from the onos devices api
2089
2090 Dependencies:
2091 1. numpy - "sudo pip install numpy"
2092 """
2093 from numpy import uint64
2094
2095 mnDPIDs = []
2096 for swName, switch in switches.iteritems():
2097 mnDPIDs.append( switch[ 'dpid' ].lower() )
2098 mnDPIDs.sort()
2099 if switchesJson == "":
2100 main.log.error(
2101 self.name +
2102 ".compareSwitches(): Empty JSON object given from ONOS" )
2103 return main.FALSE
2104 onos = switchesJson
2105 onosDPIDs = []
2106 for switch in onos:
2107 if switch[ 'available' ]:
2108 onosDPIDs.append(
2109 switch[ 'id' ].replace(
2110 ":",
2111 '' ).replace(
2112 "of",
2113 '' ).lower() )
2114 onosDPIDs.sort()
2115
2116 if mnDPIDs != onosDPIDs:
2117 switchResults = main.FALSE
2118 main.log.error( "Switches in MN but not in ONOS:" )
2119 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
2120 main.log.error( str( list1 ) )
2121 main.log.error( "Switches in ONOS but not in MN:" )
2122 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
2123 main.log.error( str( list2 ) )
2124 else:
2125 switchResults = main.TRUE
2126 finalResults = switchResults
2127
2128
2129
2130 portsResults = main.TRUE
2131
2132
2133 for name, mnSwitch in switches.iteritems():
2134 mnPorts = []
2135 onosPorts = []
2136 switchResult = main.TRUE
2137 for port in mnSwitch[ 'ports' ]:
2138 if port[ 'enabled' ]:
2139 mnPorts.append( int( port[ 'of_port' ] ) )
2140 for onosSwitch in portsJson:
2141 if onosSwitch[ 'device' ][ 'available' ]:
2142 if onosSwitch[ 'device' ][ 'id' ].replace(
2143 ':',
2144 '' ).replace(
2145 "of",
2146 '' ) == mnSwitch[ 'dpid' ]:
2147 for port in onosSwitch[ 'ports' ]:
2148 if port[ 'isEnabled' ]:
2149 if port[ 'port' ] == 'local':
2150
2151 onosPorts.append( long( uint64( -2 ) ) )
2152 else:
2153 onosPorts.append( int( port[ 'port' ] ) )
2154 break
2155 mnPorts.sort( key=float )
2156 onosPorts.sort( key=float )
2157
2158 mnPortsLog = mnPorts
2159 onosPortsLog = onosPorts
2160 mnPorts = [ x for x in mnPorts ]
2161 onosPorts = [ x for x in onosPorts ]
2162
2163
2164
2165
2166
2167 for mnPort in mnPortsLog:
2168 if mnPort in onosPorts:
2169
2170
2171 mnPorts.remove( mnPort )
2172 onosPorts.remove( mnPort )
2173
2174
2175
2176
2177 if 65534 in mnPorts:
2178 mnPorts.remove( 65534 )
2179 if long( uint64( -2 ) ) in onosPorts:
2180 onosPorts.remove( long( uint64( -2 ) ) )
2181 if len( mnPorts ):
2182 switchResult = main.FALSE
2183 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2184 if len( onosPorts ):
2185 switchResult = main.FALSE
2186 main.log.warn(
2187 "Ports in ONOS but not MN: " +
2188 str( onosPorts ) )
2189 if switchResult == main.FALSE:
2190 main.log.error(
2191 "The list of ports for switch %s(%s) does not match:" %
2192 ( name, mnSwitch[ 'dpid' ] ) )
2193 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2194 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2195 portsResults = portsResults and switchResult
2196 finalResults = finalResults and portsResults
2197 return finalResults
2198
2200 """
2201 Compare mn and onos links
2202 linksJson: parsed json object from the onos links api
2203
2204 """
2205
2206
2207 onos = linksJson
2208
2209 mnLinks = []
2210 for l in links:
2211 try:
2212 node1 = switches[ l[ 'node1' ] ]
2213 node2 = switches[ l[ 'node2' ] ]
2214 enabled = True
2215 for port in node1[ 'ports' ]:
2216 if port[ 'of_port' ] == l[ 'port1' ]:
2217 enabled = enabled and port[ 'enabled' ]
2218 for port in node2[ 'ports' ]:
2219 if port[ 'of_port' ] == l[ 'port2' ]:
2220 enabled = enabled and port[ 'enabled' ]
2221 if enabled:
2222 mnLinks.append( l )
2223 except KeyError:
2224 pass
2225 if 2 * len( mnLinks ) == len( onos ):
2226 linkResults = main.TRUE
2227 else:
2228 linkResults = main.FALSE
2229 main.log.error(
2230 "Mininet has " + str( len( mnLinks ) ) +
2231 " bidirectional links and ONOS has " +
2232 str( len( onos ) ) + " unidirectional links" )
2233
2234
2235
2236 for link in mnLinks:
2237
2238 node1 = None
2239 port1 = None
2240 node2 = None
2241 port2 = None
2242 firstDir = main.FALSE
2243 secondDir = main.FALSE
2244 for swName, switch in switches.iteritems():
2245 if swName == link[ 'node1' ]:
2246 node1 = switch[ 'dpid' ]
2247 for port in switch[ 'ports' ]:
2248 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
2249 port1 = port[ 'of_port' ]
2250 if node1 is not None and node2 is not None:
2251 break
2252 if swName == link[ 'node2' ]:
2253 node2 = switch[ 'dpid' ]
2254 for port in switch[ 'ports' ]:
2255 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
2256 port2 = port[ 'of_port' ]
2257 if node1 is not None and node2 is not None:
2258 break
2259
2260 for onosLink in onos:
2261 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
2262 ":", '' ).replace( "of", '' )
2263 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
2264 ":", '' ).replace( "of", '' )
2265 onosPort1 = onosLink[ 'src' ][ 'port' ]
2266 onosPort2 = onosLink[ 'dst' ][ 'port' ]
2267
2268
2269 if str( onosNode1 ) == str( node1 ) and str(
2270 onosNode2 ) == str( node2 ):
2271 if int( onosPort1 ) == int( port1 ) and int(
2272 onosPort2 ) == int( port2 ):
2273 firstDir = main.TRUE
2274 else:
2275 main.log.warn(
2276 'The port numbers do not match for ' +
2277 str( link ) +
2278 ' between ONOS and MN. When checking ONOS for ' +
2279 'link %s/%s -> %s/%s' %
2280 ( node1, port1, node2, port2 ) +
2281 ' ONOS has the values %s/%s -> %s/%s' %
2282 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
2283
2284
2285 elif ( str( onosNode1 ) == str( node2 ) and
2286 str( onosNode2 ) == str( node1 ) ):
2287 if ( int( onosPort1 ) == int( port2 )
2288 and int( onosPort2 ) == int( port1 ) ):
2289 secondDir = main.TRUE
2290 else:
2291 main.log.warn(
2292 'The port numbers do not match for ' +
2293 str( link ) +
2294 ' between ONOS and MN. When checking ONOS for ' +
2295 'link %s/%s -> %s/%s' %
2296 ( node1, port1, node2, port2 ) +
2297 ' ONOS has the values %s/%s -> %s/%s' %
2298 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
2299 else:
2300 pass
2301 if not firstDir:
2302 main.log.error(
2303 'ONOS does not have the link %s/%s -> %s/%s' %
2304 ( node1, port1, node2, port2 ) )
2305 if not secondDir:
2306 main.log.error(
2307 'ONOS does not have the link %s/%s -> %s/%s' %
2308 ( node2, port2, node1, port1 ) )
2309 linkResults = linkResults and firstDir and secondDir
2310 return linkResults
2311
2313 """
2314 Compare mn and onos Hosts.
2315 Since Mininet hosts are quiet, ONOS will only know of them when they
2316 speak. For this reason, we will only check that the hosts in ONOS
2317 stores are in Mininet, and not vice versa.
2318
2319 Arguments:
2320 hostsJson: parsed json object from the onos hosts api
2321 Returns:
2322 """
2323 import json
2324 hostResults = main.TRUE
2325 for onosHost in hostsJson:
2326 onosMAC = onosHost[ 'mac' ].lower()
2327 match = False
2328 for mnHost, info in hosts.iteritems():
2329 for mnIntf in info[ 'interfaces' ]:
2330 if onosMAC == mnIntf[ 'mac' ].lower():
2331 match = True
2332 for ip in mnIntf[ 'ips' ]:
2333 if ip in onosHost[ 'ipAddresses' ]:
2334 pass
2335 else:
2336
2337 main.log.error( "ONOS host " +
2338 onosHost[ 'id' ] +
2339 " has a different IP(" +
2340 str( onosHost[ 'ipAddresses' ] ) +
2341 ") than the Mininet host(" +
2342 str( ip ) +
2343 ")." )
2344 output = json.dumps(
2345 onosHost,
2346 sort_keys=True,
2347 indent=4,
2348 separators=( ',', ': ' ) )
2349 main.log.info( output )
2350 hostResults = main.FALSE
2351 if not match:
2352 hostResults = main.FALSE
2353 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2354 "corresponding Mininet host." )
2355 output = json.dumps( onosHost,
2356 sort_keys=True,
2357 indent=4,
2358 separators=( ',', ': ' ) )
2359 main.log.info( output )
2360 return hostResults
2361
2363 """
2364 Returns a list of all hosts
2365 Don't ask questions just use it"""
2366 self.handle.sendline( "" )
2367 self.handle.expect( "mininet>" )
2368
2369 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2370 self.handle.expect( "mininet>" )
2371
2372 handlePy = self.handle.before
2373 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2374 handlePy = handlePy.rstrip()
2375
2376 self.handle.sendline( "" )
2377 self.handle.expect( "mininet>" )
2378
2379 hostStr = handlePy.replace( "]", "" )
2380 hostStr = hostStr.replace( "'", "" )
2381 hostStr = hostStr.replace( "[", "" )
2382 hostStr = hostStr.replace( " ", "" )
2383 hostList = hostStr.split( "," )
2384
2385 return hostList
2386
2388 """
2389 Returns a list of all switches
2390 Again, don't ask question just use it...
2391 """
2392
2393 hostList = self.getHosts()
2394
2395 hostSet = set( hostList )
2396
2397
2398 self.handle.sendline( "" )
2399 self.handle.expect( "mininet>" )
2400
2401 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2402 self.handle.expect( "mininet>" )
2403
2404 handlePy = self.handle.before
2405 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2406 handlePy = handlePy.rstrip()
2407
2408 self.handle.sendline( "" )
2409 self.handle.expect( "mininet>" )
2410
2411 nodesStr = handlePy.replace( "]", "" )
2412 nodesStr = nodesStr.replace( "'", "" )
2413 nodesStr = nodesStr.replace( "[", "" )
2414 nodesStr = nodesStr.replace( " ", "" )
2415 nodesList = nodesStr.split( "," )
2416
2417 nodesSet = set( nodesList )
2418
2419 nodesSet.discard( 'c0' )
2420 nodesSet.discard( 'c1' )
2421 nodesSet.discard( 'c2' )
2422
2423 switchSet = nodesSet - hostSet
2424 switchList = list( switchSet )
2425
2426 return switchList
2427
2429 """
2430 updates the port address and status information for
2431 each port in mn"""
2432
2433 main.log.info( "Updating MN port information" )
2434 try:
2435 self.handle.sendline( "" )
2436 self.handle.expect( "mininet>" )
2437
2438 self.handle.sendline( "update" )
2439 self.handle.expect( "update" )
2440 self.handle.expect( "mininet>" )
2441
2442 self.handle.sendline( "" )
2443 self.handle.expect( "mininet>" )
2444
2445 return main.TRUE
2446 except pexpect.EOF:
2447 main.log.error( self.name + ": EOF exception found" )
2448 main.log.error( self.name + ": " + self.handle.before )
2449 main.cleanup()
2450 main.exit()
2451
2453 """
2454 Add vlan tag to a host.
2455 Dependencies:
2456 This class depends on the "vlan" package
2457 $ sudo apt-get install vlan
2458 Configuration:
2459 Load the 8021q module into the kernel
2460 $sudo modprobe 8021q
2461
2462 To make this setup permanent:
2463 $ sudo su -c 'echo "8021q" >> /etc/modules'
2464 """
2465 if self.handle:
2466 try:
2467
2468 main.log.info( "Get the ip address of the host" )
2469 ipaddr = self.getIPAddress( host )
2470 print repr( ipaddr )
2471
2472
2473
2474 main.log.info( "Remove IP from interface " )
2475 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2476 self.handle.sendline( cmd2 )
2477 self.handle.expect( "mininet>" )
2478 response = self.handle.before
2479 main.log.info( "====> %s ", response )
2480
2481
2482
2483 main.log.info( "Create Vlan" )
2484 cmd3 = host + " vconfig add " + intf + " " + vlan
2485 self.handle.sendline( cmd3 )
2486 self.handle.expect( "mininet>" )
2487 response = self.handle.before
2488 main.log.info( "====> %s ", response )
2489
2490
2491
2492 main.log.info( "Assign the host IP to the vlan interface" )
2493 vintf = intf + "." + vlan
2494 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2495 self.handle.sendline( cmd4 )
2496 self.handle.expect( "mininet>" )
2497 response = self.handle.before
2498 main.log.info( "====> %s ", response )
2499
2500 return main.TRUE
2501 except pexpect.EOF:
2502 main.log.error( self.name + ": EOF exception found" )
2503 main.log.error( self.name + ": " + self.handle.before )
2504 return main.FALSE
2505
2506 if __name__ != "__main__":
2507 import sys
2508 sys.modules[ __name__ ] = MininetCliDriver()
2509