Commit 77f16d47 authored by Pedro Oliveira's avatar Pedro Oliveira

assert

parent 2290b757
...@@ -92,6 +92,7 @@ class Daemon: ...@@ -92,6 +92,7 @@ class Daemon:
# Try killing the Daemon process # Try killing the Daemon process
try: try:
while 1: while 1:
#os.killpg(os.getpgid(pid), signal.SIGTERM)
os.kill(pid, signal.SIGTERM) os.kill(pid, signal.SIGTERM)
time.sleep(0.1) time.sleep(0.1)
except OSError as err: except OSError as err:
...@@ -100,7 +101,7 @@ class Daemon: ...@@ -100,7 +101,7 @@ class Daemon:
if os.path.exists(self.pidfile): if os.path.exists(self.pidfile):
os.remove(self.pidfile) os.remove(self.pidfile)
else: else:
print (str(err.args)) print(str(err.args))
sys.exit(1) sys.exit(1)
def restart(self): def restart(self):
...@@ -125,5 +126,5 @@ class Daemon: ...@@ -125,5 +126,5 @@ class Daemon:
try: try:
os.kill(pid, 0) os.kill(pid, 0)
return True return True
except OSError: except:
return False return False
import random
from threading import Timer
from Packet.Packet import Packet
from Packet.ReceivedPacket import ReceivedPacket from Packet.ReceivedPacket import ReceivedPacket
from Packet.PacketPimHello import PacketPimHello
from Packet.PacketPimHeader import PacketPimHeader
from Interface import Interface
import Main import Main
from utils import HELLO_HOLD_TIME_TIMEOUT
from Neighbor import Neighbor from Neighbor import Neighbor
...@@ -17,39 +10,6 @@ class Hello: ...@@ -17,39 +10,6 @@ class Hello:
def __init__(self): def __init__(self):
Main.add_protocol(Hello.TYPE, 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 # receive handler
def receive_handle(self, packet: ReceivedPacket): def receive_handle(self, packet: ReceivedPacket):
interface = packet.interface interface = packet.interface
...@@ -71,44 +31,44 @@ class Hello: ...@@ -71,44 +31,44 @@ class Hello:
interface.neighbors[ip] = Neighbor(interface, ip, generation_id, hello_hold_time) interface.neighbors[ip] = Neighbor(interface, ip, generation_id, hello_hold_time)
return return
with neighbor.neighbor_lock: neighbor.receive_hello(generation_id, hello_hold_time)
# Already know Neighbor """
print("neighbor conhecido") with neighbor.neighbor_lock:
neighbor.heartbeat() # Already know Neighbor
if neighbor.hello_hold_time != hello_hold_time: print("neighbor conhecido")
print("keep alive period diferente") neighbor.heartbeat()
neighbor.set_hello_hold_time(hello_hold_time) if neighbor.hello_hold_time != hello_hold_time:
if neighbor.generation_id != generation_id: print("keep alive period diferente")
print("neighbor reiniciado") neighbor.set_hello_hold_time(hello_hold_time)
neighbor.set_generation_id(generation_id) if neighbor.generation_id != generation_id:
print("neighbor reiniciado")
neighbor.set_generation_id(generation_id)
'''
with interface.neighbors_lock.genWlock(): with interface.neighbors_lock.genWlock():
#if interface.get_neighbor(ip) is None: #if interface.get_neighbor(ip) is None:
if ip in interface.neighbors: if ip in interface.neighbors:
# Unknown Neighbor # Unknown Neighbor
if (1 in options) and (20 in options): if (1 in options) and (20 in options):
try: try:
#Main.add_neighbor(packet.interface, ip, options[20], options[1]) #Main.add_neighbor(packet.interface, ip, options[20], options[1])
print("non neighbor and options inside") print("non neighbor and options inside")
except Exception: except Exception:
# Received Neighbor with Timeout # Received Neighbor with Timeout
print("non neighbor and options inside but neighbor timedout") print("non neighbor and options inside but neighbor timedout")
pass pass
return return
print("non neighbor and required options not inside") print("non neighbor and required options not inside")
else: else:
# Already know Neighbor # Already know Neighbor
print("neighbor conhecido") print("neighbor conhecido")
neighbor = Main.get_neighbor(ip) neighbor = Main.get_neighbor(ip)
neighbor.heartbeat() neighbor.heartbeat()
if 1 in options and neighbor.hello_hold_time != options[1]: if 1 in options and neighbor.hello_hold_time != options[1]:
print("keep alive period diferente") print("keep alive period diferente")
neighbor.set_hello_hold_time(options[1]) neighbor.set_hello_hold_time(options[1])
if 20 in options and neighbor.generation_id != options[20]: if 20 in options and neighbor.generation_id != options[20]:
print("neighbor reiniciado") print("neighbor reiniciado")
neighbor.remove() neighbor.remove()
Main.add_neighbor(packet.interface, ip, options[20], options[1]) Main.add_neighbor(packet.interface, ip, options[20], options[1])
''' """
\ No newline at end of file
...@@ -5,7 +5,12 @@ from Packet.ReceivedPacket import ReceivedPacket ...@@ -5,7 +5,12 @@ from Packet.ReceivedPacket import ReceivedPacket
import Main import Main
import traceback import traceback
from RWLock.RWLock import RWLockWrite 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): class InterfacePim(Interface):
MCAST_GRP = '224.0.0.13' MCAST_GRP = '224.0.0.13'
...@@ -20,6 +25,12 @@ class InterfacePim(Interface): ...@@ -20,6 +25,12 @@ class InterfacePim(Interface):
self.neighbors = {} self.neighbors = {}
self.neighbors_lock = RWLockWrite() 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 # run receive method in background
receive_thread = threading.Thread(target=self.receive) receive_thread = threading.Thread(target=self.receive)
receive_thread.daemon = True receive_thread.daemon = True
...@@ -49,9 +60,35 @@ class InterfacePim(Interface): ...@@ -49,9 +60,35 @@ class InterfacePim(Interface):
def send(self, data: bytes, group_ip: str=MCAST_GRP): def send(self, data: bytes, group_ip: str=MCAST_GRP):
super().send(data=data, group_ip=group_ip) 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): 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() super().remove()
def add_neighbor(self, ip, random_number, hello_hold_time): def add_neighbor(self, ip, random_number, hello_hold_time):
with self.neighbors_lock.genWlock(): with self.neighbors_lock.genWlock():
if ip not in self.neighbors: if ip not in self.neighbors:
...@@ -69,3 +106,7 @@ class InterfacePim(Interface): ...@@ -69,3 +106,7 @@ class InterfacePim(Interface):
def get_neighbor(self, ip): def get_neighbor(self, ip):
with self.neighbors_lock.genRlock(): with self.neighbors_lock.genRlock():
return self.neighbors[ip] return self.neighbors[ip]
def remove_neighbor(self, ip):
with self.neighbors_lock.genWlock():
del self.neighbors[ip]
...@@ -133,6 +133,7 @@ class Kernel: ...@@ -133,6 +133,7 @@ class Kernel:
# MRT PIM # MRT PIM
s.setsockopt(socket.IPPROTO_IP, Kernel.MRT_PIM, 0) s.setsockopt(socket.IPPROTO_IP, Kernel.MRT_PIM, 0)
s.setsockopt(socket.IPPROTO_IP, Kernel.MRT_ASSERT, 1)
self.socket = s self.socket = s
self.rwlock = RWLockWrite() self.rwlock = RWLockWrite()
...@@ -275,6 +276,7 @@ class Kernel: ...@@ -275,6 +276,7 @@ class Kernel:
msg = self.socket.recv(5000) msg = self.socket.recv(5000)
#print(len(msg)) #print(len(msg))
(_, _, im_msgtype, im_mbz, im_vif, _, im_src, im_dst) = struct.unpack("II B B B B 4s 4s", msg[:20]) (_, _, 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: if im_mbz != 0:
continue continue
...@@ -284,7 +286,7 @@ class Kernel: ...@@ -284,7 +286,7 @@ class Kernel:
print(im_vif) print(im_vif)
print(socket.inet_ntoa(im_src)) print(socket.inet_ntoa(im_src))
print(socket.inet_ntoa(im_dst)) 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_src = socket.inet_ntoa(im_src)
ip_dst = socket.inet_ntoa(im_dst) ip_dst = socket.inet_ntoa(im_dst)
...@@ -293,6 +295,7 @@ class Kernel: ...@@ -293,6 +295,7 @@ class Kernel:
print("IGMP NO CACHE") print("IGMP NO CACHE")
self.igmpmsg_nocache_handler(ip_src, ip_dst, im_vif) self.igmpmsg_nocache_handler(ip_src, ip_dst, im_vif)
elif im_msgtype == Kernel.IGMPMSG_WRONGVIF: elif im_msgtype == Kernel.IGMPMSG_WRONGVIF:
print("WRONG VIF HANDLER")
self.igmpmsg_wrongvif_handler(ip_src, ip_dst, im_vif) self.igmpmsg_wrongvif_handler(ip_src, ip_dst, im_vif)
else: else:
raise Exception raise Exception
...@@ -333,7 +336,8 @@ class Kernel: ...@@ -333,7 +336,8 @@ class Kernel:
# receive multicast (S,G) packet in a outbound_interface # receive multicast (S,G) packet in a outbound_interface
def igmpmsg_wrongvif_handler(self, ip_src, ip_dst, iif): def igmpmsg_wrongvif_handler(self, ip_src, ip_dst, iif):
#kernel_entry = self.routing[(ip_src, ip_dst)] #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) #kernel_entry.recv_data_msg(iif)
""" """
...@@ -357,4 +361,19 @@ class Kernel: ...@@ -357,4 +361,19 @@ class Kernel:
#self.set_multicast_route(kernel_entry) #self.set_multicast_route(kernel_entry)
return kernel_entry return kernel_entry
else: else:
return None return None
\ No newline at end of file
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)
...@@ -6,6 +6,7 @@ from InterfacePIM import InterfacePim ...@@ -6,6 +6,7 @@ from InterfacePIM import InterfacePim
from InterfaceIGMP import InterfaceIGMP from InterfaceIGMP import InterfaceIGMP
from Kernel import Kernel from Kernel import Kernel
from threading import Lock from threading import Lock
import UnicastRouting
interfaces = {} # interfaces with multicast routing enabled interfaces = {} # interfaces with multicast routing enabled
igmp_interfaces = {} # igmp interfaces igmp_interfaces = {} # igmp interfaces
...@@ -13,15 +14,16 @@ protocols = {} ...@@ -13,15 +14,16 @@ protocols = {}
kernel = None kernel = None
igmp = None igmp = None
def add_interface(interface_name, pim=False, igmp=False): def add_interface(interface_name, pim=False, igmp=False):
if pim is True and interface_name not in interfaces: if pim is True and interface_name not in interfaces:
interface = InterfacePim(interface_name) interface = InterfacePim(interface_name)
interfaces[interface_name] = interface interfaces[interface_name] = interface
protocols[0].force_send(interface)
if igmp is True and interface_name not in igmp_interfaces: if igmp is True and interface_name not in igmp_interfaces:
interface = InterfaceIGMP(interface_name) interface = InterfaceIGMP(interface_name)
igmp_interfaces[interface_name] = interface igmp_interfaces[interface_name] = interface
def remove_interface(interface_name, pim=False, igmp=False): def remove_interface(interface_name, pim=False, igmp=False):
if pim is True and ((interface_name in interfaces) or interface_name == "*"): if pim is True and ((interface_name in interfaces) or interface_name == "*"):
if interface_name == "*": if interface_name == "*":
...@@ -29,10 +31,12 @@ def remove_interface(interface_name, pim=False, igmp=False): ...@@ -29,10 +31,12 @@ def remove_interface(interface_name, pim=False, igmp=False):
else: else:
interface_name_list = [interface_name] interface_name_list = [interface_name]
for if_name in interface_name_list: for if_name in interface_name_list:
protocols[0].force_send_remove(interfaces[if_name]) interface_obj = interfaces.pop(if_name)
interfaces[if_name].remove() interface_obj.remove()
del interfaces[if_name] #interfaces[if_name].remove()
#del interfaces[if_name]
print("removido interface") print("removido interface")
print(interfaces)
if igmp is True and ((interface_name in igmp_interfaces) or interface_name == "*"): if igmp is True and ((interface_name in igmp_interfaces) or interface_name == "*"):
if interface_name == "*": if interface_name == "*":
...@@ -43,6 +47,7 @@ def remove_interface(interface_name, pim=False, igmp=False): ...@@ -43,6 +47,7 @@ def remove_interface(interface_name, pim=False, igmp=False):
igmp_interfaces[if_name].remove() igmp_interfaces[if_name].remove()
del igmp_interfaces[if_name] del igmp_interfaces[if_name]
print("removido interface") print("removido interface")
print(igmp_interfaces)
""" """
...@@ -126,7 +131,7 @@ def list_enabled_interfaces(): ...@@ -126,7 +131,7 @@ def list_enabled_interfaces():
t = PrettyTable(['Interface', 'IP', 'PIM/IMGP Enabled', 'IGMP State']) t = PrettyTable(['Interface', 'IP', 'PIM/IGMP Enabled', 'IGMP State'])
for interface in netifaces.interfaces(): for interface in netifaces.interfaces():
try: try:
# TODO: fix same interface with multiple ips # TODO: fix same interface with multiple ips
...@@ -145,6 +150,11 @@ def list_enabled_interfaces(): ...@@ -145,6 +150,11 @@ def list_enabled_interfaces():
return str(t) 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(): def list_igmp_state():
t = PrettyTable(['Interface', 'RouterState', 'Group Adress', 'GroupState']) t = PrettyTable(['Interface', 'RouterState', 'Group Adress', 'GroupState'])
for (interface_name, interface_obj) in list(igmp_interfaces.items()): for (interface_name, interface_obj) in list(igmp_interfaces.items()):
...@@ -158,6 +168,7 @@ def list_igmp_state(): ...@@ -158,6 +168,7 @@ def list_igmp_state():
t.add_row([interface_name, state_txt, group_addr, group_state_txt]) t.add_row([interface_name, state_txt, group_addr, group_state_txt])
return str(t) return str(t)
def list_routing_state(): def list_routing_state():
routing_entries = kernel.routing.values() routing_entries = kernel.routing.values()
vif_indexes = kernel.vif_index_to_name_dic.keys() vif_indexes = kernel.vif_index_to_name_dic.keys()
...@@ -182,7 +193,13 @@ def list_routing_state(): ...@@ -182,7 +193,13 @@ def list_routing_state():
return str(t) 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 Hello import Hello
from IGMP import IGMP from IGMP import IGMP
from Assert import Assert from Assert import Assert
...@@ -196,5 +213,3 @@ def main(interfaces_to_add=[]): ...@@ -196,5 +213,3 @@ def main(interfaces_to_add=[]):
global igmp global igmp
igmp = IGMP() igmp = IGMP()
for interface in interfaces_to_add:
add_interface(interface)
from threading import Timer from threading import Timer
import time import time
from utils import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT from utils import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT, TYPE_CHECKING
from Interface import Interface
import Main
from threading import Lock from threading import Lock
import Main
if TYPE_CHECKING:
from InterfacePIM import InterfacePim
class Neighbor: 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: if hello_hold_time == HELLO_HOLD_TIME_TIMEOUT:
raise Exception raise Exception
self.contact_interface = contact_interface self.contact_interface = contact_interface
...@@ -19,8 +20,9 @@ class Neighbor: ...@@ -19,8 +20,9 @@ class Neighbor:
self.time_of_last_update = time.time() self.time_of_last_update = time.time()
self.neighbor_lock = Lock() self.neighbor_lock = Lock()
# todo # send hello to new neighbor
Main.protocols[0].force_send(contact_interface) self.contact_interface.send_hello()
def set_hello_hold_time(self, hello_hold_time: int): def set_hello_hold_time(self, hello_hold_time: int):
self.hello_hold_time = hello_hold_time self.hello_hold_time = hello_hold_time
...@@ -36,13 +38,13 @@ class Neighbor: ...@@ -36,13 +38,13 @@ class Neighbor:
self.neighbor_liveness_timer = None self.neighbor_liveness_timer = None
def set_generation_id(self, generation_id): 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 self.generation_id = generation_id
elif self.generation_id != generation_id: self.contact_interface.send_hello()
self.generation_id = generation_id self.reset()
self.set_hello_hold_time(self.hello_hold_time)
self.time_of_last_update = time.time()
"""
def heartbeat(self): def heartbeat(self):
if (self.hello_hold_time != HELLO_HOLD_TIME_TIMEOUT) and \ if (self.hello_hold_time != HELLO_HOLD_TIME_TIMEOUT) and \
(self.hello_hold_time != HELLO_HOLD_TIME_NO_TIMEOUT): (self.hello_hold_time != HELLO_HOLD_TIME_NO_TIMEOUT):
...@@ -52,10 +54,30 @@ class Neighbor: ...@@ -52,10 +54,30 @@ class Neighbor:
self.neighbor_liveness_timer = Timer(self.hello_hold_time, self.remove) self.neighbor_liveness_timer = Timer(self.hello_hold_time, self.remove)
self.neighbor_liveness_timer.start() self.neighbor_liveness_timer.start()
self.time_of_last_update = time.time() self.time_of_last_update = time.time()
"""
def remove(self): def remove(self):
print('HELLO TIMER EXPIRED... remove neighbor') print('HELLO TIMER EXPIRED... remove neighbor')
if self.neighbor_liveness_timer is not None: if self.neighbor_liveness_timer is not None:
self.neighbor_liveness_timer.cancel() self.neighbor_liveness_timer.cancel()
#Main.remove_neighbor(self.ip) #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] 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)
...@@ -62,7 +62,7 @@ class MyDaemon(Daemon): ...@@ -62,7 +62,7 @@ class MyDaemon(Daemon):
elif args.list_neighbors: elif args.list_neighbors:
connection.sendall(pickle.dumps(Main.list_neighbors())) connection.sendall(pickle.dumps(Main.list_neighbors()))
elif args.list_state: 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: elif args.add_interface:
Main.add_interface(args.add_interface[0], pim=True) Main.add_interface(args.add_interface[0], pim=True)
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
...@@ -76,7 +76,7 @@ class MyDaemon(Daemon): ...@@ -76,7 +76,7 @@ class MyDaemon(Daemon):
Main.remove_interface(args.remove_interface_igmp[0], igmp=True) Main.remove_interface(args.remove_interface_igmp[0], igmp=True)
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
elif args.stop: elif args.stop:
Main.remove_interface("*", pim=True, igmp=True) Main.stop()
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
except Exception: except Exception:
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
......
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
import Main import Main
import socket import socket
import netifaces
from tree.root_interface import SFRMRootInterface from tree.root_interface import SFRMRootInterface
from tree.non_root_interface import SFRMNonRootInterface from tree.non_root_interface import SFRMNonRootInterface
from threading import Timer, Lock from threading import Timer, Lock
import UnicastRouting
class KernelEntry: class KernelEntry:
TREE_TIMEOUT = 180 TREE_TIMEOUT = 180
...@@ -64,18 +64,7 @@ class KernelEntry: ...@@ -64,18 +64,7 @@ class KernelEntry:
return outbound_indexes return outbound_indexes
def check_rpf(self): def check_rpf(self):
from pyroute2 import IPRoute return UnicastRouting.check_rpf(self.source_ip)
# 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
def recv_data_msg(self, index): def recv_data_msg(self, index):
if self.is_originater(): if self.is_originater():
...@@ -130,19 +119,16 @@ class KernelEntry: ...@@ -130,19 +119,16 @@ class KernelEntry:
# todo # todo
return return
def nbr_died(self, index, neighbor_ip):
# todo
self.interface_state[index].nbr_died(neighbor_ip)
def is_in_group(self): def is_in_group(self):
# todo # todo
#if self.get_has_members(): #if self.get_has_members():
#if True: #if True:
# return 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(): for interface in self.interface_state.values():
if interface.is_forwarding(): if interface.is_forwarding():
return True return True
...@@ -176,16 +162,6 @@ class KernelEntry: ...@@ -176,16 +162,6 @@ class KernelEntry:
def get_group(self): def get_group(self):
return self.group_ip 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): def change(self):
# todo: changes on unicast routing or multicast routing... # todo: changes on unicast routing or multicast routing...
with self._multicast_change: with self._multicast_change:
......
...@@ -183,7 +183,7 @@ class SFMRAssertLooser(SFMRAssertABC): ...@@ -183,7 +183,7 @@ class SFMRAssertLooser(SFMRAssertABC):
interface._set_assert_state(AssertState.Winner) interface._set_assert_state(AssertState.Winner)
interface._set_winner_metric(None) interface._set_winner_metric(None)
interface.send_assert()
@staticmethod @staticmethod
def al_rpc_better_than_aw(interface): def al_rpc_better_than_aw(interface):
......
...@@ -58,10 +58,13 @@ class SFMRAssertMetric(object): ...@@ -58,10 +58,13 @@ class SFMRAssertMetric(object):
#metric._node = tree_if.get_node() #metric._node = tree_if.get_node()
metric_preference = 10 # todo check how to get metric preference #metric_preference = 10 # todo check how to get metric preference
route_metric = tree_if.get_cost() #route_metric = tree_if.get_cost()
ip = tree_if.get_ip() import UnicastRouting
metric = SFMRAssertMetric(metric_preference=metric_preference, route_metric=route_metric, ip_address=ip) (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 return metric
......
...@@ -34,8 +34,10 @@ class SFRMNonRootInterface(SFRMTreeInterface): ...@@ -34,8 +34,10 @@ class SFRMNonRootInterface(SFRMTreeInterface):
# Override # Override
def recv_data_msg(self, msg=None, sender=None): def recv_data_msg(self, msg=None, sender=None):
if self._prune_state != SFMRPruneState.NDI: # todo perguntar ao prof
self._assert_state.data_arrival(self) #if self._prune_state != SFMRPruneState.NDI:
# self._assert_state.data_arrival(self)
self._assert_state.data_arrival(self)
# Override # Override
def recv_assert_msg(self, msg: ReceivedPacket, sender=None): def recv_assert_msg(self, msg: ReceivedPacket, sender=None):
...@@ -43,8 +45,9 @@ class SFRMNonRootInterface(SFRMTreeInterface): ...@@ -43,8 +45,9 @@ class SFRMNonRootInterface(SFRMTreeInterface):
@type msg: SFMRAssertMsg @type msg: SFMRAssertMsg
@type sender: Addr @type sender: Addr
''' '''
if self._prune_state == SFMRPruneState.NDI: # todo perguntar ao prof
return #if self._prune_state == SFMRPruneState.NDI:
# return
if self._assert_state == AssertState.Looser: if self._assert_state == AssertState.Looser:
winner_metric = self._get_winner_metric() winner_metric = self._get_winner_metric()
...@@ -55,8 +58,10 @@ class SFRMNonRootInterface(SFRMTreeInterface): ...@@ -55,8 +58,10 @@ class SFRMNonRootInterface(SFRMTreeInterface):
pkt_assert = msg.payload.payload # type: PacketPimAssert 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) 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): if winner_metric.is_worse_than(msg_metric):
print("ASSERT BETTER")
self._assert_state.recv_better_metric(self, msg_metric) self._assert_state.recv_better_metric(self, msg_metric)
else: else:
print("ASSERT WORSE")
self._assert_state.recv_worse_metric(self, msg_metric) self._assert_state.recv_worse_metric(self, msg_metric)
# Override # Override
...@@ -85,7 +90,9 @@ class SFRMNonRootInterface(SFRMTreeInterface): ...@@ -85,7 +90,9 @@ class SFRMNonRootInterface(SFRMTreeInterface):
from Packet.Packet import Packet from Packet.Packet import Packet
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
from Packet.PacketPimAssert import PacketPimAssert 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)) pckt = Packet(payload=PacketPimHeader(ph))
self.get_interface().send(pckt.bytes()) self.get_interface().send(pckt.bytes())
print('sent assert msg') print('sent assert msg')
...@@ -111,11 +118,22 @@ class SFRMNonRootInterface(SFRMTreeInterface): ...@@ -111,11 +118,22 @@ class SFRMNonRootInterface(SFRMTreeInterface):
return self._prune_state == SFMRPruneState.NDI return self._prune_state == SFMRPruneState.NDI
# Override # Override
def nbr_died(self, node): def nbr_died(self, neighbor_ip):
import ipaddress
neighbor_ip = ipaddress.ip_address(neighbor_ip)
# todo # 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 \ if self._get_winner_metric() is not None \
and self._get_winner_metric().get_ip_address() == node\ and self._get_winner_metric().get_ip_address() == neighbor_ip:
and self._prune_state != SFMRPruneState.NDI:
self._assert_state.aw_failure(self) self._assert_state.aw_failure(self)
self._prune_state.lost_nbr(self) self._prune_state.lost_nbr(self)
......
...@@ -166,8 +166,8 @@ class SFMRDownstreamInterestedPending(SFMRPruneStateABC): ...@@ -166,8 +166,8 @@ class SFMRDownstreamInterestedPending(SFMRPruneStateABC):
''' '''
print('lost_nbr, DIP -> DIP') print('lost_nbr, DIP -> DIP')
#todo alterado pelo Pedro... necessita de verificar se esta OK... #todo alterado pelo Pedro... necessita de verificar se esta OK...
interface.send_prune() #interface.send_prune()
interface.set_dipt_timer() #interface.set_dipt_timer()
class SFMRNoDownstreamInterested(SFMRPruneStateABC): class SFMRNoDownstreamInterested(SFMRPruneStateABC):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment