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:
...
@@ -355,7 +355,7 @@ class Kernel:
if
ip_src
not
in
self
.
routing
:
if
ip_src
not
in
self
.
routing
:
self
.
routing
[
ip_src
]
=
{}
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
.
set_flood_multicast_route
(
ip_src
,
ip_dst
,
iif
)
self
.
routing
[
ip_src
][
ip_dst
]
=
kernel_entry
self
.
routing
[
ip_src
][
ip_dst
]
=
kernel_entry
return
kernel_entry
return
kernel_entry
...
...
UnicastRouting.py
View file @
8f254e2d
import
socket
import
socket
import
ipaddress
import
ipaddress
from
threading
import
RLock
from
pyroute2
import
IPDB
,
IPRoute
from
pyroute2
import
IPDB
,
IPRoute
import
Main
import
Main
from
utils
import
if_indextoname
def
get_route
(
ip_dst
:
str
):
def
get_route
(
ip_dst
:
str
):
...
@@ -17,10 +18,12 @@ def check_rpf(ip_dst):
...
@@ -17,10 +18,12 @@ def check_rpf(ip_dst):
return
UnicastRouting
.
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
):
class
UnicastRouting
(
object
):
ipr
=
None
ipdb
=
None
ipdb
=
None
lock
=
RLock
()
def
__init__
(
self
):
def
__init__
(
self
):
UnicastRouting
.
ipr
=
IPRoute
()
UnicastRouting
.
ipr
=
IPRoute
()
...
@@ -28,60 +31,85 @@ class UnicastRouting(object):
...
@@ -28,60 +31,85 @@ class UnicastRouting(object):
self
.
_ipdb
=
UnicastRouting
.
ipdb
self
.
_ipdb
=
UnicastRouting
.
ipdb
self
.
_ipdb
.
register_callback
(
UnicastRouting
.
unicast_changes
,
mode
=
"post"
)
self
.
_ipdb
.
register_callback
(
UnicastRouting
.
unicast_changes
,
mode
=
"post"
)
# get metrics (routing preference and cost) to IP ip_dst
@
staticmethod
@
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_bytes
=
socket
.
inet_aton
(
ip_dst
)
ip_int
=
int
.
from_bytes
(
ip_bytes
,
byteorder
=
'big'
)
ip_int
=
int
.
from_bytes
(
ip_bytes
,
byteorder
=
'big'
)
info
=
None
info
=
None
with
UnicastRouting
.
lock
:
ipdb
=
UnicastRouting
.
ipdb
# type:IPDB
ipdb
=
UnicastRouting
.
ipdb
# type:IPDB
for
mask_len
in
range
(
32
,
0
,
-
1
):
for
mask_len
in
range
(
32
,
0
,
-
1
):
ip_bytes
=
(
ip_int
&
(
0xFFFFFFFF
<<
(
32
-
mask_len
))).
to_bytes
(
4
,
"big"
)
ip_bytes
=
(
ip_int
&
(
0xFFFFFFFF
<<
(
32
-
mask_len
))).
to_bytes
(
4
,
"big"
)
ip_dst
=
socket
.
inet_ntoa
(
ip_bytes
)
+
"/"
+
str
(
mask_len
)
ip_dst
=
socket
.
inet_ntoa
(
ip_bytes
)
+
"/"
+
str
(
mask_len
)
print
(
ip_dst
)
print
(
ip_dst
)
if
ip_dst
in
ipdb
.
routes
:
if
ip_dst
in
ipdb
.
routes
:
print
(
info
)
if
ipdb
.
routes
[
ip_dst
][
'ipdb_scope'
]
!=
'gc'
:
info
=
ipdb
.
routes
[
ip_dst
]
info
=
ipdb
.
routes
[
ip_dst
]
break
break
else
:
else
:
continue
continue
if
not
info
:
if
not
info
:
print
(
"0.0.0.0/0"
)
print
(
"0.0.0.0/0"
)
if
"default"
in
ipdb
.
routes
:
info
=
ipdb
.
routes
[
"default"
]
info
=
ipdb
.
routes
[
"default"
]
print
(
info
)
print
(
info
)
return
info
return
info
# get metrics (routing preference and cost) to IP ip_dst
@
staticmethod
@
staticmethod
def
get_metric
(
ip_dst
:
str
):
def
get_unicast_info
(
ip_dst
):
unicast_routing_entry
=
UnicastRouting
.
get_route
(
ip_dst
)
metric_administrative_distance
=
0xFFFFFFFF
entry_protocol
=
unicast_routing_entry
[
"proto"
]
metric_cost
=
0xFFFFFFFF
entry_cost
=
unicast_routing_entry
[
"priority"
]
rpf_node
=
ip_dst
mask
=
unicast_routing_entry
[
"dst_len"
]
oif
=
None
if
entry_cost
is
None
:
mask
=
0
entry_cost
=
0
unicast_route
=
UnicastRouting
.
get_route
(
ip_dst
)
return
(
entry_protocol
,
entry_cost
,
mask
)
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
metric_administrative_distance
=
unicast_route
[
"proto"
]
# (root interface IP to ip_dst)
metric_cost
=
unicast_route
[
"priority"
]
@
staticmethod
metric_cost
=
metric_cost
if
metric_cost
is
not
None
else
0
def
check_rpf
(
ip_dst
):
mask
=
unicast_route
[
"dst_len"
]
# 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
# obter ip da interface de saida
interface_name
=
None
if
oif
is
None
else
if_indextoname
(
int
(
oif
))
rpf_i
nterface_source
=
UnicastRouting
.
ipr
.
get_routes
(
family
=
socket
.
AF_INET
,
dst
=
ip_dst
)[
0
][
'attrs'
][
3
][
1
]
rpf_i
f
=
Main
.
kernel
.
vif_name_to_index_dic
.
get
(
interface_name
)
return
rpf_interface_source
return
(
metric_administrative_distance
,
metric_cost
,
rpf_node
,
rpf_if
,
mask
)
@
staticmethod
@
staticmethod
def
unicast_changes
(
ipdb
,
msg
,
action
):
def
unicast_changes
(
ipdb
,
msg
,
action
):
print
(
"unicast change?"
)
print
(
"unicast change?"
)
print
(
action
)
print
(
action
)
UnicastRouting
.
lock
.
acquire
()
UnicastRouting
.
ipdb
=
ipdb
if
action
==
"RTM_NEWROUTE"
or
action
==
"RTM_DELROUTE"
:
if
action
==
"RTM_NEWROUTE"
or
action
==
"RTM_DELROUTE"
:
print
(
ipdb
.
routes
)
print
(
ipdb
.
routes
)
mask_len
=
msg
[
"dst_len"
]
mask_len
=
msg
[
"dst_len"
]
...
@@ -100,12 +128,9 @@ class UnicastRouting(object):
...
@@ -100,12 +128,9 @@ class UnicastRouting(object):
print
(
network_address
+
"/"
+
str
(
mask_len
))
print
(
network_address
+
"/"
+
str
(
mask_len
))
subnet
=
ipaddress
.
ip_network
(
network_address
+
"/"
+
str
(
mask_len
))
subnet
=
ipaddress
.
ip_network
(
network_address
+
"/"
+
str
(
mask_len
))
print
(
str
(
subnet
))
print
(
str
(
subnet
))
UnicastRouting
.
lock
.
release
()
Main
.
kernel
.
notify_unicast_changes
(
subnet
)
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(action)
print(msg)
print(msg)
interface_name = None
interface_name = None
...
@@ -115,15 +140,37 @@ class UnicastRouting(object):
...
@@ -115,15 +140,37 @@ class UnicastRouting(object):
if key == "IFA_LABEL":
if key == "IFA_LABEL":
interface_name = value
interface_name = value
break
break
Main.kernel.notify_interface_change(interface_name)
'''
else
:
UnicastRouting.lock.release()
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
):
def
stop
(
self
):
if
UnicastRouting
.
ipr
:
UnicastRouting
.
ipr
.
close
()
if
UnicastRouting
.
ipdb
:
if
UnicastRouting
.
ipdb
:
UnicastRouting
.
ipdb
=
None
UnicastRouting
.
ipdb
=
None
if
self
.
_ipdb
:
if
self
.
_ipdb
:
...
...
tree/KernelEntry.py
View file @
8f254e2d
...
@@ -19,26 +19,12 @@ class KernelEntry:
...
@@ -19,26 +19,12 @@ class KernelEntry:
self
.
source_ip
=
source_ip
self
.
source_ip
=
source_ip
self
.
group_ip
=
group_ip
self
.
group_ip
=
group_ip
# CHECK UNICAST ROUTING INFORMATION###################################################
# OBTAIN UNICAST ROUTING INFORMATION###################################################
# CHOSE RPC INTERFACE
(
metric_administrative_distance
,
metric_cost
,
rpf_node
,
root_if
,
mask
)
=
\
# GET RPC TO SOURCE
UnicastRouting
.
get_unicast_info
(
source_ip
)
unicast_route
=
UnicastRouting
.
get_route
(
source_ip
)
if
root_if
is
None
:
next_hop
=
unicast_route
[
"gateway"
]
raise
Exception
multipaths
=
unicast_route
[
"multipath"
]
self
.
rpf_node
=
rpf_node
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
)
# (S,G) starts IG state
# (S,G) starts IG state
self
.
_was_olist_null
=
False
self
.
_was_olist_null
=
False
...
@@ -49,7 +35,7 @@ class KernelEntry:
...
@@ -49,7 +35,7 @@ class KernelEntry:
self
.
CHANGE_STATE_LOCK
=
RLock
()
self
.
CHANGE_STATE_LOCK
=
RLock
()
# decide inbound interface based on rpf check
# 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]
self
.
interface_state
=
{}
# type: Dict[int, TreeInterface]
with
self
.
CHANGE_STATE_LOCK
:
with
self
.
CHANGE_STATE_LOCK
:
...
@@ -69,9 +55,6 @@ class KernelEntry:
...
@@ -69,9 +55,6 @@ class KernelEntry:
self
.
timestamp_of_last_state_refresh_message_received
=
0
self
.
timestamp_of_last_state_refresh_message_received
=
0
print
(
'Tree created'
)
print
(
'Tree created'
)
#self._lock = threading.RLock()
def
get_inbound_interface_index
(
self
):
def
get_inbound_interface_index
(
self
):
return
self
.
inbound_interface_index
return
self
.
inbound_interface_index
...
@@ -81,10 +64,6 @@ class KernelEntry:
...
@@ -81,10 +64,6 @@ class KernelEntry:
outbound_indexes
[
index
]
=
state
.
is_forwarding
()
outbound_indexes
[
index
]
=
state
.
is_forwarding
()
return
outbound_indexes
return
outbound_indexes
def
check_rpf
(
self
):
return
UnicastRouting
.
check_rpf
(
self
.
source_ip
)
################################################
################################################
# Receive (S,G) data packets or control packets
# Receive (S,G) data packets or control packets
################################################
################################################
...
@@ -168,41 +147,10 @@ class KernelEntry:
...
@@ -168,41 +147,10 @@ class KernelEntry:
def
network_update
(
self
):
def
network_update
(
self
):
# TODO TALVEZ OUTRO LOCK PARA BLOQUEAR ENTRADA DE PACOTES
# TODO TALVEZ OUTRO LOCK PARA BLOQUEAR ENTRADA DE PACOTES
with
self
.
CHANGE_STATE_LOCK
:
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
:
if
new_inbound_interface_index
is
None
:
self
.
delete
()
self
.
delete
()
return
return
...
@@ -210,25 +158,31 @@ class KernelEntry:
...
@@ -210,25 +158,31 @@ class KernelEntry:
self
.
rpf_node
=
rpf_node
self
.
rpf_node
=
rpf_node
# get old interfaces
# get old interfaces
old_upstream_interface
=
self
.
interface_state
[
self
.
inbound_interface_index
]
old_upstream_interface
=
self
.
interface_state
.
get
(
self
.
inbound_interface_index
,
None
)
old_downstream_interface
=
self
.
interface_state
[
new_inbound_interface_index
]
old_downstream_interface
=
self
.
interface_state
.
get
(
new_inbound_interface_index
,
None
)
# change type of interfaces
# change type of interfaces
new_downstream_interface
=
TreeInterfaceDownstream
(
self
,
self
.
inbound_interface_index
)
if
self
.
inbound_interface_index
is
not
None
:
self
.
interface_state
[
self
.
inbound_interface_index
]
=
new_downstream_interface
new_downstream_interface
=
TreeInterfaceDownstream
(
self
,
self
.
inbound_interface_index
)
new_upstream_interface
=
TreeInterfaceUpstream
(
self
,
new_inbound_interface_index
)
self
.
interface_state
[
self
.
inbound_interface_index
]
=
new_downstream_interface
self
.
interface_state
[
new_inbound_interface_index
]
=
new_upstream_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
self
.
inbound_interface_index
=
new_inbound_interface_index
# remove old interfaces
# remove old interfaces
old_upstream_interface
.
delete
(
change_type_interface
=
True
)
if
old_upstream_interface
is
not
None
:
old_downstream_interface
.
delete
(
change_type_interface
=
True
)
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
# atualizar tabela de encaminhamento multicast
#self._was_olist_null = False
#self._was_olist_null = False
self
.
change
()
self
.
change
()
self
.
evaluate_olist_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
:
elif
self
.
rpf_node
!=
rpf_node
:
self
.
rpf_node
=
rpf_node
self
.
rpf_node
=
rpf_node
self
.
interface_state
[
self
.
inbound_interface_index
].
change_on_unicast_routing
()
self
.
interface_state
[
self
.
inbound_interface_index
].
change_on_unicast_routing
()
...
@@ -294,7 +248,7 @@ class KernelEntry:
...
@@ -294,7 +248,7 @@ class KernelEntry:
#check if removed interface is root interface
#check if removed interface is root interface
if
self
.
inbound_interface_index
==
index
:
if
self
.
inbound_interface_index
==
index
:
self
.
delete
()
self
.
delete
()
el
s
e
:
el
if
index
in
self
.
interface_stat
e
:
self
.
interface_state
.
pop
(
index
).
delete
()
self
.
interface_state
.
pop
(
index
).
delete
()
self
.
change
()
self
.
change
()
self
.
evaluate_olist_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