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
77f16d47
Commit
77f16d47
authored
Oct 03, 2017
by
Pedro Oliveira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
assert
parent
2290b757
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
329 additions
and
153 deletions
+329
-153
Daemon/Daemon.py
Daemon/Daemon.py
+3
-2
Hello.py
Hello.py
+41
-81
InterfacePIM.py
InterfacePIM.py
+42
-1
Kernel.py
Kernel.py
+22
-3
Main.py
Main.py
+23
-8
Neighbor.py
Neighbor.py
+33
-11
Run.py
Run.py
+2
-2
UnicastRouting.py
UnicastRouting.py
+121
-0
tree/KernelEntry.py
tree/KernelEntry.py
+6
-30
tree/assert_.py
tree/assert_.py
+1
-1
tree/metric.py
tree/metric.py
+7
-4
tree/non_root_interface.py
tree/non_root_interface.py
+26
-8
tree/prune.py
tree/prune.py
+2
-2
No files found.
Daemon/Daemon.py
View file @
77f16d47
...
...
@@ -92,6 +92,7 @@ class Daemon:
# Try killing the Daemon process
try
:
while
1
:
#os.killpg(os.getpgid(pid), signal.SIGTERM)
os
.
kill
(
pid
,
signal
.
SIGTERM
)
time
.
sleep
(
0.1
)
except
OSError
as
err
:
...
...
@@ -100,7 +101,7 @@ class Daemon:
if
os
.
path
.
exists
(
self
.
pidfile
):
os
.
remove
(
self
.
pidfile
)
else
:
print
(
str
(
err
.
args
))
print
(
str
(
err
.
args
))
sys
.
exit
(
1
)
def
restart
(
self
):
...
...
@@ -125,5 +126,5 @@ class Daemon:
try
:
os
.
kill
(
pid
,
0
)
return
True
except
OSError
:
except
:
return
False
Hello.py
View file @
77f16d47
import
random
from
threading
import
Timer
from
Packet.Packet
import
Packet
from
Packet.ReceivedPacket
import
ReceivedPacket
from
Packet.PacketPimHello
import
PacketPimHello
from
Packet.PacketPimHeader
import
PacketPimHeader
from
Interface
import
Interface
import
Main
from
utils
import
HELLO_HOLD_TIME_TIMEOUT
from
Neighbor
import
Neighbor
...
...
@@ -17,39 +10,6 @@ class Hello:
def
__init__
(
self
):
Main
.
add_protocol
(
Hello
.
TYPE
,
self
)
self
.
thread
=
Timer
(
Hello
.
TRIGGERED_HELLO_DELAY
,
self
.
send_handle
)
self
.
thread
.
start
()
def
send_handle
(
self
):
for
interface
in
list
(
Main
.
interfaces
.
values
()):
self
.
packet_send_handle
(
interface
)
# reschedule timer
self
.
thread
=
Timer
(
Hello
.
TRIGGERED_HELLO_DELAY
,
self
.
send_handle
)
self
.
thread
.
start
()
def
packet_send_handle
(
self
,
interface
:
Interface
):
pim_payload
=
PacketPimHello
()
pim_payload
.
add_option
(
1
,
3.5
*
Hello
.
TRIGGERED_HELLO_DELAY
)
pim_payload
.
add_option
(
20
,
interface
.
generation_id
)
ph
=
PacketPimHeader
(
pim_payload
)
packet
=
Packet
(
payload
=
ph
)
interface
.
send
(
packet
.
bytes
())
def
force_send
(
self
,
interface
:
Interface
):
# When PIM is enabled on an interface or when a router first starts, the Hello Timer (HT)
# MUST be set to random value between 0 and Triggered_Hello_Delay
hello_timer
=
random
.
uniform
(
0
,
Hello
.
TRIGGERED_HELLO_DELAY
)
Timer
(
hello_timer
,
self
.
packet_send_handle
,
args
=
[
interface
]).
start
()
def
force_send_remove
(
self
,
interface
:
Interface
):
pim_payload
=
PacketPimHello
()
pim_payload
.
add_option
(
1
,
HELLO_HOLD_TIME_TIMEOUT
)
pim_payload
.
add_option
(
20
,
interface
.
generation_id
)
ph
=
PacketPimHeader
(
pim_payload
)
packet
=
Packet
(
payload
=
ph
)
interface
.
send
(
packet
.
bytes
())
# receive handler
def
receive_handle
(
self
,
packet
:
ReceivedPacket
):
interface
=
packet
.
interface
...
...
@@ -71,44 +31,44 @@ class Hello:
interface
.
neighbors
[
ip
]
=
Neighbor
(
interface
,
ip
,
generation_id
,
hello_hold_time
)
return
with
neighbor
.
neighbor_lock
:
# Already know Neighbor
print
(
"neighbor conhecido"
)
neighbor
.
heartbeat
()
if
neighbor
.
hello_hold_time
!=
hello_hold_time
:
print
(
"keep alive period diferente"
)
neighbor
.
set_hello_hold_time
(
hello_hold_time
)
if
neighbor
.
generation_id
!=
generation_id
:
print
(
"neighbor reiniciado"
)
neighbor
.
set_generation_id
(
generation_id
)
'''
with interface.neighbors_lock.genWlock():
#if interface.get_neighbor(ip) is None:
if ip in interface.neighbors:
# Unknown Neighbor
if (1 in options) and (20 in options):
try:
#Main.add_neighbor(packet.interface, ip, options[20], options[1])
print("non neighbor and options inside")
except Exception:
# Received Neighbor with Timeout
print("non neighbor and options inside but neighbor timedout")
pass
return
print("non neighbor and required options not inside")
else:
# Already know Neighbor
print("neighbor conhecido")
neighbor = Main.get_neighbor(ip)
neighbor.heartbeat()
if 1 in options and neighbor.hello_hold_time != options[1]:
print("keep alive period diferente")
neighbor.set_hello_hold_time(options[1])
if 20 in options and neighbor.generation_id != options[20]:
print("neighbor reiniciado")
neighbor.remove()
Main.add_neighbor(packet.interface, ip, options[20], options[1])
'''
neighbor
.
receive_hello
(
generation_id
,
hello_hold_time
)
"""
with neighbor.neighbor_lock:
# Already know Neighbor
print("neighbor conhecido")
neighbor.heartbeat(
)
if neighbor.hello_hold_time != hello_hold_time:
print("keep alive period diferente")
neighbor.set_hello_hold_time(hello_hold_time
)
if neighbor.generation_id != generation_id:
print("neighbor reiniciado")
neighbor.set_generation_id(generation_id)
with interface.neighbors_lock.genWlock():
#if interface.get_neighbor(ip) is None:
if ip in interface.neighbors:
# Unknown Neighbor
if (1 in options) and (20 in options):
try:
#Main.add_neighbor(packet.interface, ip, options[20], options[1])
print("non neighbor and options inside")
except Exception:
# Received Neighbor with Timeout
print("non neighbor and options inside but neighbor timedout")
pass
return
print("non neighbor and required options not inside")
else:
# Already know Neighbor
print("neighbor conhecido")
neighbor = Main.get_neighbor(ip)
neighbor.heartbeat()
if 1 in options and neighbor.hello_hold_time != options[1]:
print("keep alive period diferente")
neighbor.set_hello_hold_time(options[1])
if 20 in options and neighbor.generation_id != options[20]:
print("neighbor reiniciado")
neighbor.remove()
Main.add_neighbor(packet.interface, ip, options[20], options[1])
"""
\ No newline at end of file
InterfacePIM.py
View file @
77f16d47
...
...
@@ -5,7 +5,12 @@ from Packet.ReceivedPacket import ReceivedPacket
import
Main
import
traceback
from
RWLock.RWLock
import
RWLockWrite
from
Packet.PacketPimHello
import
PacketPimHello
from
Packet.PacketPimHeader
import
PacketPimHeader
from
Packet.Packet
import
Packet
from
Hello
import
Hello
from
utils
import
HELLO_HOLD_TIME_TIMEOUT
from
threading
import
Timer
class
InterfacePim
(
Interface
):
MCAST_GRP
=
'224.0.0.13'
...
...
@@ -20,6 +25,12 @@ class InterfacePim(Interface):
self
.
neighbors
=
{}
self
.
neighbors_lock
=
RWLockWrite
()
# When PIM is enabled on an interface or when a router first starts, the Hello Timer (HT)
# MUST be set to random value between 0 and Triggered_Hello_Delay
hello_timer_time
=
random
.
uniform
(
0
,
Hello
.
TRIGGERED_HELLO_DELAY
)
self
.
hello_timer
=
Timer
(
hello_timer_time
,
self
.
send_hello
)
self
.
hello_timer
.
start
()
# run receive method in background
receive_thread
=
threading
.
Thread
(
target
=
self
.
receive
)
receive_thread
.
daemon
=
True
...
...
@@ -49,9 +60,35 @@ class InterfacePim(Interface):
def
send
(
self
,
data
:
bytes
,
group_ip
:
str
=
MCAST_GRP
):
super
().
send
(
data
=
data
,
group_ip
=
group_ip
)
def
send_hello
(
self
):
self
.
hello_timer
.
cancel
()
pim_payload
=
PacketPimHello
()
pim_payload
.
add_option
(
1
,
3.5
*
Hello
.
TRIGGERED_HELLO_DELAY
)
pim_payload
.
add_option
(
20
,
self
.
generation_id
)
ph
=
PacketPimHeader
(
pim_payload
)
packet
=
Packet
(
payload
=
ph
)
self
.
send
(
packet
.
bytes
())
# reschedule hello_timer
self
.
hello_timer
=
Timer
(
Hello
.
TRIGGERED_HELLO_DELAY
,
self
.
send_hello
)
self
.
hello_timer
.
start
()
def
remove
(
self
):
self
.
hello_timer
.
cancel
()
self
.
hello_timer
=
None
# send pim_hello timeout message
pim_payload
=
PacketPimHello
()
pim_payload
.
add_option
(
1
,
HELLO_HOLD_TIME_TIMEOUT
)
pim_payload
.
add_option
(
20
,
self
.
generation_id
)
ph
=
PacketPimHeader
(
pim_payload
)
packet
=
Packet
(
payload
=
ph
)
self
.
send
(
packet
.
bytes
())
super
().
remove
()
def
add_neighbor
(
self
,
ip
,
random_number
,
hello_hold_time
):
with
self
.
neighbors_lock
.
genWlock
():
if
ip
not
in
self
.
neighbors
:
...
...
@@ -69,3 +106,7 @@ class InterfacePim(Interface):
def
get_neighbor
(
self
,
ip
):
with
self
.
neighbors_lock
.
genRlock
():
return
self
.
neighbors
[
ip
]
def
remove_neighbor
(
self
,
ip
):
with
self
.
neighbors_lock
.
genWlock
():
del
self
.
neighbors
[
ip
]
Kernel.py
View file @
77f16d47
...
...
@@ -133,6 +133,7 @@ class Kernel:
# MRT PIM
s
.
setsockopt
(
socket
.
IPPROTO_IP
,
Kernel
.
MRT_PIM
,
0
)
s
.
setsockopt
(
socket
.
IPPROTO_IP
,
Kernel
.
MRT_ASSERT
,
1
)
self
.
socket
=
s
self
.
rwlock
=
RWLockWrite
()
...
...
@@ -275,6 +276,7 @@ class Kernel:
msg
=
self
.
socket
.
recv
(
5000
)
#print(len(msg))
(
_
,
_
,
im_msgtype
,
im_mbz
,
im_vif
,
_
,
im_src
,
im_dst
)
=
struct
.
unpack
(
"II B B B B 4s 4s"
,
msg
[:
20
])
print
((
im_msgtype
,
im_mbz
,
socket
.
inet_ntoa
(
im_src
),
socket
.
inet_ntoa
(
im_dst
)))
if
im_mbz
!=
0
:
continue
...
...
@@ -284,7 +286,7 @@ class Kernel:
print
(
im_vif
)
print
(
socket
.
inet_ntoa
(
im_src
))
print
(
socket
.
inet_ntoa
(
im_dst
))
print
(
struct
.
unpack
(
"II B B B B 4s 4s"
,
msg
[:
20
]
))
#print((im_msgtype, im_mbz, socket.inet_ntoa(im_src), socket.inet_ntoa(im_dst)
))
ip_src
=
socket
.
inet_ntoa
(
im_src
)
ip_dst
=
socket
.
inet_ntoa
(
im_dst
)
...
...
@@ -293,6 +295,7 @@ class Kernel:
print
(
"IGMP NO CACHE"
)
self
.
igmpmsg_nocache_handler
(
ip_src
,
ip_dst
,
im_vif
)
elif
im_msgtype
==
Kernel
.
IGMPMSG_WRONGVIF
:
print
(
"WRONG VIF HANDLER"
)
self
.
igmpmsg_wrongvif_handler
(
ip_src
,
ip_dst
,
im_vif
)
else
:
raise
Exception
...
...
@@ -333,7 +336,8 @@ class Kernel:
# receive multicast (S,G) packet in a outbound_interface
def
igmpmsg_wrongvif_handler
(
self
,
ip_src
,
ip_dst
,
iif
):
#kernel_entry = self.routing[(ip_src, ip_dst)]
self
.
get_routing_entry
((
ip_src
,
ip_dst
),
create_if_not_existent
=
True
).
recv_data_msg
(
iif
)
source_group_pair
=
(
ip_src
,
ip_dst
)
self
.
get_routing_entry
(
source_group_pair
,
create_if_not_existent
=
True
).
recv_data_msg
(
iif
)
#kernel_entry.recv_data_msg(iif)
"""
...
...
@@ -357,4 +361,19 @@ class Kernel:
#self.set_multicast_route(kernel_entry)
return
kernel_entry
else
:
return
None
\ No newline at end of file
return
None
def
neighbor_removed
(
self
,
interface_name
,
neighbor_ip
):
# todo
interface_index
=
self
.
vif_name_to_index_dic
[
interface_name
]
with
self
.
rwlock
.
genRlock
():
for
routing_entry
in
self
.
routing
.
values
():
routing_entry
.
nbr_died
(
interface_index
,
neighbor_ip
)
Main.py
View file @
77f16d47
...
...
@@ -6,6 +6,7 @@ from InterfacePIM import InterfacePim
from
InterfaceIGMP
import
InterfaceIGMP
from
Kernel
import
Kernel
from
threading
import
Lock
import
UnicastRouting
interfaces
=
{}
# interfaces with multicast routing enabled
igmp_interfaces
=
{}
# igmp interfaces
...
...
@@ -13,15 +14,16 @@ protocols = {}
kernel
=
None
igmp
=
None
def
add_interface
(
interface_name
,
pim
=
False
,
igmp
=
False
):
if
pim
is
True
and
interface_name
not
in
interfaces
:
interface
=
InterfacePim
(
interface_name
)
interfaces
[
interface_name
]
=
interface
protocols
[
0
].
force_send
(
interface
)
if
igmp
is
True
and
interface_name
not
in
igmp_interfaces
:
interface
=
InterfaceIGMP
(
interface_name
)
igmp_interfaces
[
interface_name
]
=
interface
def
remove_interface
(
interface_name
,
pim
=
False
,
igmp
=
False
):
if
pim
is
True
and
((
interface_name
in
interfaces
)
or
interface_name
==
"*"
):
if
interface_name
==
"*"
:
...
...
@@ -29,10 +31,12 @@ def remove_interface(interface_name, pim=False, igmp=False):
else
:
interface_name_list
=
[
interface_name
]
for
if_name
in
interface_name_list
:
protocols
[
0
].
force_send_remove
(
interfaces
[
if_name
])
interfaces
[
if_name
].
remove
()
del
interfaces
[
if_name
]
interface_obj
=
interfaces
.
pop
(
if_name
)
interface_obj
.
remove
()
#interfaces[if_name].remove()
#del interfaces[if_name]
print
(
"removido interface"
)
print
(
interfaces
)
if
igmp
is
True
and
((
interface_name
in
igmp_interfaces
)
or
interface_name
==
"*"
):
if
interface_name
==
"*"
:
...
...
@@ -43,6 +47,7 @@ def remove_interface(interface_name, pim=False, igmp=False):
igmp_interfaces
[
if_name
].
remove
()
del
igmp_interfaces
[
if_name
]
print
(
"removido interface"
)
print
(
igmp_interfaces
)
"""
...
...
@@ -126,7 +131,7 @@ def list_enabled_interfaces():
t
=
PrettyTable
([
'Interface'
,
'IP'
,
'PIM/I
MG
P Enabled'
,
'IGMP State'
])
t
=
PrettyTable
([
'Interface'
,
'IP'
,
'PIM/I
GM
P Enabled'
,
'IGMP State'
])
for
interface
in
netifaces
.
interfaces
():
try
:
# TODO: fix same interface with multiple ips
...
...
@@ -145,6 +150,11 @@ def list_enabled_interfaces():
return
str
(
t
)
def
list_state
():
state_text
=
"IGMP State:
\
n
"
+
list_igmp_state
()
+
"
\
n
\
n
\
n
\
n
"
+
"Multicast Routing State:
\
n
"
+
list_routing_state
()
return
state_text
def
list_igmp_state
():
t
=
PrettyTable
([
'Interface'
,
'RouterState'
,
'Group Adress'
,
'GroupState'
])
for
(
interface_name
,
interface_obj
)
in
list
(
igmp_interfaces
.
items
()):
...
...
@@ -158,6 +168,7 @@ def list_igmp_state():
t
.
add_row
([
interface_name
,
state_txt
,
group_addr
,
group_state_txt
])
return
str
(
t
)
def
list_routing_state
():
routing_entries
=
kernel
.
routing
.
values
()
vif_indexes
=
kernel
.
vif_index_to_name_dic
.
keys
()
...
...
@@ -182,7 +193,13 @@ def list_routing_state():
return
str
(
t
)
def
main
(
interfaces_to_add
=
[]):
def
stop
():
remove_interface
(
"*"
,
pim
=
True
,
igmp
=
True
)
kernel
.
exit
()
UnicastRouting
.
stop
()
def
main
():
from
Hello
import
Hello
from
IGMP
import
IGMP
from
Assert
import
Assert
...
...
@@ -196,5 +213,3 @@ def main(interfaces_to_add=[]):
global
igmp
igmp
=
IGMP
()
for
interface
in
interfaces_to_add
:
add_interface
(
interface
)
Neighbor.py
View file @
77f16d47
from
threading
import
Timer
import
time
from
utils
import
HELLO_HOLD_TIME_NO_TIMEOUT
,
HELLO_HOLD_TIME_TIMEOUT
from
Interface
import
Interface
import
Main
from
utils
import
HELLO_HOLD_TIME_NO_TIMEOUT
,
HELLO_HOLD_TIME_TIMEOUT
,
TYPE_CHECKING
from
threading
import
Lock
import
Main
if
TYPE_CHECKING
:
from
InterfacePIM
import
InterfacePim
class
Neighbor
:
def
__init__
(
self
,
contact_interface
:
Interface
,
ip
,
generation_id
:
int
,
hello_hold_time
:
int
):
def
__init__
(
self
,
contact_interface
:
"InterfacePim"
,
ip
,
generation_id
:
int
,
hello_hold_time
:
int
):
if
hello_hold_time
==
HELLO_HOLD_TIME_TIMEOUT
:
raise
Exception
self
.
contact_interface
=
contact_interface
...
...
@@ -19,8 +20,9 @@ class Neighbor:
self
.
time_of_last_update
=
time
.
time
()
self
.
neighbor_lock
=
Lock
()
# todo
Main
.
protocols
[
0
].
force_send
(
contact_interface
)
# send hello to new neighbor
self
.
contact_interface
.
send_hello
()
def
set_hello_hold_time
(
self
,
hello_hold_time
:
int
):
self
.
hello_hold_time
=
hello_hold_time
...
...
@@ -36,13 +38,13 @@ class Neighbor:
self
.
neighbor_liveness_timer
=
None
def
set_generation_id
(
self
,
generation_id
):
if
self
.
generation_id
is
None
:
# neighbor restarted
if
self
.
generation_id
!=
generation_id
:
self
.
generation_id
=
generation_id
elif
self
.
generation_id
!=
generation_id
:
self
.
generation_id
=
generation_id
self
.
set_hello_hold_time
(
self
.
hello_hold_time
)
self
.
time_of_last_update
=
time
.
time
()
self
.
contact_interface
.
send_hello
()
self
.
reset
()
"""
def heartbeat(self):
if (self.hello_hold_time != HELLO_HOLD_TIME_TIMEOUT) and
\
(self.hello_hold_time != HELLO_HOLD_TIME_NO_TIMEOUT):
...
...
@@ -52,10 +54,30 @@ class Neighbor:
self.neighbor_liveness_timer = Timer(self.hello_hold_time, self.remove)
self.neighbor_liveness_timer.start()
self.time_of_last_update = time.time()
"""
def
remove
(
self
):
print
(
'HELLO TIMER EXPIRED... remove neighbor'
)
if
self
.
neighbor_liveness_timer
is
not
None
:
self
.
neighbor_liveness_timer
.
cancel
()
#Main.remove_neighbor(self.ip)
interface_name
=
self
.
contact_interface
.
interface_name
neighbor_ip
=
self
.
ip
Main
.
kernel
.
neighbor_removed
(
interface_name
,
neighbor_ip
)
del
self
.
contact_interface
.
neighbors
[
self
.
ip
]
def
reset
(
self
):
interface_name
=
self
.
contact_interface
.
interface_name
neighbor_ip
=
self
.
ip
Main
.
kernel
.
neighbor_removed
(
interface_name
,
neighbor_ip
)
# todo new neighbor
def
receive_hello
(
self
,
generation_id
,
hello_hold_time
):
if
hello_hold_time
==
HELLO_HOLD_TIME_TIMEOUT
:
self
.
set_hello_hold_time
(
hello_hold_time
)
else
:
self
.
time_of_last_update
=
time
.
time
()
self
.
set_generation_id
(
generation_id
)
self
.
set_hello_hold_time
(
hello_hold_time
)
Run.py
View file @
77f16d47
...
...
@@ -62,7 +62,7 @@ class MyDaemon(Daemon):
elif
args
.
list_neighbors
:
connection
.
sendall
(
pickle
.
dumps
(
Main
.
list_neighbors
()))
elif
args
.
list_state
:
connection
.
sendall
(
pickle
.
dumps
(
Main
.
list_
igmp_state
()
+
"
\
n
\
n
\
n
\
n
\
n
\
n
"
+
Main
.
list_routing_
state
()))
connection
.
sendall
(
pickle
.
dumps
(
Main
.
list_state
()))
elif
args
.
add_interface
:
Main
.
add_interface
(
args
.
add_interface
[
0
],
pim
=
True
)
connection
.
shutdown
(
socket
.
SHUT_RDWR
)
...
...
@@ -76,7 +76,7 @@ class MyDaemon(Daemon):
Main
.
remove_interface
(
args
.
remove_interface_igmp
[
0
],
igmp
=
True
)
connection
.
shutdown
(
socket
.
SHUT_RDWR
)
elif
args
.
stop
:
Main
.
remove_interface
(
"*"
,
pim
=
True
,
igmp
=
True
)
Main
.
stop
(
)
connection
.
shutdown
(
socket
.
SHUT_RDWR
)
except
Exception
:
connection
.
shutdown
(
socket
.
SHUT_RDWR
)
...
...
UnicastRouting.py
0 → 100644
View file @
77f16d47
from
pyroute2
import
IPDB
,
IPRoute
import
socket
#ipdb = IPDB()
ipr
=
IPRoute
()
def
get_route
(
ip_dst
:
str
):
with
IPDB
()
as
ipdb
:
ip_bytes
=
socket
.
inet_aton
(
ip_dst
)
ip_int
=
int
.
from_bytes
(
ip_bytes
,
byteorder
=
'big'
)
info
=
None
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
)
try
:
info
=
ipdb
.
routes
[
ip_dst
]
break
except
:
continue
if
not
info
:
print
(
"0.0.0.0/0"
)
info
=
ipdb
.
routes
[
"default"
]
print
(
info
)
return
info
# get metrics (routing preference and cost) to IP ip_dst
def
get_metric
(
ip_dst
:
str
):
unicast_routing_entry
=
get_route
(
ip_dst
)
entry_protocol
=
unicast_routing_entry
[
"proto"
]
entry_cost
=
unicast_routing_entry
[
"priority"
]
return
(
entry_protocol
,
entry_cost
)
"""
def get_rpf(ip_dst: str):
unicast_routing_entry = get_route(ip_dst)
#interface_oif = unicast_routing_entry['oif']
if not unicast_routing_entry['multipath']:
interface_oif = unicast_routing_entry['oif']
else:
multiple_entries = unicast_routing_entry['multipath']
print(multiple_entries)
(entry0, _) = multiple_entries
print(entry0)
interface_oif = entry0['oif']
print("ola")
print(ipdb.interfaces[interface_oif]['ipaddr'])
for i in range(len(ipdb.interfaces[interface_oif]['ipaddr'])):
print("ola2")
interface = ipdb.interfaces[interface_oif]['ipaddr'][i]
print(interface)
if interface['family'] == socket.AF_INET:
return interface['address']
return None
"""
# get output interface IP, used to send data to IP ip_dst
# (root interface IP to ip_dst)
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
# obter ip da interface de saida
rpf_interface_source
=
ipr
.
get_routes
(
family
=
socket
.
AF_INET
,
dst
=
ip_dst
)[
0
][
'attrs'
][
3
][
1
]
return
rpf_interface_source
"""
def get_metric(ip_dst: str):
ip_bytes = socket.inet_aton(ip_dst)
ip_int = int.from_bytes(ip_bytes, byteorder='big')
info = None
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)
try:
info = ipdb.routes[ip_dst]
break
except:
continue
if not info:
print("0.0.0.0/0")
info = ipdb.routes["default"]
print(info)
print("metric=", info["priority"])
print("proto=", info["proto"])
#print(info.keys())
#if info["gateway"]:
# print("next_hop=", info["gateway"])
#elif info["prefsrc"]:
# print("next_hop=", info["prefsrc"])
return (info["proto"], info["priority"])
def check_rpf(ip_dst: str):
from pyroute2 import IPRoute
# from utils import if_indextoname
ipr = IPRoute()
# 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
rpf_interface_source = ipr.get_routes(family=socket.AF_INET, dst=ip_dst)[0]['attrs'][3][1]
return rpf_interface_source
"""
def
stop
():
ipr
.
close
()
#ip = input("ip=")
#get_metric(ip)
\ No newline at end of file
tree/KernelEntry.py
View file @
77f16d47
import
Main
import
socket
import
netifaces
from
tree.root_interface
import
SFRMRootInterface
from
tree.non_root_interface
import
SFRMNonRootInterface
from
threading
import
Timer
,
Lock
import
UnicastRouting
class
KernelEntry
:
TREE_TIMEOUT
=
180
...
...
@@ -64,18 +64,7 @@ class KernelEntry:
return
outbound_indexes
def
check_rpf
(
self
):
from
pyroute2
import
IPRoute
# from utils import if_indextoname
ipr
=
IPRoute
()
# 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
rpf_interface_source
=
ipr
.
get_routes
(
family
=
socket
.
AF_INET
,
dst
=
self
.
source_ip
)[
0
][
'attrs'
][
3
][
1
]
return
rpf_interface_source
return
UnicastRouting
.
check_rpf
(
self
.
source_ip
)
def
recv_data_msg
(
self
,
index
):
if
self
.
is_originater
():
...
...
@@ -130,19 +119,16 @@ class KernelEntry:
# todo
return
def
nbr_died
(
self
,
index
,
neighbor_ip
):
# todo
self
.
interface_state
[
index
].
nbr_died
(
neighbor_ip
)
def
is_in_group
(
self
):
# todo
#if self.get_has_members():
#if True:
# return True
"""
for index in Main.kernel.vif_index_to_name_dic.keys():
if self.interface_state[index].is_forwarding():
return True
return False
"""
for
interface
in
self
.
interface_state
.
values
():
if
interface
.
is_forwarding
():
return
True
...
...
@@ -176,16 +162,6 @@ class KernelEntry:
def
get_group
(
self
):
return
self
.
group_ip
def
get_has_members
(
self
):
#return self._has_members
return
True
def
set_has_members
(
self
,
value
):
assert
isinstance
(
value
,
bool
)
self
.
_has_members
=
value
self
.
evaluate_ingroup
()
def
change
(
self
):
# todo: changes on unicast routing or multicast routing...
with
self
.
_multicast_change
:
...
...
tree/assert_.py
View file @
77f16d47
...
...
@@ -183,7 +183,7 @@ class SFMRAssertLooser(SFMRAssertABC):
interface
.
_set_assert_state
(
AssertState
.
Winner
)
interface
.
_set_winner_metric
(
None
)
interface
.
send_assert
()
@
staticmethod
def
al_rpc_better_than_aw
(
interface
):
...
...
tree/metric.py
View file @
77f16d47
...
...
@@ -58,10 +58,13 @@ class SFMRAssertMetric(object):
#metric._node = tree_if.get_node()
metric_preference
=
10
# todo check how to get metric preference
route_metric
=
tree_if
.
get_cost
()
ip
=
tree_if
.
get_ip
()
metric
=
SFMRAssertMetric
(
metric_preference
=
metric_preference
,
route_metric
=
route_metric
,
ip_address
=
ip
)
#metric_preference = 10 # todo check how to get metric preference
#route_metric = tree_if.get_cost()
import
UnicastRouting
(
source
,
group
)
=
tree_if
.
get_tree_id
()
(
metric_prefernce
,
metric
)
=
UnicastRouting
.
get_metric
(
source
)
interface_ip
=
tree_if
.
get_ip
()
metric
=
SFMRAssertMetric
(
metric_preference
=
metric_prefernce
,
route_metric
=
metric
,
ip_address
=
interface_ip
)
return
metric
...
...
tree/non_root_interface.py
View file @
77f16d47
...
...
@@ -34,8 +34,10 @@ class SFRMNonRootInterface(SFRMTreeInterface):
# Override
def
recv_data_msg
(
self
,
msg
=
None
,
sender
=
None
):
if
self
.
_prune_state
!=
SFMRPruneState
.
NDI
:
self
.
_assert_state
.
data_arrival
(
self
)
# todo perguntar ao prof
#if self._prune_state != SFMRPruneState.NDI:
# self._assert_state.data_arrival(self)
self
.
_assert_state
.
data_arrival
(
self
)
# Override
def
recv_assert_msg
(
self
,
msg
:
ReceivedPacket
,
sender
=
None
):
...
...
@@ -43,8 +45,9 @@ class SFRMNonRootInterface(SFRMTreeInterface):
@type msg: SFMRAssertMsg
@type sender: Addr
'''
if
self
.
_prune_state
==
SFMRPruneState
.
NDI
:
return
# todo perguntar ao prof
#if self._prune_state == SFMRPruneState.NDI:
# return
if
self
.
_assert_state
==
AssertState
.
Looser
:
winner_metric
=
self
.
_get_winner_metric
()
...
...
@@ -55,8 +58,10 @@ class SFRMNonRootInterface(SFRMTreeInterface):
pkt_assert
=
msg
.
payload
.
payload
# type: PacketPimAssert
msg_metric
=
SFMRAssertMetric
(
metric_preference
=
pkt_assert
.
metric_preference
,
route_metric
=
pkt_assert
.
metric
,
ip_address
=
ip_sender
)
if
winner_metric
.
is_worse_than
(
msg_metric
):
print
(
"ASSERT BETTER"
)
self
.
_assert_state
.
recv_better_metric
(
self
,
msg_metric
)
else
:
print
(
"ASSERT WORSE"
)
self
.
_assert_state
.
recv_worse_metric
(
self
,
msg_metric
)
# Override
...
...
@@ -85,7 +90,9 @@ class SFRMNonRootInterface(SFRMTreeInterface):
from
Packet.Packet
import
Packet
from
Packet.PacketPimHeader
import
PacketPimHeader
from
Packet.PacketPimAssert
import
PacketPimAssert
ph
=
PacketPimAssert
(
multicast_group_address
=
group
,
source_address
=
source
,
metric_preference
=
10
,
metric
=
2
)
import
UnicastRouting
(
metric_preference
,
metric
)
=
UnicastRouting
.
get_metric
(
source
)
ph
=
PacketPimAssert
(
multicast_group_address
=
group
,
source_address
=
source
,
metric_preference
=
metric_preference
,
metric
=
metric
)
pckt
=
Packet
(
payload
=
PacketPimHeader
(
ph
))
self
.
get_interface
().
send
(
pckt
.
bytes
())
print
(
'sent assert msg'
)
...
...
@@ -111,11 +118,22 @@ class SFRMNonRootInterface(SFRMTreeInterface):
return
self
.
_prune_state
==
SFMRPruneState
.
NDI
# Override
def
nbr_died
(
self
,
node
):
def
nbr_died
(
self
,
neighbor_ip
):
import
ipaddress
neighbor_ip
=
ipaddress
.
ip_address
(
neighbor_ip
)
# todo
#if self._get_winner_metric() is not None \
# and self._get_winner_metric().get_ip_address() == node\
# and self._prune_state != SFMRPruneState.NDI:
# self._assert_state.aw_failure(self)
winner_metric
=
self
.
_get_winner_metric
()
print
(
winner_metric
.
get_ip_address
())
print
(
neighbor_ip
)
print
(
winner_metric
.
get_route_metric
())
print
(
winner_metric
.
get_metric_preference
())
if
self
.
_get_winner_metric
()
is
not
None
\
and
self
.
_get_winner_metric
().
get_ip_address
()
==
node
\
and
self
.
_prune_state
!=
SFMRPruneState
.
NDI
:
and
self
.
_get_winner_metric
().
get_ip_address
()
==
neighbor_ip
:
self
.
_assert_state
.
aw_failure
(
self
)
self
.
_prune_state
.
lost_nbr
(
self
)
...
...
tree/prune.py
View file @
77f16d47
...
...
@@ -166,8 +166,8 @@ class SFMRDownstreamInterestedPending(SFMRPruneStateABC):
'''
print
(
'lost_nbr, DIP -> DIP'
)
#todo alterado pelo Pedro... necessita de verificar se esta OK...
interface
.
send_prune
()
interface
.
set_dipt_timer
()
#
interface.send_prune()
#
interface.set_dipt_timer()
class
SFMRNoDownstreamInterested
(
SFMRPruneStateABC
):
...
...
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