Commit 546472f4 authored by Martín Ferrari's avatar Martín Ferrari

many fixes to the routing code, seems to work

parent 3006f202
......@@ -224,38 +224,38 @@ class route(object):
prefix = property(_make_getter("_prefix"),
_make_setter("_prefix", _non_empty_str))
prefix_len = property(_make_getter("_plen"),
_make_setter("_plen", int))
lambda s, v: setattr(s, '_plen', int(v or 0)))
nexthop = property(_make_getter("_nexthop"),
_make_setter("_nexthop", _non_empty_str))
interface = property(_make_getter("_interface"),
_make_setter("_interface", _positive))
metric = property(_make_getter("_metric"),
_make_setter("_metric", int))
device = property(_make_getter("_device"),
_make_setter("_device", _positive))
lambda s, v: setattr(s, '_metric', int(v or 0)))
def __init__(self, tipe = 'unicast', prefix = None, prefix_len = 0,
nexthop = None, device = None, metric = 0):
nexthop = None, interface = None, metric = 0):
self.tipe = tipe
self.prefix = prefix
self.prefix_len = prefix_len
self.nexthop = nexthop
self.device = device
self.interface = interface
self.metric = metric
assert nexthop or device
assert nexthop or interface
def __repr__(self):
s = "%s.%s(tipe = %s, prefix = %s, prefix_len = %s, nexthop = %s, "
s += "device = %s, metric = %s)"
s += "interface = %s, metric = %s)"
return s % (self.__module__, self.__class__.__name__,
self.tipe.__repr__(), self.prefix.__repr__(),
self.prefix_len.__repr__(), self.nexthop.__repr__(),
self.device.__repr__(), self.metric.__repr__())
self.interface.__repr__(), self.metric.__repr__())
def __eq__(self, o):
if not isinstance(o, route):
return False
return (self.tipe == o.tipe and self.prefix == o.prefix and
self.prefix_len == o.prefix_len and self.nexthop == o.nexthop
and self.device == o.device and self.metric == o.metric)
and self.interface == o.interface and self.metric == o.metric)
# helpers
def _execute(cmd):
......@@ -614,19 +614,23 @@ def get_all_route_data():
continue
match = re.match(r'(?:(unicast|local|broadcast|multicast|throw|' +
r'unreachable|prohibit|blackhole|nat) )?' +
r'(\S+)(?: via (\S+))? dev (\S+)', line)
r'(\S+)(?: via (\S+))? dev (\S+).*(?: metric (\d+))?', line)
if not match:
raise RuntimeError("Invalid output from `ip route'")
raise RuntimeError("Invalid output from `ip route': `%s'" % line)
tipe = match.group(1) or 'unicast'
prefix = match.group(2)
nexthop = match.group(3)
device = ifdata[match.group(4)]
interface = ifdata[match.group(4)]
metric = match.group(5)
if prefix == 'default' or re.search(r'/0$', prefix):
prefix = None
prefix_len = 0
else:
prefix, foo, prefix_len = prefix.partition('/')
ret.append(route(tipe, prefix, prefix_len, nexthop, device.index))
match = re.match(r'([0-9a-f:.]+)(?:/(\d+))?$', prefix)
prefix = match.group(1)
prefix_len = int(match.group(2) or 32)
ret.append(route(tipe, prefix, prefix_len, nexthop, interface.index,
metric))
return ret
def get_route_data():
......@@ -653,6 +657,6 @@ def _add_del_route(action, route):
cmd += ['default']
if route.nexthop:
cmd += ['via', route.nexthop]
if route.device:
cmd += ['dev', _get_if_name(route.device)]
if route.interface:
cmd += ['dev', _get_if_name(route.interface)]
_execute(cmd)
......@@ -85,8 +85,8 @@ class Node(object):
def del_if(self, iface):
"""Doesn't destroy the interface if it wasn't created by us."""
iface.destroy()
del self._interfaces[iface.index]
iface.destroy()
def get_interfaces(self):
ifaces = self._slave.get_if_data()
......@@ -105,19 +105,24 @@ class Node(object):
return sorted(ret, key = lambda x: x.index)
def route(self, tipe = 'unicast', prefix = None, prefix_len = 0,
nexthop = None, interface = None, metric = 0):
return netns.iproute.route(tipe, prefix, prefix_len, nexthop,
interface.index if interface else None, metric)
def add_route(self, *args, **kwargs):
# Accepts either a route object or all its constructor's parameters
if len(args) == 1 and not kwargs:
r = args[0]
else:
r = netns.iproute.route(*args, **kwargs)
r = self.route(*args, **kwargs)
return self._slave.add_route(r)
def del_route(self, *args, **kwargs):
if len(args) == 1 and not kwargs:
r = args[0]
else:
r = netns.iproute.route(*args, **kwargs)
r = self.route(*args, **kwargs)
return self._slave.del_route(r)
def get_routes(self):
......
......@@ -382,13 +382,13 @@ class Server(object):
def do_ROUT_ADD(self, cmdname, tipe, prefix, prefixlen, nexthop, ifnr,
metric):
netns.iproute.add_route(netns.iproute.route(tipe, prefix, prefixlen,
nexthop, ifnr, metric))
nexthop, ifnr or None, metric))
self.reply(200, "Done.")
def do_ROUT_DEL(self, cmdname, tipe, prefix, prefixlen, nexthop, ifnr,
metric):
netns.iproute.del_route(netns.iproute.route(tipe, prefix, prefixlen,
nexthop, ifnr, metric))
nexthop, ifnr or None, metric))
self.reply(200, "Done.")
# ============================================================================
......@@ -598,8 +598,8 @@ class Client(object):
def _add_del_route(self, action, route):
args = ["ROUT", action, _b64(route.tipe), _b64(route.prefix),
route.prefix_len, _b64(route.nexthop), route.device,
route.metric]
route.prefix_len or 0, _b64(route.nexthop),
route.interface or 0, route.metric or 0]
self._send_cmd(*args)
self._read_and_check_reply()
......
......@@ -10,15 +10,20 @@ class TestRouting(unittest.TestCase):
routes = node.get_routes()
if(len(routes)):
self.assertRaises(ValueError, node.add_route, routes[0])
routes[0].device += 1 # should be enough to make it unique
routes[0].interface += 1 # should be enough to make it unique
self.assertRaises(ValueError, node.del_route, routes[0])
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_routing(self):
node = netns.Node()
self.assertEquals(len(node.get_routes()), 0)
if0 = node.add_if()
if0.add_v4_address('10.0.0.1', 24)
node.add_default_route(nexthop = '10.0.0.2')
if0.up = True
self.assertEquals(len(node.get_routes()), 1)
node.add_route(nexthop = '10.0.0.2') # default route
node.add_route(prefix = '10.1.0.0', prefix_len = 16,
nexthop = '10.0.0.3')
node.add_route(prefix = '11.1.0.1', prefix_len = 32, interface = if0)
......
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