Separate kernel and user switches into separate objects

This commit is contained in:
Brandon Heller
2010-01-02 10:58:28 -08:00
parent 16c57ddb33
commit 1bb4412ff3
4 changed files with 124 additions and 129 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ from ripcord.topo import FatTreeTopo
from mininet.logging_mod import lg, set_loglevel, LEVELS from mininet.logging_mod import lg, set_loglevel, LEVELS
from mininet.net import Mininet, init from mininet.net import Mininet, init
from mininet.node import Switch, Host, Controller, ControllerParams, NOX from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
from mininet.topo import TreeTopo from mininet.topo import TreeTopo
# built in topologies, created only when run # built in topologies, created only when run
@@ -24,7 +24,7 @@ TOPOS = {'minimal' : (lambda: TreeTopo(depth = 2, fanout = 2)),
'fattree6' : (lambda: FatTreeTopo(k = 6))} 'fattree6' : (lambda: FatTreeTopo(k = 6))}
SWITCH_DEF = 'kernel' SWITCH_DEF = 'kernel'
SWITCHES = {'kernel' : Switch} SWITCHES = {'kernel' : KernelSwitch}
HOST_DEF = 'process' HOST_DEF = 'process'
HOSTS = {'process' : Host} HOSTS = {'process' : Host}
+10 -4
View File
@@ -377,14 +377,20 @@ class Mininet(object):
return ploss return ploss
def ping_all(self): def ping_all(self):
'''Ping between all hosts.''' '''Ping between all hosts.
self.ping()
@return ploss packet loss percentage
'''
return self.ping()
def ping_pair(self): def ping_pair(self):
'''Ping between first two hosts, useful for testing.''' '''Ping between first two hosts, useful for testing.
@return ploss packet loss percentage
'''
hosts_sorted = sorted(self.topo.hosts()) hosts_sorted = sorted(self.topo.hosts())
hosts = [hosts_sorted[0], hosts_sorted[1]] hosts = [hosts_sorted[0], hosts_sorted[1]]
self.ping(hosts = hosts) return self.ping(hosts = hosts)
@staticmethod @staticmethod
def _parseIperf(iperfOutput): def _parseIperf(iperfOutput):
+104 -109
View File
@@ -211,6 +211,102 @@ class Host(Node):
pass pass
class Switch(Node):
'''A Switch is a Node that is running (or has execed)
an OpenFlow switch.'''
def sendCmd(self, cmd):
'''Send command to Node.
@param cmd string
'''
if not self.execed:
return Node.sendCmd(self, cmd)
else:
lg.error('*** Error: %s has execed and cannot accept commands' %
self.name)
def monitor(self):
'''Monitor node.'''
if not self.execed:
return Node.monitor(self)
else:
return True, ''
class UserSwitch(Switch):
def __init__(self, name):
'''Init.
@param name
'''
Node.__init__(self, name, inNamespace = True)
def start(self, controllers):
'''Start OpenFlow reference user datapath.
Log to /tmp/sN-{ofd,ofp}.log.
@param controllers dict of controller names to objects
'''
if 'c0' not in controller:
raise Exception('User datapath start() requires controller c0')
controller = controllers['c0']
ofdlog = '/tmp/' + self.name + '-ofd.log'
ofplog = '/tmp/' + self.name + '-ofp.log'
self.cmd('ifconfig lo up')
intfs = self.intfs[1:] # 0 is mgmt interface
self.cmdPrint('ofdatapath -i ' + ','.join(intfs) +
' ptcp: 1> ' + ofdlog + ' 2> ' + ofdlog + ' &')
self.cmdPrint('ofprotocol tcp:' + controller.IP() +
' tcp:localhost --fail=closed 1> ' + ofplog + ' 2>' +
ofplog + ' &')
def stop(self):
'''Stop OpenFlow reference user datapath.'''
self.cmd('kill %ofdatapath')
self.cmd('kill %ofprotocol')
class KernelSwitch(Switch):
def __init__(self, name, datapath = None):
'''Init.
@param name
@param datapath string, datapath name
'''
self.dp = datapath
Node.__init__(self, name, inNamespace = (datapath == None))
def start(self, ignore):
'''Start up reference kernel datapath.'''
ofplog = '/tmp/' + self.name + '-ofp.log'
quietRun('ifconfig lo up')
# Delete local datapath if it exists;
# then create a new one monitoring the given interfaces
quietRun('dpctl deldp ' + self.dp)
self.cmdPrint('dpctl adddp ' + self.dp)
self.cmdPrint('dpctl addif ' + self.dp + ' ' + ' '.join(self.intfs))
# Run protocol daemon
self.cmdPrint('ofprotocol' +
' ' + self.dp + ' tcp:127.0.0.1 ' +
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &')
self.execed = False # XXX until I fix it
def stop(self):
'''Terminate reference kernel datapath.'''
quietRun('dpctl deldp ' + self.dp)
# In theory the interfaces should go away after we shut down.
# However, this takes time, so we're better off to remove them
# explicitly so that we won't get errors if we run before they
# have been removed by the kernel. Unfortunately this is very slow.
self.cmd('kill %ofprotocol')
for intf in self.intfs:
quietRun('ip link del ' + intf)
lg.info('.')
class Controller(Node): class Controller(Node):
'''A Controller is a Node that is running (or has execed) an '''A Controller is a Node that is running (or has execed) an
OpenFlow controller.''' OpenFlow controller.'''
@@ -240,105 +336,16 @@ class Controller(Node):
self.terminate() self.terminate()
class Switch(Node): class ControllerParams(object):
'''A Switch is a Node that is running (or has execed) '''Container for controller IP parameters.'''
an OpenFlow switch.''' def __init__(self, ip, subnet_size):
def __init__(self, name, datapath = None):
'''Init. '''Init.
@param name @param ip integer, controller IP
@param datapath string, datapath name @param subnet_size integer, ex 8 for slash-8, covering 17M
''' '''
self.dp = datapath self.ip = ip
Node.__init__(self, name, inNamespace = (datapath == None)) self.subnet_size = subnet_size
def _startUserDatapath(self, controllers):
'''Start OpenFlow reference user datapath.
Log to /tmp/sN-{ofd,ofp}.log.
@param controllers dict of controller names to objects
'''
if 'c0' not in controller:
raise Exception('User datapath start() requires controller c0')
controller = controllers['c0']
ofdlog = '/tmp/' + self.name + '-ofd.log'
ofplog = '/tmp/' + self.name + '-ofp.log'
self.cmd('ifconfig lo up')
intfs = self.intfs[1:] # 0 is mgmt interface
self.cmdPrint('ofdatapath -i ' + ','.join(intfs) +
' ptcp: 1> ' + ofdlog + ' 2> ' + ofdlog + ' &')
self.cmdPrint('ofprotocol tcp:' + controller.IP() +
' tcp:localhost --fail=closed 1> ' + ofplog + ' 2>' +
ofplog + ' &')
def _stopUserDatapath(self):
'''Stop OpenFlow reference user datapath.'''
self.cmd('kill %ofdatapath')
self.cmd('kill %ofprotocol')
def _startKernelDatapath(self):
'''Start up reference kernel datapath.'''
ofplog = '/tmp/' + self.name + '-ofp.log'
quietRun('ifconfig lo up')
# Delete local datapath if it exists;
# then create a new one monitoring the given interfaces
quietRun('dpctl deldp ' + self.dp)
self.cmdPrint('dpctl adddp ' + self.dp)
self.cmdPrint('dpctl addif ' + self.dp + ' ' + ' '.join(self.intfs))
# Run protocol daemon
self.cmdPrint('ofprotocol' +
' ' + self.dp + ' tcp:127.0.0.1 ' +
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &')
self.execed = False # XXX until I fix it
def _stopKernelDatapath(self):
'''Terminate reference kernel datapath.'''
quietRun('dpctl deldp ' + self.dp)
# In theory the interfaces should go away after we shut down.
# However, this takes time, so we're better off to remove them
# explicitly so that we won't get errors if we run before they
# have been removed by the kernel. Unfortunately this is very slow.
self.cmd('kill %ofprotocol')
for intf in self.intfs:
quietRun('ip link del ' + intf)
lg.info('.')
def start(self, controllers):
'''Start datapath.
@param controllers dict of controller names to objects
'''
if self.dp is None:
self._startUserDatapath(controllers)
else:
self._startKernelDatapath()
def stop(self):
'''Stop datapath.'''
if self.dp is None:
self._stopUserDatapath()
else:
self._stopKernelDatapath()
def sendCmd(self, cmd):
'''Send command to Node.
@param cmd string
'''
if not self.execed:
return Node.sendCmd(self, cmd)
else:
lg.error('*** Error: %s has execed and cannot accept commands' %
self.name)
def monitor(self):
'''Monitor node.'''
if not self.execed:
return Node.monitor(self)
else:
return True, ''
class NOX(Controller): class NOX(Controller):
@@ -360,16 +367,4 @@ class NOX(Controller):
controller = nox_core_dir + '/nox_core', controller = nox_core_dir + '/nox_core',
cargs = '--libdir=/usr/local/lib -v -i ptcp: ' + \ cargs = '--libdir=/usr/local/lib -v -i ptcp: ' + \
' '.join(nox_args), ' '.join(nox_args),
cdir = nox_core_dir, **kwargs) cdir = nox_core_dir, **kwargs)
class ControllerParams(object):
'''Container for controller IP parameters.'''
def __init__(self, ip, subnet_size):
'''Init.
@param ip integer, controller IP
@param subnet_size integer, ex 8 for slash-8, covering 17M
'''
self.ip = ip
self.subnet_size = subnet_size
+8 -14
View File
@@ -8,12 +8,12 @@ from time import sleep
import unittest import unittest
from mininet.net import init, Mininet #, DATAPATHS from mininet.net import init, Mininet #, DATAPATHS
from mininet.node import Switch, Host, NOXController, ControllerParams from mininet.node import KernelSwitch, Host, ControllerParams
from mininet.node import Controller from mininet.node import Controller
from mininet.topo import TreeTopo from mininet.topo import TreeTopo
# temporary, until user-space side is tested # temporary, until user-space side is tested
DATAPATHS = ['kernel'] SWITCHES = {'kernel' : KernelSwitch}
class testMinimal(unittest.TestCase): class testMinimal(unittest.TestCase):
'''For each datapath type, test ping with a minimal topology. '''For each datapath type, test ping with a minimal topology.
@@ -24,15 +24,12 @@ class testMinimal(unittest.TestCase):
def testMinimal(self): def testMinimal(self):
'''Ping test with both datapaths on minimal topology''' '''Ping test with both datapaths on minimal topology'''
init() init()
for datapath in DATAPATHS: for switch in SWITCHES.values():
k = datapath == 'kernel'
controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8
mn = Mininet(TreeTopo(), Switch, Host, Controller, mn = Mininet(TreeTopo(), switch, Host, Controller,
controller_params) controller_params)
mn.start() dropped = mn.run('ping')
dropped = mn.ping_test()
self.assertEqual(dropped, 0) self.assertEqual(dropped, 0)
mn.stop()
class testTree(unittest.TestCase): class testTree(unittest.TestCase):
@@ -41,16 +38,13 @@ class testTree(unittest.TestCase):
def testTree16(self): def testTree16(self):
'''Ping test with both datapaths on 16-host topology''' '''Ping test with both datapaths on 16-host topology'''
init() init()
for datapath in DATAPATHS: for switch in SWITCHES.values():
k = datapath == 'kernel'
controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8
tree_topo = TreeTopo(depth = 3, fanout = 4) tree_topo = TreeTopo(depth = 3, fanout = 4)
mn = Mininet(tree_topo, Switch, Host, Controller, mn = Mininet(tree_topo, switch, Host, Controller,
controller_params) controller_params)
mn.start() dropped = mn.run('ping')
dropped = mn.ping_test()
self.assertEqual(dropped, 0) self.assertEqual(dropped, 0)
mn.stop()
#class testLinear(unittest.TestCase): #class testLinear(unittest.TestCase):
# '''For each datapath type, test all-pairs ping with LinearNet.''' # '''For each datapath type, test all-pairs ping with LinearNet.'''