From 1bb4412ff345a8c3583bbf881ae3be6679a44a3e Mon Sep 17 00:00:00 2001 From: Brandon Heller <brandonh@stanford.edu> Date: Sat, 2 Jan 2010 08:51:24 -0800 Subject: [PATCH] Separate kernel and user switches into separate objects --- bin/mn_run.py | 4 +- mininet/net.py | 14 ++-- mininet/node.py | 145 ++++++++++++++++++-------------------- mininet/test/test_nets.py | 22 +++--- 4 files changed, 90 insertions(+), 95 deletions(-) diff --git a/bin/mn_run.py b/bin/mn_run.py index 0aa72482..2c566c48 100755 --- a/bin/mn_run.py +++ b/bin/mn_run.py @@ -11,7 +11,7 @@ from mininet.logging_mod import lg, set_loglevel, LEVELS 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 # built in topologies, created only when run @@ -24,7 +24,7 @@ 'fattree6' : (lambda: FatTreeTopo(k = 6))} SWITCH_DEF = 'kernel' -SWITCHES = {'kernel' : Switch} +SWITCHES = {'kernel' : KernelSwitch} HOST_DEF = 'process' HOSTS = {'process' : Host} diff --git a/mininet/net.py b/mininet/net.py index 063ca23f..0a72349d 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -377,14 +377,20 @@ def ping(self, hosts = None): return ploss def ping_all(self): - '''Ping between all hosts.''' - self.ping() + '''Ping between all hosts. + + @return ploss packet loss percentage + ''' + return self.ping() 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 = [hosts_sorted[0], hosts_sorted[1]] - self.ping(hosts = hosts) + return self.ping(hosts = hosts) @staticmethod def _parseIperf(iperfOutput): diff --git a/mininet/node.py b/mininet/node.py index 023d01c3..dab98ddd 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -211,49 +211,38 @@ class Host(Node): pass -class Controller(Node): - '''A Controller is a Node that is running (or has execed) an - OpenFlow controller.''' - - def __init__(self, name, inNamespace = False, controller = 'controller', - cargs = '-v ptcp:', cdir = None): - self.controller = controller - self.cargs = cargs - self.cdir = cdir - Node.__init__(self, name, inNamespace = inNamespace) +class Switch(Node): + '''A Switch is a Node that is running (or has execed) + an OpenFlow switch.''' - def start(self): - '''Start <controller> <args> on controller. + def sendCmd(self, cmd): + '''Send command to Node. - Log to /tmp/cN.log + @param cmd string ''' - cout = '/tmp/' + self.name + '.log' - if self.cdir is not None: - self.cmdPrint('cd ' + self.cdir) - self.cmdPrint(self.controller + ' ' + self.cargs + - ' 1> ' + cout + ' 2> ' + cout + ' &') - self.execed = False # XXX Until I fix it - - def stop(self): - '''Stop controller.''' - self.cmd('kill %' + self.controller) - self.terminate() + 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 Switch(Node): - '''A Switch is a Node that is running (or has execed) - an OpenFlow switch.''' +class UserSwitch(Switch): - def __init__(self, name, datapath = None): + def __init__(self, name): '''Init. @param name - @param datapath string, datapath name ''' - self.dp = datapath - Node.__init__(self, name, inNamespace = (datapath == None)) + Node.__init__(self, name, inNamespace = True) - def _startUserDatapath(self, controllers): + def start(self, controllers): '''Start OpenFlow reference user datapath. Log to /tmp/sN-{ofd,ofp}.log. @@ -273,12 +262,24 @@ def _startUserDatapath(self, controllers): ' tcp:localhost --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &') - def _stopUserDatapath(self): + def stop(self): '''Stop OpenFlow reference user datapath.''' self.cmd('kill %ofdatapath') self.cmd('kill %ofprotocol') - def _startKernelDatapath(self): + +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') @@ -293,7 +294,7 @@ def _startKernelDatapath(self): ' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &') self.execed = False # XXX until I fix it - def _stopKernelDatapath(self): + def stop(self): '''Terminate reference kernel datapath.''' quietRun('dpctl deldp ' + self.dp) # In theory the interfaces should go away after we shut down. @@ -305,40 +306,46 @@ def _stopKernelDatapath(self): quietRun('ip link del ' + intf) lg.info('.') - def start(self, controllers): - '''Start datapath. - @param controllers dict of controller names to objects +class Controller(Node): + '''A Controller is a Node that is running (or has execed) an + OpenFlow controller.''' + + def __init__(self, name, inNamespace = False, controller = 'controller', + cargs = '-v ptcp:', cdir = None): + self.controller = controller + self.cargs = cargs + self.cdir = cdir + Node.__init__(self, name, inNamespace = inNamespace) + + def start(self): + '''Start <controller> <args> on controller. + + Log to /tmp/cN.log ''' - if self.dp is None: - self._startUserDatapath(controllers) - else: - self._startKernelDatapath() + cout = '/tmp/' + self.name + '.log' + if self.cdir is not None: + self.cmdPrint('cd ' + self.cdir) + self.cmdPrint(self.controller + ' ' + self.cargs + + ' 1> ' + cout + ' 2> ' + cout + ' &') + self.execed = False # XXX Until I fix it def stop(self): - '''Stop datapath.''' - if self.dp is None: - self._stopUserDatapath() - else: - self._stopKernelDatapath() + '''Stop controller.''' + self.cmd('kill %' + self.controller) + self.terminate() - 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) +class ControllerParams(object): + '''Container for controller IP parameters.''' + def __init__(self, ip, subnet_size): + '''Init. - def monitor(self): - '''Monitor node.''' - if not self.execed: - return Node.monitor(self) - else: - return True, '' + @param ip integer, controller IP + @param subnet_size integer, ex 8 for slash-8, covering 17M + ''' + self.ip = ip + self.subnet_size = subnet_size class NOX(Controller): @@ -360,16 +367,4 @@ def __init__(self, name, inNamespace = False, nox_args = None, **kwargs): controller = nox_core_dir + '/nox_core', cargs = '--libdir=/usr/local/lib -v -i ptcp: ' + \ ' '.join(nox_args), - 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 \ No newline at end of file + cdir = nox_core_dir, **kwargs) \ No newline at end of file diff --git a/mininet/test/test_nets.py b/mininet/test/test_nets.py index ed6570df..2c65fd19 100755 --- a/mininet/test/test_nets.py +++ b/mininet/test/test_nets.py @@ -8,12 +8,12 @@ import unittest 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.topo import TreeTopo # temporary, until user-space side is tested -DATAPATHS = ['kernel'] +SWITCHES = {'kernel' : KernelSwitch} class testMinimal(unittest.TestCase): '''For each datapath type, test ping with a minimal topology. @@ -24,15 +24,12 @@ class testMinimal(unittest.TestCase): def testMinimal(self): '''Ping test with both datapaths on minimal topology''' init() - for datapath in DATAPATHS: - k = datapath == 'kernel' + for switch in SWITCHES.values(): controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 - mn = Mininet(TreeTopo(), Switch, Host, Controller, + mn = Mininet(TreeTopo(), switch, Host, Controller, controller_params) - mn.start() - dropped = mn.ping_test() + dropped = mn.run('ping') self.assertEqual(dropped, 0) - mn.stop() class testTree(unittest.TestCase): @@ -41,16 +38,13 @@ class testTree(unittest.TestCase): def testTree16(self): '''Ping test with both datapaths on 16-host topology''' init() - for datapath in DATAPATHS: - k = datapath == 'kernel' + for switch in SWITCHES.values(): controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 tree_topo = TreeTopo(depth = 3, fanout = 4) - mn = Mininet(tree_topo, Switch, Host, Controller, + mn = Mininet(tree_topo, switch, Host, Controller, controller_params) - mn.start() - dropped = mn.ping_test() + dropped = mn.run('ping') self.assertEqual(dropped, 0) - mn.stop() #class testLinear(unittest.TestCase): # '''For each datapath type, test all-pairs ping with LinearNet.''' -- GitLab