Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pim_dm
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
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
pim_dm
Commits
8f254e2d
Commit
8f254e2d
authored
Aug 24, 2018
by
Pedro Oliveira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use IPDB also to obtain metric and RPF interface
parent
3ac652db
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
124 additions
and
123 deletions
+124
-123
Kernel.py
Kernel.py
+1
-1
UnicastRouting.py
UnicastRouting.py
+98
-51
tree/KernelEntry.py
tree/KernelEntry.py
+25
-71
No files found.
Kernel.py
View file @
8f254e2d
...
...
@@ -355,7 +355,7 @@ class Kernel:
if
ip_src
not
in
self
.
routing
:
self
.
routing
[
ip_src
]
=
{}
iif
=
self
.
vif_dic
.
get
(
UnicastRouting
.
check_rpf
(
ip_src
)
)
iif
=
UnicastRouting
.
check_rpf
(
ip_src
)
self
.
set_flood_multicast_route
(
ip_src
,
ip_dst
,
iif
)
self
.
routing
[
ip_src
][
ip_dst
]
=
kernel_entry
return
kernel_entry
...
...
UnicastRouting.py
View file @
8f254e2d
import
socket
import
ipaddress
from
threading
import
RLock
from
pyroute2
import
IPDB
,
IPRoute
import
Main
from
utils
import
if_indextoname
def
get_route
(
ip_dst
:
str
):
...
...
@@ -17,10 +18,12 @@ def check_rpf(ip_dst):
return
UnicastRouting
.
check_rpf
(
ip_dst
)
def
get_unicast_info
(
ip_dst
):
return
UnicastRouting
.
get_unicast_info
(
ip_dst
)
class
UnicastRouting
(
object
):
ipr
=
None
ipdb
=
None
lock
=
RLock
()
def
__init__
(
self
):
UnicastRouting
.
ipr
=
IPRoute
()
...
...
@@ -28,60 +31,85 @@ class UnicastRouting(object):
self
.
_ipdb
=
UnicastRouting
.
ipdb
self
.
_ipdb
.
register_callback
(
UnicastRouting
.
unicast_changes
,
mode
=
"post"
)
# get metrics (routing preference and cost) to IP ip_dst
@
staticmethod
def
get_route
(
ip_dst
:
str
):
def
get_metric
(
ip_dst
:
str
):
(
metric_administrative_distance
,
metric_cost
,
_
,
_
,
mask
)
=
UnicastRouting
.
get_unicast_info
(
ip_dst
)
return
(
metric_administrative_distance
,
metric_cost
,
mask
)
# get output interface IP, used to send data to IP ip_dst
# (root interface IP to ip_dst)
@
staticmethod
def
check_rpf
(
ip_dst
):
# vif index of rpf interface
return
UnicastRouting
.
get_unicast_info
(
ip_dst
)[
3
]
@
staticmethod
def
get_route
(
ip_dst
:
str
):
ip_bytes
=
socket
.
inet_aton
(
ip_dst
)
ip_int
=
int
.
from_bytes
(
ip_bytes
,
byteorder
=
'big'
)
info
=
None
with
UnicastRouting
.
lock
:
ipdb
=
UnicastRouting
.
ipdb
# type:IPDB
for
mask_len
in
range
(
32
,
0
,
-
1
):
ip_bytes
=
(
ip_int
&
(
0xFFFFFFFF
<<
(
32
-
mask_len
))).
to_bytes
(
4
,
"big"
)
ip_dst
=
socket
.
inet_ntoa
(
ip_bytes
)
+
"/"
+
str
(
mask_len
)
print
(
ip_dst
)
if
ip_dst
in
ipdb
.
routes
:
ipdb
=
UnicastRouting
.
ipdb
# type:IPDB
for
mask_len
in
range
(
32
,
0
,
-
1
):
ip_bytes
=
(
ip_int
&
(
0xFFFFFFFF
<<
(
32
-
mask_len
))).
to_bytes
(
4
,
"big"
)
ip_dst
=
socket
.
inet_ntoa
(
ip_bytes
)
+
"/"
+
str
(
mask_len
)
print
(
ip_dst
)
if
ip_dst
in
ipdb
.
routes
:
print
(
info
)
if
ipdb
.
routes
[
ip_dst
][
'ipdb_scope'
]
!=
'gc'
:
info
=
ipdb
.
routes
[
ip_dst
]
break
else
:
continue
if
not
info
:
print
(
"0.0.0.0/0"
)
break
else
:
continue
if
not
info
:
print
(
"0.0.0.0/0"
)
if
"default"
in
ipdb
.
routes
:
info
=
ipdb
.
routes
[
"default"
]
print
(
info
)
return
info
print
(
info
)
return
info
# get metrics (routing preference and cost) to IP ip_dst
@
staticmethod
def
get_metric
(
ip_dst
:
str
):
unicast_routing_entry
=
UnicastRouting
.
get_route
(
ip_dst
)
entry_protocol
=
unicast_routing_entry
[
"proto"
]
entry_cost
=
unicast_routing_entry
[
"priority"
]
mask
=
unicast_routing_entry
[
"dst_len"
]
if
entry_cost
is
None
:
entry_cost
=
0
return
(
entry_protocol
,
entry_cost
,
mask
)
def
get_unicast_info
(
ip_dst
):
metric_administrative_distance
=
0xFFFFFFFF
metric_cost
=
0xFFFFFFFF
rpf_node
=
ip_dst
oif
=
None
mask
=
0
unicast_route
=
UnicastRouting
.
get_route
(
ip_dst
)
if
unicast_route
is
not
None
:
oif
=
unicast_route
.
get
(
"oif"
)
next_hop
=
unicast_route
[
"gateway"
]
multipaths
=
unicast_route
[
"multipath"
]
# prefsrc = unicast_route.get("prefsrc")
# rpf_node = ip_dst if (next_hop is None and prefsrc is not None) else next_hop
rpf_node
=
next_hop
if
next_hop
is
not
None
else
ip_dst
highest_ip
=
ipaddress
.
ip_address
(
"0.0.0.0"
)
for
m
in
multipaths
:
if
m
[
"gateway"
]
is
None
:
oif
=
m
.
get
(
'oif'
)
rpf_node
=
ip_dst
break
elif
ipaddress
.
ip_address
(
m
[
"gateway"
])
>
highest_ip
:
highest_ip
=
ipaddress
.
ip_address
(
m
[
"gateway"
])
oif
=
m
.
get
(
'oif'
)
rpf_node
=
m
[
"gateway"
]
# get output interface IP, used to send data to IP ip_dst
# (root interface IP to ip_dst)
@
staticmethod
def
check_rpf
(
ip_dst
):
# obter index da interface
# rpf_interface_index = ipr.get_routes(family=socket.AF_INET, dst=ip)[0]['attrs'][2][1]
# interface_name = if_indextoname(rpf_interface_index)
# return interface_name
metric_administrative_distance
=
unicast_route
[
"proto"
]
metric_cost
=
unicast_route
[
"priority"
]
metric_cost
=
metric_cost
if
metric_cost
is
not
None
else
0
mask
=
unicast_route
[
"dst_len"
]
# obter ip da interface de saida
rpf_i
nterface_source
=
UnicastRouting
.
ipr
.
get_routes
(
family
=
socket
.
AF_INET
,
dst
=
ip_dst
)[
0
][
'attrs'
][
3
][
1
]
return
rpf_interface_source
interface_name
=
None
if
oif
is
None
else
if_indextoname
(
int
(
oif
))
rpf_i
f
=
Main
.
kernel
.
vif_name_to_index_dic
.
get
(
interface_name
)
return
(
metric_administrative_distance
,
metric_cost
,
rpf_node
,
rpf_if
,
mask
)
@
staticmethod
def
unicast_changes
(
ipdb
,
msg
,
action
):
print
(
"unicast change?"
)
print
(
action
)
UnicastRouting
.
lock
.
acquire
()
UnicastRouting
.
ipdb
=
ipdb
if
action
==
"RTM_NEWROUTE"
or
action
==
"RTM_DELROUTE"
:
print
(
ipdb
.
routes
)
mask_len
=
msg
[
"dst_len"
]
...
...
@@ -100,12 +128,9 @@ class UnicastRouting(object):
print
(
network_address
+
"/"
+
str
(
mask_len
))
subnet
=
ipaddress
.
ip_network
(
network_address
+
"/"
+
str
(
mask_len
))
print
(
str
(
subnet
))
UnicastRouting
.
lock
.
release
()
Main
.
kernel
.
notify_unicast_changes
(
subnet
)
elif
action
==
"RTM_NEWADDR"
or
action
==
"RTM_DELADDR"
:
UnicastRouting
.
lock
.
release
()
# TODO ALTERACOES NA INTERFACE
'''
elif action == "RTM_NEWADDR" or action == "RTM_DELADDR":
print(action)
print(msg)
interface_name = None
...
...
@@ -115,15 +140,37 @@ class UnicastRouting(object):
if key == "IFA_LABEL":
interface_name = value
break
Main.kernel.notify_interface_change(interface_name)
'''
else
:
UnicastRouting.lock.release()
try:
Main.kernel.notify_interface_changes(interface_name)
except:
import traceback
traceback.print_exc()
pass
bnet = ipaddress.ip_network("0.0.0.0/0")
Main.kernel.notify_unicast_changes(subnet)
elif action == "RTM_NEWLINK" or action == "RTM_DELLINK":
attrs = msg["attrs"]
if_name = None
operation = None
for (key, value) in attrs:
print((key, value))
if key == "IFLA_IFNAME":
if_name = value
elif key == "IFLA_OPERSTATE":
operation = value
if if_name is not None and operation is not None:
break
if if_name is not None:
print(if_name + ": " + operation)
UnicastRouting.lock.release()
if operation == 'DOWN':
Main.kernel.remove_interface(if_name, igmp=True, pim=True)
subnet = ipaddress.ip_network("0.0.0.0/0")
Main.kernel.notify_unicast_changes(subnet)
'''
def
stop
(
self
):
if
UnicastRouting
.
ipr
:
UnicastRouting
.
ipr
.
close
()
if
UnicastRouting
.
ipdb
:
UnicastRouting
.
ipdb
=
None
if
self
.
_ipdb
:
...
...
tree/KernelEntry.py
View file @
8f254e2d
...
...
@@ -19,26 +19,12 @@ class KernelEntry:
self
.
source_ip
=
source_ip
self
.
group_ip
=
group_ip
# CHECK UNICAST ROUTING INFORMATION###################################################
# CHOSE RPC INTERFACE
# GET RPC TO SOURCE
unicast_route
=
UnicastRouting
.
get_route
(
source_ip
)
next_hop
=
unicast_route
[
"gateway"
]
multipaths
=
unicast_route
[
"multipath"
]
self
.
rpf_node
=
next_hop
if
next_hop
is
not
None
else
source_ip
import
ipaddress
highest_ip
=
ipaddress
.
ip_address
(
"0.0.0.0"
)
for
m
in
multipaths
:
if
m
[
"gateway"
]
is
None
:
self
.
rpf_node
=
source_ip
break
elif
ipaddress
.
ip_address
(
m
[
"gateway"
])
>
highest_ip
:
highest_ip
=
ipaddress
.
ip_address
(
m
[
"gateway"
])
self
.
rpf_node
=
m
[
"gateway"
]
print
(
"RPF_NODE:"
,
UnicastRouting
.
get_route
(
source_ip
))
print
(
self
.
rpf_node
==
source_ip
)
# OBTAIN UNICAST ROUTING INFORMATION###################################################
(
metric_administrative_distance
,
metric_cost
,
rpf_node
,
root_if
,
mask
)
=
\
UnicastRouting
.
get_unicast_info
(
source_ip
)
if
root_if
is
None
:
raise
Exception
self
.
rpf_node
=
rpf_node
# (S,G) starts IG state
self
.
_was_olist_null
=
False
...
...
@@ -49,7 +35,7 @@ class KernelEntry:
self
.
CHANGE_STATE_LOCK
=
RLock
()
# decide inbound interface based on rpf check
self
.
inbound_interface_index
=
Main
.
kernel
.
vif_dic
[
self
.
check_rpf
()]
self
.
inbound_interface_index
=
root_if
self
.
interface_state
=
{}
# type: Dict[int, TreeInterface]
with
self
.
CHANGE_STATE_LOCK
:
...
...
@@ -69,9 +55,6 @@ class KernelEntry:
self
.
timestamp_of_last_state_refresh_message_received
=
0
print
(
'Tree created'
)
#self._lock = threading.RLock()
def
get_inbound_interface_index
(
self
):
return
self
.
inbound_interface_index
...
...
@@ -81,10 +64,6 @@ class KernelEntry:
outbound_indexes
[
index
]
=
state
.
is_forwarding
()
return
outbound_indexes
def
check_rpf
(
self
):
return
UnicastRouting
.
check_rpf
(
self
.
source_ip
)
################################################
# Receive (S,G) data packets or control packets
################################################
...
...
@@ -168,41 +147,10 @@ class KernelEntry:
def
network_update
(
self
):
# TODO TALVEZ OUTRO LOCK PARA BLOQUEAR ENTRADA DE PACOTES
with
self
.
CHANGE_STATE_LOCK
:
'''
next_hop = UnicastRouting.get_route(self.source_ip)["gateway"]
multipaths = UnicastRouting.get_route(self.source_ip)["multipath"]
rpf_node = next_hop
print("MUL", multipaths)
# self.rpf_node = multipaths[0]["gateway"]
for m in multipaths:
if m["gateway"] is None:
rpf_node = self.source_ip
break
else:
rpf_node = m["gateway"]
'''
unicast_route
=
UnicastRouting
.
get_route
(
self
.
source_ip
)
next_hop
=
unicast_route
[
"gateway"
]
multipaths
=
unicast_route
[
"multipath"
]
rpf_node
=
next_hop
if
next_hop
is
not
None
else
self
.
source_ip
import
ipaddress
highest_ip
=
ipaddress
.
ip_address
(
"0.0.0.0"
)
for
m
in
multipaths
:
if
m
[
"gateway"
]
is
None
:
rpf_node
=
self
.
source_ip
break
elif
ipaddress
.
ip_address
(
m
[
"gateway"
])
>
highest_ip
:
highest_ip
=
ipaddress
.
ip_address
(
m
[
"gateway"
])
rpf_node
=
m
[
"gateway"
]
print
(
"RPF_NODE:"
,
UnicastRouting
.
get_route
(
self
.
source_ip
))
print
(
self
.
rpf_node
==
self
.
source_ip
)
(
metric_administrative_distance
,
metric_cost
,
rpf_node
,
new_inbound_interface_index
,
_
)
=
\
UnicastRouting
.
get_unicast_info
(
self
.
source_ip
)
new_inbound_interface_index
=
Main
.
kernel
.
vif_dic
.
get
(
self
.
check_rpf
(),
None
)
if
new_inbound_interface_index
is
None
:
self
.
delete
()
return
...
...
@@ -210,25 +158,31 @@ class KernelEntry:
self
.
rpf_node
=
rpf_node
# get old interfaces
old_upstream_interface
=
self
.
interface_state
[
self
.
inbound_interface_index
]
old_downstream_interface
=
self
.
interface_state
[
new_inbound_interface_index
]
old_upstream_interface
=
self
.
interface_state
.
get
(
self
.
inbound_interface_index
,
None
)
old_downstream_interface
=
self
.
interface_state
.
get
(
new_inbound_interface_index
,
None
)
# change type of interfaces
new_downstream_interface
=
TreeInterfaceDownstream
(
self
,
self
.
inbound_interface_index
)
self
.
interface_state
[
self
.
inbound_interface_index
]
=
new_downstream_interface
new_upstream_interface
=
TreeInterfaceUpstream
(
self
,
new_inbound_interface_index
)
self
.
interface_state
[
new_inbound_interface_index
]
=
new_upstream_interface
if
self
.
inbound_interface_index
is
not
None
:
new_downstream_interface
=
TreeInterfaceDownstream
(
self
,
self
.
inbound_interface_index
)
self
.
interface_state
[
self
.
inbound_interface_index
]
=
new_downstream_interface
new_upstream_interface
=
None
if
new_inbound_interface_index
is
not
None
:
new_upstream_interface
=
TreeInterfaceUpstream
(
self
,
new_inbound_interface_index
)
self
.
interface_state
[
new_inbound_interface_index
]
=
new_upstream_interface
self
.
inbound_interface_index
=
new_inbound_interface_index
# remove old interfaces
old_upstream_interface
.
delete
(
change_type_interface
=
True
)
old_downstream_interface
.
delete
(
change_type_interface
=
True
)
if
old_upstream_interface
is
not
None
:
old_upstream_interface
.
delete
(
change_type_interface
=
True
)
if
old_downstream_interface
is
not
None
:
old_downstream_interface
.
delete
(
change_type_interface
=
True
)
# atualizar tabela de encaminhamento multicast
#self._was_olist_null = False
self
.
change
()
self
.
evaluate_olist_change
()
new_upstream_interface
.
change_on_unicast_routing
(
interface_change
=
True
)
if
new_upstream_interface
is
not
None
:
new_upstream_interface
.
change_on_unicast_routing
(
interface_change
=
True
)
elif
self
.
rpf_node
!=
rpf_node
:
self
.
rpf_node
=
rpf_node
self
.
interface_state
[
self
.
inbound_interface_index
].
change_on_unicast_routing
()
...
...
@@ -294,7 +248,7 @@ class KernelEntry:
#check if removed interface is root interface
if
self
.
inbound_interface_index
==
index
:
self
.
delete
()
el
s
e
:
el
if
index
in
self
.
interface_stat
e
:
self
.
interface_state
.
pop
(
index
).
delete
()
self
.
change
()
self
.
evaluate_olist_change
()
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