Commit fa067176 authored by Martín Ferrari's avatar Martín Ferrari

Style adjustments

parent 8de4982b
...@@ -4,8 +4,11 @@ BUILDDIR = build ...@@ -4,8 +4,11 @@ BUILDDIR = build
DISTDIR = dist DISTDIR = dist
# stupid distutils, it's broken in so many ways # stupid distutils, it's broken in so many ways
SUBBUILDDIR = $(shell python -c 'import distutils.util, sys; print "lib.%s-%s" % (distutils.util.get_platform(), sys.version[0:3])') SUBBUILDDIR = $(shell python -c 'import distutils.util, sys; \
PYTHON25 := $(shell python -c 'import sys; v = sys.version_info; print (1 if v[0] <= 2 and v[1] <= 5 else 0)') print "lib.%s-%s" % (distutils.util.get_platform(), \
sys.version[0:3])')
PYTHON25 := $(shell python -c 'import sys; v = sys.version_info; \
print (1 if v[0] <= 2 and v[1] <= 5 else 0)')
ifeq ($(PYTHON25),0) ifeq ($(PYTHON25),0)
BUILDDIR := $(BUILDDIR)/$(SUBBUILDDIR) BUILDDIR := $(BUILDDIR)/$(SUBBUILDDIR)
......
...@@ -15,7 +15,7 @@ class Graph: ...@@ -15,7 +15,7 @@ class Graph:
lines = self.gen_output() lines = self.gen_output()
lines.insert(0, "set terminal postscript") lines.insert(0, "set terminal postscript")
lines.insert(0, "set output '%s'" % filename) lines.insert(0, "set output '%s'" % filename)
gnuplot = subprocess.Popen(['gnuplot', '-'], gnuplot = subprocess.Popen(['gnuplot', '-'],
stdin = subprocess.PIPE, stdin = subprocess.PIPE,
stdout = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = subprocess.STDOUT) stderr = subprocess.STDOUT)
...@@ -27,7 +27,7 @@ class Graph: ...@@ -27,7 +27,7 @@ class Graph:
gnuplot = subprocess.Popen(['gnuplot', '-'], stdin = subprocess.PIPE) gnuplot = subprocess.Popen(['gnuplot', '-'], stdin = subprocess.PIPE)
gnuplot.communicate(input = "\n".join(lines)) gnuplot.communicate(input = "\n".join(lines))
def _style_to_str(self, style): def _style_to_str(self, style):
d = {Graph.LINE: 'lines', Graph.DOT: 'dots', Graph.POINT: 'points', d = {Graph.LINE: 'lines', Graph.DOT: 'dots', Graph.POINT: 'points',
Graph.LINEPOINT: 'linespoints'} Graph.LINEPOINT: 'linespoints'}
return d[style] return d[style]
def gen_output(self, plots = None): def gen_output(self, plots = None):
...@@ -84,7 +84,7 @@ class Row: ...@@ -84,7 +84,7 @@ class Row:
def __len__(self): def __len__(self):
return len(self._data1) return len(self._data1)
# def __repr__(self): # def __repr__(self):
# return # return
class Data: class Data:
def __init__(self, rows = [], colnames = []): def __init__(self, rows = [], colnames = []):
......
...@@ -29,8 +29,8 @@ if1 = b.add_if(mtu = 1492) ...@@ -29,8 +29,8 @@ if1 = b.add_if(mtu = 1492)
# for using with a tun device, to connect to the outside world # for using with a tun device, to connect to the outside world
if2 = b.import_if('tun0') if2 = b.import_if('tun0')
# each Switch is a linux bridge, all the parameters are applied to the associated # each Switch is a linux bridge, all the parameters are applied to the
# interfaces as tc qdiscs. # associated interfaces as tc qdiscs.
switch0 = netns.Switch(bandwidth = 100 * 1024 * 1024, switch0 = netns.Switch(bandwidth = 100 * 1024 * 1024,
delay = 0.01, delay_jitter = 0.001, delay = 0.01, delay_jitter = 0.001,
delay_correlation = 0.25, delay_distribution = 'normal', delay_correlation = 0.25, delay_distribution = 'normal',
......
...@@ -6,7 +6,8 @@ from distutils.core import setup, Extension, Command ...@@ -6,7 +6,8 @@ from distutils.core import setup, Extension, Command
setup( setup(
name = 'netns', name = 'netns',
version = '0.1', version = '0.1',
description = 'A framework for creating emulated networks in a single host and run experiments on them', description = '''A framework for creating emulated networks in a
single host and run experiments on them''',
# long_description = longdesc, # long_description = longdesc,
author = 'Martin Ferrari', author = 'Martin Ferrari',
author_email = 'martin.ferrari@gmail.com', author_email = 'martin.ferrari@gmail.com',
......
...@@ -142,14 +142,14 @@ class NodeInterface(NSInterface): ...@@ -142,14 +142,14 @@ class NodeInterface(NSInterface):
class P2PInterface(NSInterface): class P2PInterface(NSInterface):
"""Class to create and handle point-to-point interfaces between name """Class to create and handle point-to-point interfaces between name
spaces, without using Switch objects. Those do not allow any kind of traffic spaces, without using Switch objects. Those do not allow any kind of
shaping. traffic shaping.
As two interfaces need to be created, instead of using the class As two interfaces need to be created, instead of using the class
constructor, use the P2PInterface.create_pair() static method.""" constructor, use the P2PInterface.create_pair() static method."""
@staticmethod @staticmethod
def create_pair(node1, node2): def create_pair(node1, node2):
"""Create and return a pair of connected P2PInterface objects, assigned """Create and return a pair of connected P2PInterface objects,
to name spaces represented by `node1' and `node2'.""" assigned to name spaces represented by `node1' and `node2'."""
if1 = netns.iproute.interface(name = P2PInterface._gen_if_name()) if1 = netns.iproute.interface(name = P2PInterface._gen_if_name())
if2 = netns.iproute.interface(name = P2PInterface._gen_if_name()) if2 = netns.iproute.interface(name = P2PInterface._gen_if_name())
pair = netns.iproute.create_if_pair(if1, if2) pair = netns.iproute.create_if_pair(if1, if2)
...@@ -180,12 +180,12 @@ class P2PInterface(NSInterface): ...@@ -180,12 +180,12 @@ class P2PInterface(NSInterface):
self._slave = None self._slave = None
class ImportedNodeInterface(NSInterface): class ImportedNodeInterface(NSInterface):
"""Class to handle already existing interfaces inside a name space: """Class to handle already existing interfaces inside a name space:
real devices, tun devices, etc. real devices, tun devices, etc.
The flag 'migrate' in the constructor indicates that the interface was migrated The flag 'migrate' in the constructor indicates that the interface was
inside the name space. migrated inside the name space.
On destruction, the interface will be restored to the original name space and On destruction, the interface will be restored to the original name space
will try to restore the original state.""" and will try to restore the original state."""
def __init__(self, node, iface, migrate = False): def __init__(self, node, iface, migrate = False):
self._slave = None self._slave = None
self._migrate = migrate self._migrate = migrate
...@@ -225,7 +225,7 @@ class TapNodeInterface(NSInterface): ...@@ -225,7 +225,7 @@ class TapNodeInterface(NSInterface):
self._fd = None self._fd = None
self._slave = None self._slave = None
iface = netns.iproute.interface(name = self._gen_if_name()) iface = netns.iproute.interface(name = self._gen_if_name())
iface, self._fd = netns.iproute.create_tap(iface) iface, self._fd = netns.iproute.create_tap(iface)
netns.iproute.change_netns(iface.name, node.pid) netns.iproute.change_netns(iface.name, node.pid)
super(TapNodeInterface, self).__init__(node, iface.index) super(TapNodeInterface, self).__init__(node, iface.index)
...@@ -241,7 +241,8 @@ class TapNodeInterface(NSInterface): ...@@ -241,7 +241,8 @@ class TapNodeInterface(NSInterface):
pass pass
class ExternalInterface(Interface): class ExternalInterface(Interface):
"""Add user-facing methods for interfaces that run in the main namespace.""" """Add user-facing methods for interfaces that run in the main
namespace."""
@property @property
def control(self): def control(self):
# This is *the* control interface # This is *the* control interface
...@@ -301,11 +302,11 @@ class SlaveInterface(ExternalInterface): ...@@ -301,11 +302,11 @@ class SlaveInterface(ExternalInterface):
class ImportedInterface(ExternalInterface): class ImportedInterface(ExternalInterface):
"""Class to handle already existing interfaces. Analogous to """Class to handle already existing interfaces. Analogous to
ImportedNodeInterface, this class only differs in that the interface is not ImportedNodeInterface, this class only differs in that the interface is
migrated inside the name space. This kind of interfaces can only be not migrated inside the name space. This kind of interfaces can only be
connected to Switch objects and not assigned to a name space. On connected to Switch objects and not assigned to a name space. On
destruction, the code will try to restore the interface to the state it was destruction, the code will try to restore the interface to the state it
in before being imported into netns.""" was in before being imported into netns."""
def __init__(self, iface): def __init__(self, iface):
self._original_state = None self._original_state = None
iface = netns.iproute.get_if(iface) iface = netns.iproute.get_if(iface)
...@@ -329,7 +330,8 @@ class Switch(ExternalInterface): ...@@ -329,7 +330,8 @@ class Switch(ExternalInterface):
def __init__(self, **args): def __init__(self, **args):
"""Creates a new Switch object, which models a linux bridge device. """Creates a new Switch object, which models a linux bridge device.
Parameters are passed to the set_parameters() method after creation.""" Parameters are passed to the set_parameters() method after
creation."""
iface = netns.iproute.create_bridge(self._gen_br_name()) iface = netns.iproute.create_bridge(self._gen_br_name())
super(Switch, self).__init__(iface.index) super(Switch, self).__init__(iface.index)
......
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import copy, os, re, socket, subprocess, sys, struct import copy, fcntl, os, re, socket, struct, subprocess, sys
from fcntl import ioctl
from netns.environ import * from netns.environ import *
# helpers # helpers
...@@ -182,8 +181,9 @@ class bridge(interface): ...@@ -182,8 +181,9 @@ class bridge(interface):
class address(object): class address(object):
"""Class for internal use. It is mostly a data container used to easily """Class for internal use. It is mostly a data container used to easily
pass information around; with some convenience methods. __eq__ and __hash__ pass information around; with some convenience methods. __eq__ and
are defined just to be able to easily find duplicated addresses.""" __hash__ are defined just to be able to easily find duplicated
addresses."""
# broadcast is not taken into account for differentiating addresses # broadcast is not taken into account for differentiating addresses
def __eq__(self, o): def __eq__(self, o):
if not isinstance(o, address): if not isinstance(o, address):
...@@ -502,8 +502,8 @@ def _sysfs_read_br(brname): ...@@ -502,8 +502,8 @@ def _sysfs_read_br(brname):
ports = os.listdir(p2)) ports = os.listdir(p2))
def get_bridge_data(): def get_bridge_data():
# brctl stinks too much; it is better to directly use sysfs, it is probably # brctl stinks too much; it is better to directly use sysfs, it is
# stable by now # probably stable by now
byidx = {} byidx = {}
bynam = {} bynam = {}
ports = {} ports = {}
...@@ -912,7 +912,7 @@ def create_tap(iface): ...@@ -912,7 +912,7 @@ def create_tap(iface):
fd = os.open("/dev/net/tun", os.O_RDWR) fd = os.open("/dev/net/tun", os.O_RDWR)
if fd == -1: if fd == -1:
raise RuntimeError("Could not open /dev/net/tun") raise RuntimeError("Could not open /dev/net/tun")
err = ioctl(fd, TUNSETIFF, struct.pack("16sH", iface.name, mode)) err = fcntl.ioctl(fd, TUNSETIFF, struct.pack("16sH", iface.name, mode))
if err < 0: if err < 0:
os.close(fd) os.close(fd)
raise RuntimeError("Could not configure device %s" % iface.name) raise RuntimeError("Could not configure device %s" % iface.name)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import os, socket, sys, traceback, unshare, weakref import os, socket, sys, traceback, unshare, weakref
from netns.environ import * from netns.environ import *
import netns.protocol, netns.subprocess_, netns.interface import netns.interface, netns.protocol, netns.subprocess_
__all__ = ['Node', 'get_nodes', 'import_if'] __all__ = ['Node', 'get_nodes', 'import_if']
...@@ -19,8 +19,8 @@ class Node(object): ...@@ -19,8 +19,8 @@ class Node(object):
"""Create a new node in the emulation. Implemented as a separate """Create a new node in the emulation. Implemented as a separate
process in a new network name space. Requires root privileges to run. process in a new network name space. Requires root privileges to run.
If keepns is true, the network name space is not created and can be run If keepns is true, the network name space is not created and can be
as a normal user, for testing. If debug is true, details of the run as a normal user, for testing. If debug is true, details of the
communication protocol are printed on stderr.""" communication protocol are printed on stderr."""
# Initialize attributes, in case something fails during __init__ # Initialize attributes, in case something fails during __init__
...@@ -119,7 +119,8 @@ class Node(object): ...@@ -119,7 +119,8 @@ class Node(object):
ifaces = self._slave.get_if_data() ifaces = self._slave.get_if_data()
for i in ifaces: for i in ifaces:
if i not in self._interfaces: if i not in self._interfaces:
iface = netns.interface.ImportedNodeInterface(self, i, migrate = True) iface = netns.interface.ImportedNodeInterface(self, i,
migrate = True)
self._auto_interfaces.append(iface) # keep it referenced! self._auto_interfaces.append(iface) # keep it referenced!
self._interfaces[i] = iface self._interfaces[i] = iface
# by the way, clean up _interfaces # by the way, clean up _interfaces
......
...@@ -63,8 +63,8 @@ _proc_commands = { ...@@ -63,8 +63,8 @@ _proc_commands = {
} }
class Server(object): class Server(object):
"""Class that implements the communication protocol and dispatches calls to """Class that implements the communication protocol and dispatches calls
the required functions. Also works as the main loop for the slave to the required functions. Also works as the main loop for the slave
process.""" process."""
def __init__(self, rfd, wfd, debug = 0): def __init__(self, rfd, wfd, debug = 0):
# Dictionary of valid commands # Dictionary of valid commands
......
#!/usr/bin/env python #!/usr/bin/env python
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import grp, os, pwd, select, time, threading, unittest import grp, os, pwd, select, time, unittest
import netns, test_util import netns, test_util
class TestConfigure(unittest.TestCase): class TestConfigure(unittest.TestCase):
...@@ -86,8 +86,10 @@ class TestGlobal(unittest.TestCase): ...@@ -86,8 +86,10 @@ class TestGlobal(unittest.TestCase):
i2b.add_v4_address('10.0.1.1', 24) i2b.add_v4_address('10.0.1.1', 24)
i3.add_v4_address('10.0.1.2', 24) i3.add_v4_address('10.0.1.2', 24)
n1.add_route(prefix = '10.0.1.0', prefix_len = 24, nexthop = '10.0.0.2') n1.add_route(prefix = '10.0.1.0', prefix_len = 24,
n3.add_route(prefix = '10.0.0.0', prefix_len = 24, nexthop = '10.0.1.1') nexthop = '10.0.0.2')
n3.add_route(prefix = '10.0.0.0', prefix_len = 24,
nexthop = '10.0.1.1')
null = file('/dev/null', 'wb') null = file('/dev/null', 'wb')
a1 = n1.Popen(['ping', '-qc1', '10.0.1.2'], stdout = null) a1 = n1.Popen(['ping', '-qc1', '10.0.1.2'], stdout = null)
...@@ -97,7 +99,8 @@ class TestGlobal(unittest.TestCase): ...@@ -97,7 +99,8 @@ class TestGlobal(unittest.TestCase):
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_run_ping_tap(self): def test_run_ping_tap(self):
"""This test simulates a point to point connection between two hosts using two tap devices""" """This test simulates a point to point connection between two hosts
using two tap devices"""
n1 = netns.Node() n1 = netns.Node()
n2 = netns.Node() n2 = netns.Node()
...@@ -128,7 +131,8 @@ class TestGlobal(unittest.TestCase): ...@@ -128,7 +131,8 @@ class TestGlobal(unittest.TestCase):
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_run_ping_tap_routing(self): def test_run_ping_tap_routing(self):
"""This test simulates a point to point connection between two hosts using two tap devices""" """This test simulates a point to point connection between two hosts
using two tap devices"""
n1 = netns.Node() n1 = netns.Node()
n2 = netns.Node() n2 = netns.Node()
n3 = netns.Node() n3 = netns.Node()
...@@ -186,4 +190,4 @@ class TestGlobal(unittest.TestCase): ...@@ -186,4 +190,4 @@ class TestGlobal(unittest.TestCase):
self.assertEquals(a.wait(), 0) self.assertEquals(a.wait(), 0)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -268,7 +268,7 @@ class TestSubprocess(unittest.TestCase): ...@@ -268,7 +268,7 @@ class TestSubprocess(unittest.TestCase):
stdin = PIPE, stdout = PIPE, stderr = PIPE) stdin = PIPE, stdout = PIPE, stderr = PIPE)
self.assertEquals(p.communicate(_longstring), (_longstring, ) * 2) self.assertEquals(p.communicate(_longstring), (_longstring, ) * 2)
def test_backticks(self): def test_backticks(self):
node = netns.Node(nonetns = True, debug = 0) node = netns.Node(nonetns = True, debug = 0)
self.assertEquals(backticks(node, "echo hello world"), "hello world\n") self.assertEquals(backticks(node, "echo hello world"), "hello world\n")
self.assertEquals(backticks(node, r"echo hello\ \ world"), self.assertEquals(backticks(node, r"echo hello\ \ world"),
...@@ -280,7 +280,7 @@ class TestSubprocess(unittest.TestCase): ...@@ -280,7 +280,7 @@ class TestSubprocess(unittest.TestCase):
self.assertRaises(RuntimeError, backticks_raise, node, "false") self.assertRaises(RuntimeError, backticks_raise, node, "false")
self.assertRaises(RuntimeError, backticks_raise, node, "kill $$") self.assertRaises(RuntimeError, backticks_raise, node, "kill $$")
def test_system(self): def test_system(self):
node = netns.Node(nonetns = True, debug = 0) node = netns.Node(nonetns = True, debug = 0)
self.assertEquals(system(node, "true"), 0) self.assertEquals(system(node, "true"), 0)
self.assertEquals(system(node, "false"), 1) self.assertEquals(system(node, "false"), 1)
......
...@@ -18,17 +18,21 @@ class TestSwitch(unittest.TestCase): ...@@ -18,17 +18,21 @@ class TestSwitch(unittest.TestCase):
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_switch_base(self): def test_switch_base(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
l.mtu = 3000 l.mtu = 3000
ifdata = netns.iproute.get_if_data()[0] ifdata = netns.iproute.get_if_data()[0]
self.assertEquals(ifdata[l.index].mtu, 3000) self.assertEquals(ifdata[l.index].mtu, 3000)
self.assertEquals(ifdata[i1.control.index].mtu, 3000, "MTU propagation") self.assertEquals(ifdata[i1.control.index].mtu, 3000,
self.assertEquals(ifdata[i2.control.index].mtu, 3000, "MTU propagation") "MTU propagation")
self.assertEquals(ifdata[i2.control.index].mtu, 3000,
"MTU propagation")
i1.mtu = i2.mtu = 3000 i1.mtu = i2.mtu = 3000
self.assertEquals(ifdata[l.index].up, False) self.assertEquals(ifdata[l.index].up, False)
self.assertEquals(ifdata[i1.control.index].up, False, "UP propagation") self.assertEquals(ifdata[i1.control.index].up, False,
self.assertEquals(ifdata[i2.control.index].up, False, "UP propagation") "UP propagation")
self.assertEquals(ifdata[i2.control.index].up, False,
"UP propagation")
l.up = True l.up = True
ifdata = netns.iproute.get_if_data()[0] ifdata = netns.iproute.get_if_data()[0]
...@@ -41,7 +45,7 @@ class TestSwitch(unittest.TestCase): ...@@ -41,7 +45,7 @@ class TestSwitch(unittest.TestCase):
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_switch_changes(self): def test_switch_changes(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
# Test strange rules handling # Test strange rules handling
os.system(("%s qd add dev %s root prio bands 3 " + os.system(("%s qd add dev %s root prio bands 3 " +
...@@ -70,14 +74,14 @@ class TestSwitch(unittest.TestCase): ...@@ -70,14 +74,14 @@ class TestSwitch(unittest.TestCase):
self._test_none() # both => none self._test_none() # both => none
def _test_none(self): def _test_none(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
l.set_parameters() l.set_parameters()
tcdata = netns.iproute.get_tc_data()[0] tcdata = netns.iproute.get_tc_data()[0]
self.assertEquals(tcdata[i1.control.index], {"qdiscs": {}}) self.assertEquals(tcdata[i1.control.index], {"qdiscs": {}})
self.assertEquals(tcdata[i2.control.index], {"qdiscs": {}}) self.assertEquals(tcdata[i2.control.index], {"qdiscs": {}})
def _test_tbf(self): def _test_tbf(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
l.set_parameters(bandwidth = 13107200) # 100 mbits l.set_parameters(bandwidth = 13107200) # 100 mbits
tcdata = netns.iproute.get_tc_data()[0] tcdata = netns.iproute.get_tc_data()[0]
self.assertEquals(tcdata[i1.control.index], self.assertEquals(tcdata[i1.control.index],
...@@ -87,7 +91,7 @@ class TestSwitch(unittest.TestCase): ...@@ -87,7 +91,7 @@ class TestSwitch(unittest.TestCase):
{"bandwidth": 13107000, "qdiscs": {"tbf": "1"}}) {"bandwidth": 13107000, "qdiscs": {"tbf": "1"}})
def _test_netem(self): def _test_netem(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
l.set_parameters(delay = 0.001) # 1ms l.set_parameters(delay = 0.001) # 1ms
tcdata = netns.iproute.get_tc_data()[0] tcdata = netns.iproute.get_tc_data()[0]
self.assertEquals(tcdata[i1.control.index], self.assertEquals(tcdata[i1.control.index],
...@@ -96,7 +100,7 @@ class TestSwitch(unittest.TestCase): ...@@ -96,7 +100,7 @@ class TestSwitch(unittest.TestCase):
{"delay": 0.001, "qdiscs": {"netem": "2"}}) {"delay": 0.001, "qdiscs": {"netem": "2"}})
def _test_both(self): def _test_both(self):
(n1, n2, i1, i2, l) = self.stuff (n1, n2, i1, i2, l) = self.stuff
l.set_parameters(bandwidth = 13107200, delay = 0.001) # 100 mbits, 1ms l.set_parameters(bandwidth = 13107200, delay = 0.001) # 100 mbits, 1ms
tcdata = netns.iproute.get_tc_data()[0] tcdata = netns.iproute.get_tc_data()[0]
self.assertEquals(tcdata[i1.control.index], self.assertEquals(tcdata[i1.control.index],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment