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
385fbe6c
Commit
385fbe6c
authored
Jul 23, 2010
by
Martín Ferrari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
be able to get/set bridge parameters too
parent
57a7a20f
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
183 additions
and
78 deletions
+183
-78
src/netns/interface.py
src/netns/interface.py
+98
-55
src/netns/iproute.py
src/netns/iproute.py
+85
-23
No files found.
src/netns/interface.py
View file @
385fbe6c
...
@@ -23,6 +23,7 @@ class Interface(object):
...
@@ -23,6 +23,7 @@ class Interface(object):
return
"NETNSif-%.4x%.3x"
%
(
os
.
getpid
(),
n
)
return
"NETNSif-%.4x%.3x"
%
(
os
.
getpid
(),
n
)
def
__init__
(
self
,
index
):
def
__init__
(
self
,
index
):
self
.
_changeable_attributes
=
interface
.
changeable_attributes
self
.
_idx
=
index
self
.
_idx
=
index
def
__del__
(
self
):
def
__del__
(
self
):
...
@@ -51,7 +52,11 @@ class NSInterface(Interface):
...
@@ -51,7 +52,11 @@ class NSInterface(Interface):
# 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
):
if
(
name
not
in
interface
.
changeable_attributes
):
try
:
ca
=
object
.
__getattr__
(
self
,
'_changeable_attributes'
)
except
:
ca
=
[]
if
(
name
not
in
ca
):
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
(
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
...
@@ -60,7 +65,11 @@ class NSInterface(Interface):
...
@@ -60,7 +65,11 @@ class NSInterface(Interface):
return
getattr
(
iface
,
name
)
return
getattr
(
iface
,
name
)
def
__setattr__
(
self
,
name
,
value
):
def
__setattr__
(
self
,
name
,
value
):
if
(
name
not
in
interface
.
changeable_attributes
):
try
:
ca
=
object
.
__getattr__
(
self
,
'_changeable_attributes'
)
except
:
ca
=
[]
if
(
name
not
in
ca
):
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
))
...
@@ -199,7 +208,11 @@ class ExternalInterface(Interface):
...
@@ -199,7 +208,11 @@ class ExternalInterface(Interface):
# 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
):
if
(
name
not
in
interface
.
changeable_attributes
):
try
:
ca
=
object
.
__getattr__
(
self
,
'_changeable_attributes'
)
except
:
ca
=
[]
if
(
name
not
in
ca
):
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
raise
AttributeError
(
"'%s' object has no attribute '%s'"
%
(
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
...
@@ -208,7 +221,11 @@ class ExternalInterface(Interface):
...
@@ -208,7 +221,11 @@ class ExternalInterface(Interface):
return
getattr
(
iface
,
name
)
return
getattr
(
iface
,
name
)
def
__setattr__
(
self
,
name
,
value
):
def
__setattr__
(
self
,
name
,
value
):
if
(
name
not
in
interface
.
changeable_attributes
):
try
:
ca
=
object
.
__getattr__
(
self
,
'_changeable_attributes'
)
except
:
ca
=
[]
if
(
name
not
in
ca
):
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
))
...
@@ -302,6 +319,7 @@ class Link(ExternalInterface):
...
@@ -302,6 +319,7 @@ class Link(ExternalInterface):
iface
=
netns
.
iproute
.
create_bridge
(
self
.
_gen_br_name
())
iface
=
netns
.
iproute
.
create_bridge
(
self
.
_gen_br_name
())
super
(
Link
,
self
).
__init__
(
iface
.
index
)
super
(
Link
,
self
).
__init__
(
iface
.
index
)
self
.
_changeable_attributes
=
bridge
.
changeable_attributes
self
.
_ports
=
set
()
self
.
_ports
=
set
()
# register somewhere
# register somewhere
...
@@ -391,22 +409,6 @@ def _make_setter(attr, conv = lambda x: x):
...
@@ -391,22 +409,6 @@ def _make_setter(attr, conv = lambda x: x):
class
interface
(
object
):
class
interface
(
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."""
pass information around; with some convenience methods."""
@
classmethod
def
parse_ip
(
cls
,
line
):
"""Parse a line of ouput from `ip -o link list' and construct and
return a new object with the data."""
match
=
re
.
search
(
r'^(\
d+): (
\S+): <(\
S+)> m
tu (\
d+) qdisc
\S+'
+
r'.*link/\
S+ ([
0-9a-f:]+) brd ([0-9a-f:]+)'
,
line
)
flags
=
match
.
group
(
3
).
split
(
","
)
return
cls
(
index
=
match
.
group
(
1
),
name
=
match
.
group
(
2
),
up
=
"UP"
in
flags
,
mtu
=
match
.
group
(
4
),
lladdr
=
match
.
group
(
5
),
arp
=
not
(
"NOARP"
in
flags
),
broadcast
=
match
.
group
(
6
),
multicast
=
"MULTICAST"
in
flags
)
# information for other parts of the code
# information for other parts of the code
changeable_attributes
=
[
"name"
,
"mtu"
,
"lladdr"
,
"broadcast"
,
"up"
,
changeable_attributes
=
[
"name"
,
"mtu"
,
"lladdr"
,
"broadcast"
,
"up"
,
...
@@ -455,30 +457,71 @@ class interface(object):
...
@@ -455,30 +457,71 @@ class interface(object):
return
self
.
__class__
(
self
.
index
,
name
,
up
,
mtu
,
lladdr
,
broadcast
,
return
self
.
__class__
(
self
.
index
,
name
,
up
,
mtu
,
lladdr
,
broadcast
,
multicast
,
arp
)
multicast
,
arp
)
class
bridge
(
interface
):
changeable_attributes
=
interface
.
changeable_attributes
+
[
"stp"
,
"forward_delay"
,
"hello_time"
,
"ageing_time"
,
"max_age"
]
# Index should be read-only
stp
=
property
(
_make_getter
(
"_stp"
),
_make_setter
(
"_stp"
,
_any_to_bool
))
forward_delay
=
property
(
_make_getter
(
"_forward_delay"
),
_make_setter
(
"_forward_delay"
,
float
))
hello_time
=
property
(
_make_getter
(
"_hello_time"
),
_make_setter
(
"_hello_time"
,
float
))
ageing_time
=
property
(
_make_getter
(
"_ageing_time"
),
_make_setter
(
"_ageing_time"
,
float
))
max_age
=
property
(
_make_getter
(
"_max_age"
),
_make_setter
(
"_max_age"
,
float
))
@
classmethod
def
upgrade
(
cls
,
iface
,
*
kargs
,
**
kwargs
):
"""Upgrade a interface to a bridge."""
return
cls
(
iface
.
index
,
iface
.
name
,
iface
.
up
,
iface
.
mtu
,
iface
.
lladdr
,
iface
.
broadcast
,
iface
.
multicast
,
iface
.
arp
,
*
kargs
,
**
kwargs
)
def
__init__
(
self
,
index
=
None
,
name
=
None
,
up
=
None
,
mtu
=
None
,
lladdr
=
None
,
broadcast
=
None
,
multicast
=
None
,
arp
=
None
,
stp
=
None
,
forward_delay
=
None
,
hello_time
=
None
,
ageing_time
=
None
,
max_age
=
None
):
super
(
bridge
,
self
).
__init__
(
index
,
name
,
up
,
mtu
,
lladdr
,
broadcast
,
multicast
,
arp
)
self
.
stp
=
stp
self
.
forward_delay
=
forward_delay
self
.
hello_time
=
hello_time
self
.
ageing_time
=
ageing_time
self
.
max_age
=
max_age
def
__repr__
(
self
):
s
=
"%s.%s(index = %s, name = %s, up = %s, mtu = %s, lladdr = %s, "
s
+=
"broadcast = %s, multicast = %s, arp = %s, stp = %s, "
s
+=
"forward_delay = %s, hello_time = %s, ageing_time = %s, "
s
+=
"max_age = %s)"
return
s
%
(
self
.
__module__
,
self
.
__class__
.
__name__
,
self
.
index
.
__repr__
(),
self
.
name
.
__repr__
(),
self
.
up
.
__repr__
(),
self
.
mtu
.
__repr__
(),
self
.
lladdr
.
__repr__
(),
self
.
broadcast
.
__repr__
(),
self
.
multicast
.
__repr__
(),
self
.
arp
.
__repr__
(),
self
.
stp
.
__repr__
(),
self
.
forward_delay
.
__repr__
(),
self
.
hello_time
.
__repr__
(),
self
.
ageing_time
.
__repr__
(),
self
.
max_age
.
__repr__
())
def
__sub__
(
self
,
o
):
r
=
super
(
bridge
,
self
).
__sub__
(
o
)
if
type
(
o
)
==
interface
:
return
r
r
.
stp
=
None
if
self
.
stp
==
o
.
stp
else
self
.
stp
r
.
hello_time
=
None
if
self
.
hello_time
==
o
.
hello_time
else
\
self
.
hello_time
r
.
forward_delay
=
None
if
self
.
forward_delay
==
o
.
forward_delay
else
\
self
.
forward_delay
r
.
ageing_time
=
None
if
self
.
ageing_time
==
o
.
ageing_time
else
\
self
.
ageing_time
r
.
max_age
=
None
if
self
.
max_age
==
o
.
max_age
else
self
.
max_age
return
r
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 __hash__
are defined just to be able to easily find duplicated addresses."""
are defined just to be able to easily find duplicated addresses."""
@
classmethod
def
parse_ip
(
cls
,
line
):
"""Parse a line of ouput from `ip -o addr list' (after trimming the
index and interface name) and construct and return a new object with
the data."""
match
=
re
.
search
(
r'^inet ([0-9.]+)/(\
d+)(?:
brd ([0-9.]+))?'
,
line
)
if
match
!=
None
:
return
ipv4address
(
address
=
match
.
group
(
1
),
prefix_len
=
match
.
group
(
2
),
broadcast
=
match
.
group
(
3
))
match
=
re
.
search
(
r'^inet6 ([0-9a-f:]+)/(\
d+)
', line)
if match != None:
return ipv6address(
address = match.group(1),
prefix_len = match.group(2))
raise RuntimeError("Problems parsing ip command output")
# 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
):
...
...
src/netns/iproute.py
View file @
385fbe6c
# vim:ts=4:sw=4:et:ai:sts=4
# vim:ts=4:sw=4:et:ai:sts=4
import
re
,
subprocess
,
sys
import
os
,
re
,
subprocess
,
sys
import
netns.interface
import
netns.interface
# XXX: ideally this should be replaced by netlink communication
# XXX: ideally this should be replaced by netlink communication
...
@@ -25,7 +25,18 @@ def get_if_data():
...
@@ -25,7 +25,18 @@ def get_if_data():
continue
continue
match
=
re
.
search
(
r'^(\
d+):
\s+(.*)'
,
line
)
match
=
re
.
search
(
r'^(\
d+):
\s+(.*)'
,
line
)
idx
=
int
(
match
.
group
(
1
))
idx
=
int
(
match
.
group
(
1
))
i
=
netns
.
interface
.
interface
.
parse_ip
(
line
)
match
=
re
.
search
(
r'^(\
d+): (
\S+): <(\
S+)> m
tu (\
d+) qdisc
\S+'
+
r'.*link/\
S+ ([
0-9a-f:]+) brd ([0-9a-f:]+)'
,
line
)
flags
=
match
.
group
(
3
).
split
(
","
)
i
=
netns
.
interface
.
interface
(
index
=
match
.
group
(
1
),
name
=
match
.
group
(
2
),
up
=
"UP"
in
flags
,
mtu
=
match
.
group
(
4
),
lladdr
=
match
.
group
(
5
),
arp
=
not
(
"NOARP"
in
flags
),
broadcast
=
match
.
group
(
6
),
multicast
=
"MULTICAST"
in
flags
)
byidx
[
idx
]
=
bynam
[
i
.
name
]
=
i
byidx
[
idx
]
=
bynam
[
i
.
name
]
=
i
return
byidx
,
bynam
return
byidx
,
bynam
...
@@ -146,9 +157,25 @@ def get_addr_data():
...
@@ -146,9 +157,25 @@ def get_addr_data():
if
match
.
group
(
3
):
if
match
.
group
(
3
):
bynam
[
name
]
=
byidx
[
idx
]
=
[]
bynam
[
name
]
=
byidx
[
idx
]
=
[]
continue
# link info
continue
# link info
bynam
[
name
].
append
(
netns
.
interface
.
address
.
parse_ip
(
match
.
group
(
4
)))
bynam
[
name
].
append
(
_parse_ip_addr
(
match
.
group
(
4
)))
return
byidx
,
bynam
return
byidx
,
bynam
def
_parse_ip_addr
(
line
):
match
=
re
.
search
(
r'^inet ([0-9.]+)/(\
d+)(?:
brd ([0-9.]+))?'
,
line
)
if
match
!=
None
:
return
ipv4address
(
address
=
match
.
group
(
1
),
prefix_len
=
match
.
group
(
2
),
broadcast
=
match
.
group
(
3
))
match
=
re
.
search
(
r'^inet6 ([0-9a-f:]+)/(\
d+)
', line)
if match != None:
return ipv6address(
address = match.group(1),
prefix_len = match.group(2))
raise RuntimeError("Problems parsing ip command output")
def add_addr(iface, address):
def add_addr(iface, address):
ifname = _get_if_name(iface)
ifname = _get_if_name(iface)
addresses = get_addr_data()[1][ifname]
addresses = get_addr_data()[1][ifname]
...
@@ -194,32 +221,34 @@ def set_addr(iface, addresses, recover = True):
...
@@ -194,32 +221,34 @@ def set_addr(iface, addresses, recover = True):
# Bridge handling
# Bridge handling
def get_br_data():
def get_br_data():
ifdata
=
get_if_data
()
# brctl stinks too much; it is better to directly use sysfs, it is probably
ipcmd
=
subprocess
.
Popen
([
"brctl"
,
"show"
],
stdout
=
subprocess
.
PIPE
)
# stable by now
ipdata
=
ipcmd
.
communicate
()[
0
]
def readval(fname):
assert
ipcmd
.
wait
()
==
0
f = file(fname)
return f.readline().strip()
byidx = {}
byidx = {}
bynam = {}
bynam = {}
ports = {}
ports = {}
last
=
None
ifdata = get_if_data()
for
line
in
ipdata
.
split
(
"
\
n
"
)[
1
:]:
# skip header
for i in ifdata[1]: # by name
if
line
==
""
:
p = '
/
sys
/
class
/
net
/%
s
/
bridge
/
' % i
continue
p2 = '
/
sys
/
class
/
net
/%
s
/
brif
/
' % i
if
last
:
try:
match
=
re
.
search
(
r'^\
s+(
\S+)$'
,
line
)
os.stat(p)
if
match
:
except:
ports
[
last
].
append
(
ifdata
[
1
][
match
.
group
(
1
)])
continue
continue
params = dict(
stp = readval(p + '
stp_state
'),
forward_delay = float(readval(p + '
forward_delay
')) / 100,
hello_time = float(readval(p + '
hello_time
')) / 100,
ageing_time = float(readval(p + '
ageing_time
')) / 100,
max_age = float(readval(p + '
max_age
')) / 100)
iface = ifdata[1][i]
bynam[i] = byidx[iface.index] = netns.interface.bridge.upgrade(
iface, **params)
ports[iface.index] = [ifdata[1][x].index for x in os.listdir(p2)]
match
=
re
.
search
(
r'^(\
S+)
\s+\
S+
\s+\
S+
\s*(\
S+)?
', line)
if not match:
raise RuntimeError("Invalid `brctl'
command
output
")
name = match.group(1)
last = idx = ifdata[1][name].index
bynam[name] = byidx[idx] = ifdata[1][name]
ports[idx] = []
return byidx, bynam, ports
return byidx, bynam, ports
def create_bridge(br):
def create_bridge(br):
...
@@ -242,6 +271,39 @@ def del_bridge(br):
...
@@ -242,6 +271,39 @@ def del_bridge(br):
brname = _get_if_name(br)
brname = _get_if_name(br)
_execute(["brctl", "delbr", brname])
_execute(["brctl", "delbr", brname])
def set_bridge(br, recover = True):
def saveval(fname, val):
f = file(fname, '
w
')
f.write(str(val))
f.close()
def do_cmds(basename, cmds, orig_br):
for n, v in cmds:
try:
saveval(basename + n, v)
except:
if recover:
set_bridge(orig_br, recover = False) # rollback
set_if(orig_br, recover = False) # rollback
raise
orig_br = get_br_data()[1][_get_if_name(br)]
diff = br - orig_br # Only set what'
s
needed
cmds
=
[]
if
diff
.
stp
!=
None
:
cmds
.
append
((
'stp_state'
,
int
(
diff
.
stp
)))
if
diff
.
forward_delay
!=
None
:
cmds
.
append
((
'forward_delay'
,
int
(
diff
.
forward_delay
)))
if
diff
.
hello_time
!=
None
:
cmds
.
append
((
'hello_time'
,
int
(
diff
.
hello_time
)))
if
diff
.
ageing_time
!=
None
:
cmds
.
append
((
'ageing_time'
,
int
(
diff
.
ageing_time
)))
if
diff
.
max_age
!=
None
:
cmds
.
append
((
'max_age'
,
int
(
diff
.
max_age
)))
set_if
(
diff
)
do_cmds
(
'/sys/class/net/%s/bridge/'
%
br
.
name
,
cmds
,
orig_br
)
def
add_bridge_port
(
br
,
iface
):
def
add_bridge_port
(
br
,
iface
):
ifname
=
_get_if_name
(
iface
)
ifname
=
_get_if_name
(
iface
)
brname
=
_get_if_name
(
br
)
brname
=
_get_if_name
(
br
)
...
...
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