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
47dac15d
Commit
47dac15d
authored
Jul 22, 2010
by
Martín Ferrari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Massive changes to interface module. Link class
parent
fd099ed9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
195 additions
and
67 deletions
+195
-67
sample-api.py
sample-api.py
+1
-1
src/netns/__init__.py
src/netns/__init__.py
+0
-4
src/netns/interface.py
src/netns/interface.py
+192
-60
src/netns/node.py
src/netns/node.py
+1
-1
t/test_interfaces.py
t/test_interfaces.py
+1
-1
No files found.
sample-api.py
View file @
47dac15d
...
@@ -53,7 +53,7 @@ link0.connect(if1)
...
@@ -53,7 +53,7 @@ link0.connect(if1)
# Add and connect a tap device (as if a external router were plugged into a
# Add and connect a tap device (as if a external router were plugged into a
# switch)
# switch)
if2
=
netns
.
External
Interface
(
'tap0'
)
if2
=
netns
.
Foreign
Interface
(
'tap0'
)
link0
.
connect
(
if2
)
link0
.
connect
(
if2
)
link0
.
up
=
True
link0
.
up
=
True
...
...
src/netns/__init__.py
View file @
47dac15d
...
@@ -46,8 +46,4 @@ config = __Config()
...
@@ -46,8 +46,4 @@ config = __Config()
def
set_cleanup_hooks
(
on_exit
=
False
,
on_signals
=
[]):
def
set_cleanup_hooks
(
on_exit
=
False
,
on_signals
=
[]):
pass
pass
class
Link
(
object
):
def
connect
(
self
,
iface
):
pass
src/netns/interface.py
View file @
47dac15d
...
@@ -3,41 +3,51 @@
...
@@ -3,41 +3,51 @@
import
os
,
re
,
socket
,
weakref
import
os
,
re
,
socket
,
weakref
import
netns.iproute
import
netns.iproute
__all__
=
[
'NodeInterface'
,
'P2PInterface'
,
'ExternalInterface'
]
__all__
=
[
'NodeInterface'
,
'P2PInterface'
,
'ForeignInterface'
,
'ForeignNodeInterface'
,
'Link'
]
class
_
Interface
(
object
):
class
Interface
(
object
):
"""Just a base class for the *Interface classes: assign names and handle
"""Just a base class for the *Interface classes: assign names and handle
destruction."""
destruction."""
_nextid
=
0
_nextid
=
0
@
staticmethod
@
staticmethod
def
_gen_next_id
():
def
_gen_next_id
():
n
=
_
Interface
.
_nextid
n
=
Interface
.
_nextid
_
Interface
.
_nextid
+=
1
Interface
.
_nextid
+=
1
return
n
return
n
@
staticmethod
@
staticmethod
def
_gen_if_name
():
def
_gen_if_name
():
n
=
_
Interface
.
_gen_next_id
()
n
=
Interface
.
_gen_next_id
()
# Max 15 chars
# Max 15 chars
return
"NETNSif-%.4x%.3x"
%
(
os
.
getpid
(),
n
)
return
"NETNSif-%.4x%.3x"
%
(
os
.
getpid
(),
n
)
class
_NSInterface
(
_Interface
):
def
__init__
(
self
,
index
):
"""Add user-facing methods for interfaces that go into a netns."""
self
.
_idx
=
index
def
destroy
(
self
):
try
:
# no need to check _ns_if, exceptions are ignored anyways
self
.
_slave
.
del_if
(
self
.
_ns_if
)
except
:
# Maybe it already went away, or the slave died. Anyway, better
# ignore the error
pass
def
__del__
(
self
):
def
__del__
(
self
):
self
.
destroy
()
self
.
destroy
()
def
destroy
(
self
):
raise
NotImplementedError
@
property
@
property
def
index
(
self
):
def
index
(
self
):
return
self
.
_ns_if
"""Interface index as seen by the kernel."""
return
self
.
_idx
@
property
def
control
(
self
):
"""Associated interface in the main name space (if it exists). Only
control interfaces can be put into a Link, for example."""
return
None
class
NSInterface
(
Interface
):
"""Add user-facing methods for interfaces that go into a netns."""
def
__init__
(
self
,
node
,
index
):
super
(
NSInterface
,
self
).
__init__
(
index
)
self
.
_slave
=
node
.
_slave
node
.
_add_interface
(
self
)
# some black magic to automatically get/set interface attributes
# some black magic to automatically get/set interface attributes
def
__getattr__
(
self
,
name
):
def
__getattr__
(
self
,
name
):
...
@@ -46,7 +56,7 @@ class _NSInterface(_Interface):
...
@@ -46,7 +56,7 @@ class _NSInterface(_Interface):
(
self
.
__class__
.
__name__
,
name
))
(
self
.
__class__
.
__name__
,
name
))
# I can use attributes now, as long as they are not in
# I can use attributes now, as long as they are not in
# changeable_attributes
# changeable_attributes
iface
=
self
.
_slave
.
get_if_data
(
self
.
_ns_if
)
iface
=
self
.
_slave
.
get_if_data
(
self
.
index
)
return
getattr
(
iface
,
name
)
return
getattr
(
iface
,
name
)
def
__setattr__
(
self
,
name
,
value
):
def
__setattr__
(
self
,
name
,
value
):
...
@@ -54,30 +64,30 @@ class _NSInterface(_Interface):
...
@@ -54,30 +64,30 @@ class _NSInterface(_Interface):
if
name
[
0
]
!=
'_'
:
# forbid anything that doesn't start with a _
if
name
[
0
]
!=
'_'
:
# forbid anything that doesn't start with a _
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
(
self
.
__class__
.
__name__
,
name
))
(
self
.
__class__
.
__name__
,
name
))
super
(
_
Interface
,
self
).
__setattr__
(
name
,
value
)
super
(
Interface
,
self
).
__setattr__
(
name
,
value
)
return
return
iface
=
interface
(
index
=
self
.
_ns_if
)
iface
=
interface
(
index
=
self
.
index
)
setattr
(
iface
,
name
,
value
)
setattr
(
iface
,
name
,
value
)
return
self
.
_slave
.
set_if
(
iface
)
return
self
.
_slave
.
set_if
(
iface
)
def
add_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
def
add_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
self
.
_slave
.
add_addr
(
self
.
_ns_if
,
addr
)
self
.
_slave
.
add_addr
(
self
.
index
,
addr
)
def
add_v6_address
(
self
,
address
,
prefix_len
):
def
add_v6_address
(
self
,
address
,
prefix_len
):
addr
=
ipv6address
(
address
,
prefix_len
)
addr
=
ipv6address
(
address
,
prefix_len
)
self
.
_slave
.
add_addr
(
self
.
_ns_if
,
addr
)
self
.
_slave
.
add_addr
(
self
.
index
,
addr
)
def
del_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
def
del_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
self
.
_slave
.
del_addr
(
self
.
_ns_if
,
addr
)
self
.
_slave
.
del_addr
(
self
.
index
,
addr
)
def
del_v6_address
(
self
,
address
,
prefix_len
):
def
del_v6_address
(
self
,
address
,
prefix_len
):
addr
=
ipv6address
(
address
,
prefix_len
)
addr
=
ipv6address
(
address
,
prefix_len
)
self
.
_slave
.
del_addr
(
self
.
_ns_if
,
addr
)
self
.
_slave
.
del_addr
(
self
.
index
,
addr
)
def
get_addresses
(
self
):
def
get_addresses
(
self
):
addresses
=
self
.
_slave
.
get_addr_data
(
self
.
_ns_if
)
addresses
=
self
.
_slave
.
get_addr_data
(
self
.
index
)
ret
=
[]
ret
=
[]
for
a
in
addresses
:
for
a
in
addresses
:
if
hasattr
(
a
,
'broadcast'
):
if
hasattr
(
a
,
'broadcast'
):
...
@@ -93,7 +103,7 @@ class _NSInterface(_Interface):
...
@@ -93,7 +103,7 @@ class _NSInterface(_Interface):
family
=
'inet6'
))
family
=
'inet6'
))
return
ret
return
ret
class
NodeInterface
(
_
NSInterface
):
class
NodeInterface
(
NSInterface
):
"""Class to create and handle a virtual interface inside a name space, it
"""Class to create and handle a virtual interface inside a name space, it
can be connected to a Link object with emulation of link
can be connected to a Link object with emulation of link
characteristics."""
characteristics."""
...
@@ -109,16 +119,22 @@ class NodeInterface(_NSInterface):
...
@@ -109,16 +119,22 @@ class NodeInterface(_NSInterface):
netns
.
iproute
.
del_if
(
ctl
)
netns
.
iproute
.
del_if
(
ctl
)
# the other interface should go away automatically
# the other interface should go away automatically
raise
raise
self
.
_ctl_if
=
ctl
.
index
self
.
_control
=
SlaveInterface
(
ctl
.
index
)
self
.
_ns_if
=
ns
.
index
super
(
NodeInterface
,
self
).
__init__
(
node
,
ns
.
index
)
self
.
_slave
=
node
.
_slave
node
.
_add_interface
(
self
)
@
property
@
property
def
control_index
(
self
):
def
control
(
self
):
return
self
.
_ctl_if
return
self
.
_control
def
destroy
(
self
):
try
:
self
.
_slave
.
del_if
(
self
.
index
)
except
:
# Maybe it already went away, or the slave died. Anyway, better
# ignore the error
pass
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 Link objects. Those do not allow any kind of traffic
spaces, without using Link objects. Those do not allow any kind of traffic
shaping.
shaping.
...
@@ -140,14 +156,10 @@ class P2PInterface(_NSInterface):
...
@@ -140,14 +156,10 @@ class P2PInterface(_NSInterface):
raise
raise
o1
=
P2PInterface
.
__new__
(
P2PInterface
)
o1
=
P2PInterface
.
__new__
(
P2PInterface
)
o1
.
_slave
=
node1
.
_slave
super
(
P2PInterface
,
o1
).
__init__
(
node1
,
pair
[
0
].
index
)
o1
.
_ns_if
=
pair
[
0
].
index
node1
.
_add_interface
(
o1
)
o2
=
P2PInterface
.
__new__
(
P2PInterface
)
o2
=
P2PInterface
.
__new__
(
P2PInterface
)
o2
.
_slave
=
node2
.
_slave
super
(
P2PInterface
,
o2
).
__init__
(
node2
,
pair
[
1
].
index
)
o2
.
_ns_if
=
pair
[
1
].
index
node2
.
_add_interface
(
o2
)
return
o1
,
o2
return
o1
,
o2
...
@@ -155,28 +167,13 @@ class P2PInterface(_NSInterface):
...
@@ -155,28 +167,13 @@ class P2PInterface(_NSInterface):
"Not to be called directly. Use P2PInterface.create_pair()"
"Not to be called directly. Use P2PInterface.create_pair()"
raise
RuntimeError
(
P2PInterface
.
__init__
.
__doc__
)
raise
RuntimeError
(
P2PInterface
.
__init__
.
__doc__
)
class
ExternalInterface
(
_Interface
):
def
destroy
(
self
):
"""Class to handle already existing interfaces. This kind of interfaces can
only be connected to Link objects and not assigned to a name space.
On destruction, the code will try to restore the interface to the state it
was in before being imported into netns."""
def
__init__
(
self
,
iface
):
iface
=
netns
.
iproute
.
get_if
(
iface
)
self
.
_ctl_if
=
iface
.
index
self
.
_original_state
=
iface
# FIXME: register somewhere for destruction!
def
destroy
(
self
):
# override: restore as much as possible
try
:
try
:
netns
.
iproute
.
set_if
(
self
.
_original_state
)
self
.
_slave
.
del_if
(
self
.
index
)
except
:
except
:
pass
pass
@
property
class
ForeignNodeInterface
(
NSInterface
):
def
control_index
(
self
):
return
self
.
_ctl_if
class
ExternalNodeInterface
(
_NSInterface
):
"""Class to handle already existing interfaces inside a name space, usually
"""Class to handle already existing interfaces inside a name space, usually
just the loopback device, but it can be other user-created interfaces. On
just the loopback device, but it can be other user-created interfaces. 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 was
...
@@ -184,10 +181,7 @@ class ExternalNodeInterface(_NSInterface):
...
@@ -184,10 +181,7 @@ class ExternalNodeInterface(_NSInterface):
def
__init__
(
self
,
node
,
iface
):
def
__init__
(
self
,
node
,
iface
):
iface
=
node
.
_slave
.
get_if_data
(
iface
)
iface
=
node
.
_slave
.
get_if_data
(
iface
)
self
.
_original_state
=
iface
self
.
_original_state
=
iface
super
(
ForeignNodeInterface
,
self
).
__init__
(
node
,
iface
.
index
)
self
.
_ns_if
=
iface
.
index
self
.
_slave
=
node
.
_slave
node
.
_add_interface
(
self
)
# FIXME: register somewhere for destruction!
# FIXME: register somewhere for destruction!
def
destroy
(
self
):
# override: restore as much as possible
def
destroy
(
self
):
# override: restore as much as possible
...
@@ -196,6 +190,144 @@ class ExternalNodeInterface(_NSInterface):
...
@@ -196,6 +190,144 @@ class ExternalNodeInterface(_NSInterface):
except
:
except
:
pass
pass
class
ExternalInterface
(
Interface
):
"""Add user-facing methods for interfaces that run in the main namespace."""
@
property
def
control
(
self
):
# This is *the* control interface
return
self
# some black magic to automatically get/set interface attributes
def
__getattr__
(
self
,
name
):
if
(
name
not
in
interface
.
changeable_attributes
):
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
(
self
.
__class__
.
__name__
,
name
))
# I can use attributes now, as long as they are not in
# changeable_attributes
iface
=
netns
.
iproute
.
get_if
(
self
.
index
)
return
getattr
(
iface
,
name
)
def
__setattr__
(
self
,
name
,
value
):
if
(
name
not
in
interface
.
changeable_attributes
):
if
name
[
0
]
!=
'_'
:
# forbid anything that doesn't start with a _
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
(
self
.
__class__
.
__name__
,
name
))
super
(
Interface
,
self
).
__setattr__
(
name
,
value
)
return
iface
=
interface
(
index
=
self
.
index
)
setattr
(
iface
,
name
,
value
)
return
netns
.
iproute
.
set_if
(
iface
)
def
add_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
netns
.
iproute
.
add_addr
(
self
.
index
,
addr
)
def
add_v6_address
(
self
,
address
,
prefix_len
):
addr
=
ipv6address
(
address
,
prefix_len
)
netns
.
iproute
.
add_addr
(
self
.
index
,
addr
)
def
del_v4_address
(
self
,
address
,
prefix_len
,
broadcast
=
None
):
addr
=
ipv4address
(
address
,
prefix_len
,
broadcast
)
netns
.
iproute
.
del_addr
(
self
.
index
,
addr
)
def
del_v6_address
(
self
,
address
,
prefix_len
):
addr
=
ipv6address
(
address
,
prefix_len
)
netns
.
iproute
.
del_addr
(
self
.
index
,
addr
)
def
get_addresses
(
self
):
addresses
=
netns
.
iproute
.
get_addr_data
(
self
.
index
)
ret
=
[]
for
a
in
addresses
:
if
hasattr
(
a
,
'broadcast'
):
ret
.
append
(
dict
(
address
=
a
.
address
,
prefix_len
=
a
.
prefix_len
,
broadcast
=
a
.
broadcast
,
family
=
'inet'
))
else
:
ret
.
append
(
dict
(
address
=
a
.
address
,
prefix_len
=
a
.
prefix_len
,
family
=
'inet6'
))
return
ret
class
SlaveInterface
(
ExternalInterface
):
"""Class to handle the main-name-space-facing couples of Nodeinterface.
Does nothing, just avoids any destroy code."""
def
destroy
(
self
):
pass
class
ForeignInterface
(
ExternalInterface
):
"""Class to handle already existing interfaces. This kind of interfaces can
only be connected to Link objects and not assigned to a name space.
On destruction, the code will try to restore the interface to the state it
was in before being imported into netns."""
def
__init__
(
self
,
iface
):
iface
=
netns
.
iproute
.
get_if
(
iface
)
self
.
_original_state
=
iface
super
(
ForeignInterface
,
self
).
__init__
(
iface
.
index
)
# FIXME: register somewhere for destruction!
def
destroy
(
self
):
# override: restore as much as possible
try
:
netns
.
iproute
.
set_if
(
self
.
_original_state
)
except
:
pass
# Link is just another interface type
class
Link
(
ExternalInterface
):
@
staticmethod
def
_gen_br_name
():
n
=
Link
.
_gen_next_id
()
# Max 15 chars
return
"NETNSbr-%.4x%.3x"
%
(
os
.
getpid
(),
n
)
def
__init__
(
self
,
bandwidth
=
None
,
delay
=
None
,
delay_jitter
=
None
,
delay_correlation
=
None
,
delay_distribution
=
None
,
loss
=
None
,
loss_correlation
=
None
,
dup
=
None
,
dup_correlation
=
None
,
corrupt
=
None
,
corrupt_correlation
=
None
):
self
.
_bandwidth
=
bandwidth
self
.
_delay
=
delay
self
.
_delay_jitter
=
delay_jitter
self
.
_delay_correlation
=
delay_correlation
self
.
_delay_distribution
=
delay_distribution
self
.
_loss
=
loss
self
.
_loss_correlation
=
loss_correlation
self
.
_dup
=
dup
self
.
_dup_correlation
=
dup_correlation
self
.
_corrupt
=
corrupt
self
.
_corrupt_correlation
=
corrupt_correlation
iface
=
netns
.
iproute
.
create_bridge
(
self
.
_gen_br_name
())
super
(
Link
,
self
).
__init__
(
iface
.
index
)
self
.
_ports
=
set
()
# register somewhere
def
__del__
(
self
):
self
.
destroy
()
def
destroy
(
self
):
for
p
in
self
.
_ports
:
try
:
self
.
disconnect
(
p
)
except
:
pass
netns
.
iproute
.
del_bridge
(
self
.
index
)
def
connect
(
self
,
iface
):
assert
iface
.
control
.
index
not
in
self
.
_ports
netns
.
iproute
.
add_bridge_port
(
self
.
index
,
iface
.
control
.
index
)
self
.
_ports
.
add
(
iface
.
control
.
index
)
def
disconnect
(
self
,
iface
):
assert
iface
.
control
.
index
in
self
.
_ports
netns
.
iproute
.
del_bridge_port
(
self
.
index
,
iface
.
control
.
index
)
self
.
_ports
.
remove
(
iface
.
control
.
index
)
# don't look after this :-)
# don't look after this :-)
# helpers
# helpers
...
...
src/netns/node.py
View file @
47dac15d
...
@@ -93,7 +93,7 @@ class Node(object):
...
@@ -93,7 +93,7 @@ class Node(object):
ret
=
[]
ret
=
[]
for
i
in
ifaces
:
for
i
in
ifaces
:
if
i
not
in
self
.
_interfaces
:
if
i
not
in
self
.
_interfaces
:
ret
.
append
(
netns
.
interface
.
External
NodeInterface
(
self
,
i
))
ret
.
append
(
netns
.
interface
.
Foreign
NodeInterface
(
self
,
i
))
else
:
else
:
ret
.
append
(
self
.
_interfaces
[
i
])
ret
.
append
(
self
.
_interfaces
[
i
])
# by the way, clean up _interfaces
# by the way, clean up _interfaces
...
...
t/test_interfaces.py
View file @
47dac15d
...
@@ -40,7 +40,7 @@ class TestInterfaces(unittest.TestCase):
...
@@ -40,7 +40,7 @@ class TestInterfaces(unittest.TestCase):
devs
=
get_devs
()
devs
=
get_devs
()
for
i
in
range
(
5
):
for
i
in
range
(
5
):
peer_name
=
netns
.
iproute
.
get_if
(
ifaces
[
i
].
control
_
index
).
name
peer_name
=
netns
.
iproute
.
get_if
(
ifaces
[
i
].
control
.
index
).
name
self
.
assertTrue
(
peer_name
in
devs
)
self
.
assertTrue
(
peer_name
in
devs
)
@
test_util
.
skipUnless
(
os
.
getuid
()
==
0
,
"Test requires root privileges"
)
@
test_util
.
skipUnless
(
os
.
getuid
()
==
0
,
"Test requires root privileges"
)
...
...
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