Revision 086ef80e mininet/node.py

View differences:

mininet/node.py
39 39
import os
40 40
import signal
41 41
import select
42
from time import sleep
42 43

  
43 44
from mininet.log import info, error, debug
44 45
from mininet.util import quietRun, moveIntf
......
51 52
    inToNode = {} # mapping of input fds to nodes
52 53
    outToNode = {} # mapping of output fds to nodes
53 54

  
54
    def __init__( self, name, inNamespace=True ):
55
    def __init__( self, name, inNamespace=True,
56
        defaultMAC=None, defaultIP=None ):
57
        """name: name of node
58
           inNamespace: in network namespace?
59
           defaultMAC: default MAC address for intf 0
60
           defaultIP: default IP address for intf 0"""
55 61
        self.name = name
56 62
        closeFds = False # speed vs. memory use
57 63
        # xpg_echo is needed so we can echo our sentinel in sendCmd
......
79 85
        self.connection = {} # remote node connected to each interface
80 86
        self.waiting = False
81 87
        self.execed = False
88
        self.defaultIP = defaultIP
89
        self.defaultMAC = defaultMAC
82 90

  
83 91
    @classmethod
84 92
    def fdToNode( cls, fd ):
......
213 221
        "Register connection of intf to dstIntf on dstNode."
214 222
        self.connection[ intf ] = ( dstNode, dstIntf )
215 223

  
224
    def deleteIntfs( self ):
225
        "Delete all of our interfaces."
226
        # In theory the interfaces should go away after we shut down.
227
        # However, this takes time, so we're better off removing them
228
        # explicitly so that we won't get errors if we run before they
229
        # have been removed by the kernel. Unfortunately this is very slow.
230
        self.cmd( 'kill %ofprotocol' )
231
        for intf in self.intfs.values():
232
            quietRun( 'ip link del ' + intf )
233
            info( '.' )
234
            # Does it help to sleep to let things run?
235
            sleep( 0.001 )
236

  
216 237
    def setMAC( self, intf, mac ):
217 238
        """Set the MAC address for an interface.
218 239
           mac: MAC address as string"""
......
228 249
        result = self.cmd( [ 'arp', '-s', ip, mac ] )
229 250
        return result
230 251

  
231
    def setIP( self, intf, ip, bits ):
252
    def setIP( self, intf, ip, prefixLen ):
232 253
        """Set the IP address for an interface.
233 254
           intf: interface name
234 255
           ip: IP address as a string
235
           bits: prefix length of form /24"""
236
        result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] )
256
           prefixLen: prefix length, e.g. 8 for /8 or 16M addrs"""
257
        ipSub = '%s/%d' % ( ip, prefixLen )
258
        result = self.cmd( [ 'ifconfig', intf, ipSub, 'up' ] )
237 259
        self.ips[ intf ] = ip
238 260
        return result
239 261

  
......
297 319
    """User-space switch.
298 320
       Currently only works in the root namespace."""
299 321

  
300
    def __init__( self, name ):
322
    def __init__( self, name, *args, **kwargs ):
301 323
        """Init.
302 324
           name: name for the switch"""
303
        Switch.__init__( self, name, inNamespace=False )
325
        Switch.__init__( self, name, inNamespace=False, **kwargs )
304 326

  
305 327
    def start( self, controllers ):
306 328
        """Start OpenFlow reference user datapath.
......
323 345
        "Stop OpenFlow reference user datapath."
324 346
        self.cmd( 'kill %ofdatapath' )
325 347
        self.cmd( 'kill %ofprotocol' )
326

  
348
        self.deleteIntfs()
327 349

  
328 350
class KernelSwitch( Switch ):
329 351
    """Kernel-space switch.
330 352
       Currently only works in the root namespace."""
331 353

  
332
    def __init__( self, name, dp=None, defaultMac=None ):
354
    def __init__( self, name, dp=None, **kwargs ):
333 355
        """Init.
334 356
           name:
335 357
           dp: netlink id (0, 1, 2, ...)
336
           defaultMac: default MAC as string; random value if None"""
337
        Switch.__init__( self, name, inNamespace=False )
358
           defaultMAC: default MAC as string; random value if None"""
359
        Switch.__init__( self, name, inNamespace=False, **kwargs )
338 360
        self.dp = dp
339
        self.defaultMac = defaultMac
340 361

  
341 362
    def start( self, controllers ):
342 363
        "Start up reference kernel datapath."
......
346 367
        # then create a new one monitoring the given interfaces
347 368
        quietRun( 'dpctl deldp nl:%i' % self.dp )
348 369
        self.cmd( 'dpctl adddp nl:%i' % self.dp )
349
        if self.defaultMac:
370
        if self.defaultMAC:
350 371
            intf = 'of%i' % self.dp
351
            self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMac ] )
372
            self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMAC ] )
352 373

  
353 374
        if len( self.intfs ) != max( self.intfs ) + 1:
354 375
            raise Exception( 'only contiguous, zero-indexed port ranges'
......
367 388
    def stop( self ):
368 389
        "Terminate kernel datapath."
369 390
        quietRun( 'dpctl deldp nl:%i' % self.dp )
370
        # In theory the interfaces should go away after we shut down.
371
        # However, this takes time, so we're better off removing them
372
        # explicitly so that we won't get errors if we run before they
373
        # have been removed by the kernel. Unfortunately this is very slow.
374
        self.cmd( 'kill %ofprotocol' )
375
        for intf in self.intfs.values():
376
            quietRun( 'ip link del ' + intf )
377
            info( '.' )
378

  
391
        self.deleteIntfs()
379 392

  
380 393
class OVSKernelSwitch( Switch ):
381 394
    """Open VSwitch kernel-space switch.
382 395
       Currently only works in the root namespace."""
383 396

  
384
    def __init__( self, name, dp=None, defaultMac=None ):
397
    def __init__( self, name, dp=None, **kwargs ):
385 398
        """Init.
386 399
           name:
387 400
           dp: netlink id (0, 1, 2, ...)
388 401
           dpid: datapath ID as unsigned int; random value if None"""
389
        Switch.__init__( self, name, inNamespace=False )
402
        Switch.__init__( self, name, inNamespace=False, **kwargs )
390 403
        self.dp = dp
391
        self.defaultMac = defaultMac
392 404

  
393 405
    def start( self, controllers ):
394 406
        "Start up kernel datapath."
......
398 410
        # then create a new one monitoring the given interfaces
399 411
        quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
400 412
        self.cmd( 'ovs-dpctl add-dp dp%i' % self.dp )
401
        if self.defaultMac:
413
        if self.defaultMAC:
402 414
            intf = 'dp' % self.dp
403
            mac = self.defaultMac
415
            mac = self.defaultMAC
404 416
            self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
405 417

  
406 418
        if len( self.intfs ) != max( self.intfs ) + 1:
......
419 431
    def stop( self ):
420 432
        "Terminate kernel datapath."
421 433
        quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
422
        # In theory the interfaces should go away after we shut down.
423
        # However, this takes time, so we're better off removing them
424
        # explicitly so that we won't get errors if we run before they
425
        # have been removed by the kernel. Unfortunately this is very slow.
426
        self.cmd( 'kill %ovs-openflowd' )
427
        for intf in self.intfs.values():
428
            quietRun( 'ip link del ' + intf )
429
            info( '.' )
434
        self.deleteIntfs()
430 435

  
431 436

  
432 437
class Controller( Node ):
......
434 439
       OpenFlow controller."""
435 440

  
436 441
    def __init__( self, name, inNamespace=False, controller='controller',
437
                 cargs='-v ptcp:', cdir=None, ipAddress="127.0.0.1",
442
                 cargs='-v ptcp:', cdir=None, defaultIP="127.0.0.1",
438 443
                 port=6633 ):
439 444
        self.controller = controller
440 445
        self.cargs = cargs
441 446
        self.cdir = cdir
442
        self.ipAddress = ipAddress
443 447
        self.port = port
444
        Node.__init__( self, name, inNamespace=inNamespace )
448
        Node.__init__( self, name, inNamespace=inNamespace,
449
            defaultIP=defaultIP )
445 450

  
446 451
    def start( self ):
447 452
        """Start <controller> <args> on controller.
......
460 465

  
461 466
    def IP( self ):
462 467
        "Return IP address of the Controller"
463
        return self.ipAddress
468
        return self.defaultIP
464 469

  
465 470

  
466 471
class ControllerParams( object ):
467 472
    "Container for controller IP parameters."
468 473

  
469
    def __init__( self, ip, subnetSize ):
474
    def __init__( self, ip, prefixLen ):
470 475
        """Init.
471
           ip: integer, controller IP
472
            subnetSize: integer, ex 8 for slash-8, covering 17M"""
476
           ip: string, controller IP address
477
           prefixLen: prefix length, e.g. 8 for /8, covering 16M"""
473 478
        self.ip = ip
474
        self.subnetSize = subnetSize
479
        self.prefixLen = prefixLen
475 480

  
476 481

  
477 482
class NOX( Controller ):
......
500 505
class RemoteController( Controller ):
501 506
    "Controller running outside of Mininet's control."
502 507

  
503
    def __init__( self, name, inNamespace=False, ipAddress='127.0.0.1',
508
    def __init__( self, name, inNamespace=False, defaultIP='127.0.0.1',
504 509
                 port=6633 ):
505 510
        """Init.
506 511
           name: name to give controller
507 512
           ipAddress: the IP address where the remote controller is
508 513
           listening
509 514
           port: the port where the remote controller is listening"""
510
        Controller.__init__( self, name, ipAddress=ipAddress, port=port )
515
        Controller.__init__( self, name, defaultIP=defaultIP, port=port )
511 516

  
512 517
    def start( self ):
513 518
        "Overridden to do nothing."

Also available in: Unified diff