Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nemu3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
nemu3
Commits
3006f202
Commit
3006f202
authored
Jul 27, 2010
by
Martín Ferrari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Routing support!
parent
206eed94
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
118 additions
and
52 deletions
+118
-52
src/netns/iproute.py
src/netns/iproute.py
+67
-18
src/netns/node.py
src/netns/node.py
+17
-7
src/netns/protocol.py
src/netns/protocol.py
+26
-27
t/test_routing.py
t/test_routing.py
+8
-0
No files found.
src/netns/iproute.py
View file @
3006f202
...
...
@@ -24,6 +24,12 @@ def _positive(val):
raise
ValueError
(
"Invalid value: %d"
%
v
)
return
v
def
_non_empty_str
(
val
):
if
val
==
''
:
return
None
else
:
return
str
(
val
)
def
_fix_lladdr
(
addr
):
foo
=
addr
.
lower
()
if
':'
in
addr
:
...
...
@@ -209,7 +215,47 @@ class ipv6address(address):
return
s
%
(
self
.
__module__
,
self
.
__class__
.
__name__
,
self
.
address
.
__repr__
(),
self
.
prefix_len
)
# XXX: ideally this should be replaced by netlink communication
class
route
(
object
):
tipes
=
[
'unicast'
,
'local'
,
'broadcast'
,
'multicast'
,
'throw'
,
'unreachable'
,
'prohibit'
,
'blackhole'
,
'nat'
]
tipe
=
property
(
_make_getter
(
"_tipe"
,
tipes
.
__getitem__
),
_make_setter
(
"_tipe"
,
tipes
.
index
))
prefix
=
property
(
_make_getter
(
"_prefix"
),
_make_setter
(
"_prefix"
,
_non_empty_str
))
prefix_len
=
property
(
_make_getter
(
"_plen"
),
_make_setter
(
"_plen"
,
int
))
nexthop
=
property
(
_make_getter
(
"_nexthop"
),
_make_setter
(
"_nexthop"
,
_non_empty_str
))
metric
=
property
(
_make_getter
(
"_metric"
),
_make_setter
(
"_metric"
,
int
))
device
=
property
(
_make_getter
(
"_device"
),
_make_setter
(
"_device"
,
_positive
))
def
__init__
(
self
,
tipe
=
'unicast'
,
prefix
=
None
,
prefix_len
=
0
,
nexthop
=
None
,
device
=
None
,
metric
=
0
):
self
.
tipe
=
tipe
self
.
prefix
=
prefix
self
.
prefix_len
=
prefix_len
self
.
nexthop
=
nexthop
self
.
device
=
device
self
.
metric
=
metric
assert
nexthop
or
device
def
__repr__
(
self
):
s
=
"%s.%s(tipe = %s, prefix = %s, prefix_len = %s, nexthop = %s, "
s
+=
"device = %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__
())
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
)
# helpers
def
_execute
(
cmd
):
...
...
@@ -228,6 +274,7 @@ def _get_if_name(iface):
return
iface
return
get_if
(
iface
).
name
# XXX: ideally this should be replaced by netlink communication
# Interface handling
def
get_if_data
():
"""Gets current interface information. Returns a tuple (byidx, bynam) in
...
...
@@ -579,31 +626,33 @@ def get_all_route_data():
prefix_len = 0
else:
prefix, foo, prefix_len = prefix.partition('/')
ret.append(
(tipe, prefix, int(prefix_len), nexthop, device
))
ret.append(
route(tipe, prefix, prefix_len, nexthop, device.index
))
return ret
def get_route_data():
# filter out non-unicast routes
return [x for x in get_all_route_data() if x
[0]
== 'unicast']
return [x for x in get_all_route_data() if x
.tipe
== 'unicast']
def del_route(tipe, prefix, prefix_len, nexthop, device):
_add_del_route('del', tipe, prefix, prefix_len, nexthop, device)
def add_route(route):
if route in get_all_route_data():
raise ValueError('Route already exists')
_add_del_route('add', route)
def add_route(tipe, prefix, prefix_len, nexthop, device):
_add_del_route('add', tipe, prefix, prefix_len, nexthop, device)
def del_route(route):
if route not in get_all_route_data():
raise ValueError('Route does not exist')
_add_del_route('del', route)
def _add_del_route(action,
tipe, prefix, prefix_len, nexthop, devic
e):
def _add_del_route(action,
rout
e):
cmd = ['ip', 'route', action]
if device:
device = _get_if_name(device)
if tipe and tipe != 'unicast':
cmd += [tipe]
if prefix:
cmd += ["
%
s
/%
d
" % (prefix, prefix_len)]
if route.tipe != 'unicast':
cmd += [route.tipe]
if route.prefix:
cmd += ["
%
s
/%
d
" % (route.prefix, route.prefix_len)]
else:
cmd += ['default']
if nexthop:
cmd += ['via', nexthop]
if device:
cmd += ['dev',
device
]
if
route.
nexthop:
cmd += ['via',
route.
nexthop]
if
route.
device:
cmd += ['dev',
_get_if_name(route.device)
]
_execute(cmd)
src/netns/node.py
View file @
3006f202
...
...
@@ -85,8 +85,8 @@ class Node(object):
def
del_if
(
self
,
iface
):
"""Doesn't destroy the interface if it wasn't created by us."""
del
self
.
_interfaces
[
iface
.
index
]
iface
.
destroy
()
del
self
.
_interfaces
[
iface
.
index
]
def
get_interfaces
(
self
):
ifaces
=
self
.
_slave
.
get_if_data
()
...
...
@@ -105,13 +105,23 @@ class Node(object):
return
sorted
(
ret
,
key
=
lambda
x
:
x
.
index
)
# FIXME: Routing
def
add_route
(
self
,
prefix
,
prefix_len
,
nexthop
=
None
,
interface
=
None
):
assert
nexthop
or
interface
def
add_default_route
(
self
,
nexthop
,
interface
=
None
):
return
self
.
add_route
(
'0.0.0.0'
,
0
,
nexthop
,
interface
)
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
)
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
)
return
self
.
_slave
.
del_route
(
r
)
def
get_routes
(
self
):
return
se
t
()
return
se
lf
.
_slave
.
get_route_data
()
# Handle the creation of the child; parent gets (fd, pid), child creates and
# runs a Server(); never returns.
...
...
src/netns/protocol.py
View file @
3006f202
...
...
@@ -37,8 +37,8 @@ _proto_commands = {
},
"ROUT"
:
{
"LIST"
:
(
""
,
""
),
"ADD"
:
(
"bbibi"
,
""
),
"DEL"
:
(
"bbibi"
,
""
)
"ADD"
:
(
"bbibi
i
"
,
""
),
"DEL"
:
(
"bbibi
i
"
,
""
)
},
"PROC"
:
{
"CRTE"
:
(
"b"
,
"b*"
),
...
...
@@ -375,16 +375,20 @@ class Server(object):
self
.
reply
(
200
,
"Done."
)
def
do_ROUT_LIST
(
self
,
cmdname
):
netns
.
iproute
.
get_route_data
()
rdata
=
netns
.
iproute
.
get_route_data
()
self
.
reply
(
200
,
[
"# Routing data follows."
]
+
yaml
.
dump
(
add
rdata
).
split
(
"
\
n
"
))
yaml
.
dump
(
rdata
).
split
(
"
\
n
"
))
def
do_ROUT_ADD
(
self
,
cmdname
,
tipe
,
prefix
,
prefixlen
,
nexthop
,
ifnr
):
netns
.
iproute
.
add_route
(
tipe
,
prefix
,
prefixlen
,
nexthop
,
ifnr
)
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
))
self
.
reply
(
200
,
"Done."
)
def
do_ROUT_DEL
(
self
,
cmdname
,
tipe
,
prefix
,
prefixlen
,
nexthop
,
ifnr
):
netns
.
iproute
.
del_route
(
tipe
,
prefix
,
prefixlen
,
nexthop
,
ifnr
)
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
))
self
.
reply
(
200
,
"Done."
)
# ============================================================================
...
...
@@ -586,28 +590,23 @@ class Client(object):
data
=
self
.
_read_and_check_reply
()
return
yaml
.
load
(
data
)
def
add_route
(
self
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
):
_add_del_route
(
"ADD"
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
)
def
del_route
(
self
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
):
_add_del_route
(
"DEL"
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
)
def
_add_del_route
(
self
,
action
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
):
if
not
tipe
:
tipe
=
'unicast'
if
not
prefix
:
prefix
=
''
prefix_len
=
0
if
not
nexthop
:
nexthop
=
''
if
not
ifnr
:
ifnr
=
0
args
=
[
"ROUT"
,
action
,
tipe
,
prefix
,
prefix_len
,
nexthop
,
ifnr
]
args
[
2
:
6
]
=
map
(
_b64
,
args
[
2
:
6
])
self
.
_send_cmd
(
args
)
def
add_route
(
self
,
route
):
self
.
_add_del_route
(
"ADD"
,
route
)
def
del_route
(
self
,
route
):
self
.
_add_del_route
(
"DEL"
,
route
)
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
]
self
.
_send_cmd
(
*
args
)
self
.
_read_and_check_reply
()
def
_b64
(
text
):
if
text
==
None
:
# easier this way
text
=
''
text
=
str
(
text
)
if
len
(
text
)
==
0
or
filter
(
lambda
x
:
ord
(
x
)
<=
ord
(
" "
)
or
ord
(
x
)
>
ord
(
"z"
)
or
x
==
"="
,
text
):
...
...
t/test_routing.py
View file @
3006f202
...
...
@@ -5,6 +5,14 @@ import netns, test_util
import
os
,
unittest
class
TestRouting
(
unittest
.
TestCase
):
def
test_base_routing
(
self
):
node
=
netns
.
Node
(
nonetns
=
True
)
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
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
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment