Commit c5efb3cd authored by Pedro Oliveira's avatar Pedro Oliveira

fix AssertCancel message (metric) & protocol information defined before...

fix AssertCancel message (metric) & protocol information defined before initializing sockets & use of logs for tests & routing information stored in a different way (in Kernel) & fix some state machines & fix unicast routing updates & fix delete of tree information
parent 58dd3f58
...@@ -21,8 +21,11 @@ class Interface(metaclass=ABCMeta): ...@@ -21,8 +21,11 @@ class Interface(metaclass=ABCMeta):
# set receive socket and send socket # set receive socket and send socket
self._send_socket = send_socket self._send_socket = send_socket
self._recv_socket = recv_socket self._recv_socket = recv_socket
self.interface_enabled = True self.interface_enabled = False
def _enable(self):
self.interface_enabled = True
# 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
......
...@@ -6,7 +6,7 @@ from Interface import Interface ...@@ -6,7 +6,7 @@ from Interface import Interface
from ctypes import create_string_buffer, addressof from ctypes import create_string_buffer, addressof
from ipaddress import IPv4Address from ipaddress import IPv4Address
from utils import Version_1_Membership_Report, Version_2_Membership_Report, Leave_Group, Membership_Query from utils import Version_1_Membership_Report, Version_2_Membership_Report, Leave_Group, Membership_Query
import subprocess
if not hasattr(socket, 'SO_BINDTODEVICE'): if not hasattr(socket, 'SO_BINDTODEVICE'):
socket.SO_BINDTODEVICE = 25 socket.SO_BINDTODEVICE = 25
...@@ -15,6 +15,7 @@ class InterfaceIGMP(Interface): ...@@ -15,6 +15,7 @@ class InterfaceIGMP(Interface):
ETH_P_IP = 0x0800 # Internet Protocol packet ETH_P_IP = 0x0800 # Internet Protocol packet
SO_ATTACH_FILTER = 26 SO_ATTACH_FILTER = 26
# TODO filtro nao esta a funcionar bem no netkit
FILTER_IGMP = [ FILTER_IGMP = [
struct.pack('HBBI', 0x28, 0, 0, 0x0000000c), struct.pack('HBBI', 0x28, 0, 0, 0x0000000c),
struct.pack('HBBI', 0x15, 0, 3, 0x00000800), struct.pack('HBBI', 0x15, 0, 3, 0x00000800),
...@@ -25,31 +26,36 @@ class InterfaceIGMP(Interface): ...@@ -25,31 +26,36 @@ class InterfaceIGMP(Interface):
] ]
def __init__(self, interface_name: str, vif_index:int): def __init__(self, interface_name: str, vif_index:int):
# SEND SOCKET
snd_s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
# bind to interface
snd_s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, str(interface_name + "\0").encode('utf-8'))
# RECEIVE SOCKET # RECEIVE SOCKET
rcv_s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(InterfaceIGMP.ETH_P_IP)) rcv_s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(InterfaceIGMP.ETH_P_IP))
# receive only IGMP packets by setting a BPF filter # receive only IGMP packets by setting a BPF filter
filters = b''.join(InterfaceIGMP.FILTER_IGMP) # TODO filtro nao esta a funcionar bem no netkit
b = create_string_buffer(filters) cmd = "tcpdump -ddd \"ip proto 2\""
result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
bpf_filter = b''
tmp = result.stdout.read().splitlines()
for line in tmp[1:]:
bpf_filter += struct.pack("HBBI", *tuple(map(int, line.split(b' '))))
b = create_string_buffer(bpf_filter)
mem_addr_of_filters = addressof(b) mem_addr_of_filters = addressof(b)
fprog = struct.pack('HL', len(InterfaceIGMP.FILTER_IGMP), mem_addr_of_filters) fprog = struct.pack('HL', len(InterfaceIGMP.FILTER_IGMP), mem_addr_of_filters)
rcv_s.setsockopt(socket.SOL_SOCKET, InterfaceIGMP.SO_ATTACH_FILTER, fprog) rcv_s.setsockopt(socket.SOL_SOCKET, InterfaceIGMP.SO_ATTACH_FILTER, fprog)
# bind to interface # bind to interface
rcv_s.bind((interface_name, 0x0800)) rcv_s.bind((interface_name, 0x0800))
# SEND SOCKET
snd_s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
# bind to interface
snd_s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, str(interface_name + "\0").encode('utf-8'))
super().__init__(interface_name=interface_name, recv_socket=rcv_s, send_socket=snd_s, vif_index=vif_index) super().__init__(interface_name=interface_name, recv_socket=rcv_s, send_socket=snd_s, vif_index=vif_index)
from igmp.RouterState import RouterState from igmp.RouterState import RouterState
self.interface_state = RouterState(self) self.interface_state = RouterState(self)
super()._enable()
def get_ip(self): def get_ip(self):
......
...@@ -13,6 +13,8 @@ from threading import Timer ...@@ -13,6 +13,8 @@ from threading import Timer
from tree.globals import REFRESH_INTERVAL from tree.globals import REFRESH_INTERVAL
import socket import socket
import netifaces import netifaces
class InterfacePim(Interface): class InterfacePim(Interface):
MCAST_GRP = '224.0.0.13' MCAST_GRP = '224.0.0.13'
PROPAGATION_DELAY = 0.5 PROPAGATION_DELAY = 0.5
...@@ -23,9 +25,34 @@ class InterfacePim(Interface): ...@@ -23,9 +25,34 @@ class InterfacePim(Interface):
def __init__(self, interface_name: str, vif_index:int, state_refresh_capable:bool=False): def __init__(self, interface_name: str, vif_index:int, state_refresh_capable:bool=False):
# generation id
self.generation_id = random.getrandbits(32)
# 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
self.hello_timer = None
# state refresh capable
self._state_refresh_capable = state_refresh_capable
self._neighbors_state_refresh_capable = False
# todo: lan delay enabled
self._lan_delay_enabled = False
# todo: propagation delay
self._propagation_delay = self.PROPAGATION_DELAY
# todo: override interval
self._override_interval = self.OVERRIDE_INTERNAL
# pim neighbors
self._had_neighbors = False
self.neighbors = {}
self.neighbors_lock = RWLockWrite()
# SOCKET
ip_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['addr'] ip_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['addr']
self.ip_interface = ip_interface self.ip_interface = ip_interface
self.ip_mask_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['netmask']
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM) s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM)
...@@ -49,36 +76,10 @@ class InterfacePim(Interface): ...@@ -49,36 +76,10 @@ class InterfacePim(Interface):
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0) s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
super().__init__(interface_name, s, s, vif_index) super().__init__(interface_name, s, s, vif_index)
super()._enable()
# generation id
self.generation_id = random.getrandbits(32)
# 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
self.hello_timer = None
self.force_send_hello() self.force_send_hello()
# state refresh capable
self._state_refresh_capable = state_refresh_capable
# todo: lan delay enabled
self._lan_delay_enabled = False
# todo: propagation delay
self._propagation_delay = self.PROPAGATION_DELAY
# todo: override interval
self._override_interval = self.OVERRIDE_INTERNAL
# pim neighbors
self._had_neighbors = False
self.neighbors = {}
self.neighbors_lock = RWLockWrite()
def get_ip(self): def get_ip(self):
return self.ip_interface return self.ip_interface
...@@ -144,7 +145,7 @@ class InterfacePim(Interface): ...@@ -144,7 +145,7 @@ class InterfacePim(Interface):
self._had_neighbors = has_neighbors self._had_neighbors = has_neighbors
Main.kernel.interface_change_number_of_neighbors() Main.kernel.interface_change_number_of_neighbors()
'''
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:
...@@ -153,6 +154,7 @@ class InterfacePim(Interface): ...@@ -153,6 +154,7 @@ class InterfacePim(Interface):
self.neighbors[ip] = Neighbor(self, ip, random_number, hello_hold_time) self.neighbors[ip] = Neighbor(self, ip, random_number, hello_hold_time)
self.force_send_hello() self.force_send_hello()
self.check_number_of_neighbors() self.check_number_of_neighbors()
'''
def get_neighbors(self): def get_neighbors(self):
with self.neighbors_lock.genRlock(): with self.neighbors_lock.genRlock():
...@@ -171,6 +173,19 @@ class InterfacePim(Interface): ...@@ -171,6 +173,19 @@ class InterfacePim(Interface):
def is_state_refresh_enabled(self): def is_state_refresh_enabled(self):
return self._state_refresh_capable return self._state_refresh_capable
# check if Interface is StateRefreshCapable
def is_state_refresh_capable(self):
with self.neighbors_lock.genWlock():
if len(self.neighbors) == 0:
return False
state_refresh_capable = True
for neighbor in list(self.neighbors.values()):
state_refresh_capable &= neighbor.state_refresh_capable
return state_refresh_capable
########################################### ###########################################
# Recv packets # Recv packets
......
import socket import socket
import struct import struct
import netifaces import netifaces
import threading from threading import Lock
import traceback import traceback
import ipaddress import ipaddress
...@@ -56,7 +56,7 @@ class Kernel: ...@@ -56,7 +56,7 @@ class Kernel:
self.vif_index_to_name_dic = {} self.vif_index_to_name_dic = {}
self.vif_name_to_index_dic = {} self.vif_name_to_index_dic = {}
# KEY : (source_ip, group_ip), VALUE : KernelEntry ???? TODO # KEY : source_ip, VALUE : {group_ip: KernelEntry}
self.routing = {} self.routing = {}
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP) s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
...@@ -76,24 +76,14 @@ class Kernel: ...@@ -76,24 +76,14 @@ class Kernel:
# todo useless in PIM-DM... useful in PIM-SM # todo useless in PIM-DM... useful in PIM-SM
#self.create_virtual_interface("0.0.0.0", "pimreg", index=0, flags=Kernel.VIFF_REGISTER) #self.create_virtual_interface("0.0.0.0", "pimreg", index=0, flags=Kernel.VIFF_REGISTER)
# Create virtual interfaces
'''
interfaces = netifaces.interfaces()
for interface in interfaces:
try:
# ignore localhost interface
if interface == 'lo':
continue
addrs = netifaces.ifaddresses(interface)
addr = addrs[netifaces.AF_INET][0]['addr']
self.create_virtual_interface(ip_interface=addr, interface_name=interface)
except Exception:
continue
'''
self.pim_interface = {} # name: interface_pim self.pim_interface = {} # name: interface_pim
self.igmp_interface = {} # name: interface_igmp self.igmp_interface = {} # name: interface_igmp
# logs
self.interface_logger = Main.logger.getChild('KernelInterface')
self.tree_logger = Main.logger.getChild('KernelTree')
# receive signals from kernel with a background thread # receive signals from kernel with a background thread
handler_thread = threading.Thread(target=self.handler) handler_thread = threading.Thread(target=self.handler)
handler_thread.daemon = True handler_thread.daemon = True
...@@ -152,9 +142,11 @@ class Kernel: ...@@ -152,9 +142,11 @@ class Kernel:
self.vif_name_to_index_dic[interface_name] = index self.vif_name_to_index_dic[interface_name] = index
with self.rwlock.genWlock(): with self.rwlock.genWlock():
for kernel_entry in list(self.routing.values()): for source_dict in list(self.routing.values()):
kernel_entry.new_interface(index) for kernel_entry in list(source_dict.values()):
kernel_entry.new_interface(index)
self.interface_logger.debug('Create virtual interface: %s -> %d', interface_name, index)
return index return index
...@@ -273,13 +265,15 @@ class Kernel: ...@@ -273,13 +265,15 @@ class Kernel:
del self.vif_dic[ip_interface] del self.vif_dic[ip_interface]
del self.vif_name_to_index_dic[self.vif_index_to_name_dic[index]] del self.vif_name_to_index_dic[self.vif_index_to_name_dic[index]]
del self.vif_index_to_name_dic[index] interface_name = self.vif_index_to_name_dic.pop(index)
# TODO alterar MFC's para colocar a 0 esta interface
# alterar MFC's para colocar a 0 esta interface
with self.rwlock.genWlock(): with self.rwlock.genWlock():
for kernel_entry in list(self.routing.values()): for source_dict in list(self.routing.values()):
kernel_entry.remove_interface(index) for kernel_entry in list(source_dict.values()):
kernel_entry.remove_interface(index)
self.interface_logger.debug('Remove virtual interface: %s -> %d', interface_name, index)
...@@ -316,9 +310,6 @@ class Kernel: ...@@ -316,9 +310,6 @@ class Kernel:
struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, kernel_entry.inbound_interface_index, *outbound_interfaces_and_other_parameters) struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, kernel_entry.inbound_interface_index, *outbound_interfaces_and_other_parameters)
self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_ADD_MFC, struct_mfcctl) self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_ADD_MFC, struct_mfcctl)
# TODO: ver melhor tabela routing
#self.routing[(socket.inet_ntoa(source_ip), socket.inet_ntoa(group_ip))] = {"inbound_interface_index": inbound_interface_index, "outbound_interfaces": outbound_interfaces}
def remove_multicast_route(self, kernel_entry: KernelEntry): def remove_multicast_route(self, kernel_entry: KernelEntry):
source_ip = socket.inet_aton(kernel_entry.source_ip) source_ip = socket.inet_aton(kernel_entry.source_ip)
...@@ -326,9 +317,10 @@ class Kernel: ...@@ -326,9 +317,10 @@ class Kernel:
outbound_interfaces_and_other_parameters = [0] + [0]*Kernel.MAXVIFS + [0]*4 outbound_interfaces_and_other_parameters = [0] + [0]*Kernel.MAXVIFS + [0]*4
struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, *outbound_interfaces_and_other_parameters) struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, *outbound_interfaces_and_other_parameters)
self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_DEL_MFC, struct_mfcctl) self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_DEL_MFC, struct_mfcctl)
self.routing.pop((kernel_entry.source_ip, kernel_entry.group_ip)) self.routing[kernel_entry.source_ip].pop(kernel_entry.group_ip)
if len(self.routing[kernel_entry.source_ip]) == 0:
self.routing.pop(kernel_entry.source_ip)
def exit(self): def exit(self):
self.running = False self.running = False
...@@ -389,39 +381,12 @@ class Kernel: ...@@ -389,39 +381,12 @@ class Kernel:
# receive multicast (S,G) packet and multicast routing table has no (S,G) entry # receive multicast (S,G) packet and multicast routing table has no (S,G) entry
def igmpmsg_nocache_handler(self, ip_src, ip_dst, iif): def igmpmsg_nocache_handler(self, ip_src, ip_dst, iif):
source_group_pair = (ip_src, ip_dst) source_group_pair = (ip_src, ip_dst)
"""
with self.rwlock.genWlock():
if source_group_pair in self.routing:
kernel_entry = self.routing[(ip_src, ip_dst)]
else:
kernel_entry = KernelEntry(ip_src, ip_dst, iif)
self.routing[(ip_src, ip_dst)] = kernel_entry
self.set_multicast_route(kernel_entry)
kernel_entry.recv_data_msg(iif)
"""
"""
with self.rwlock.genRlock():
if source_group_pair in self.routing:
kernel_entry = self.routing[(ip_src, ip_dst)]
with self.rwlock.genWlock():
if source_group_pair in self.routing:
kernel_entry = self.routing[(ip_src, ip_dst)]
else:
kernel_entry = KernelEntry(ip_src, ip_dst, iif)
self.routing[(ip_src, ip_dst)] = kernel_entry
self.set_multicast_route(kernel_entry)
kernel_entry.recv_data_msg(iif)
"""
self.get_routing_entry(source_group_pair, create_if_not_existent=True).recv_data_msg(iif) self.get_routing_entry(source_group_pair, create_if_not_existent=True).recv_data_msg(iif)
# 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)]
source_group_pair = (ip_src, ip_dst) source_group_pair = (ip_src, ip_dst)
self.get_routing_entry(source_group_pair, create_if_not_existent=True).recv_data_msg(iif) self.get_routing_entry(source_group_pair, create_if_not_existent=True).recv_data_msg(iif)
#kernel_entry.recv_data_msg(iif)
''' useless in PIM-DM... useful in PIM-SM ''' useless in PIM-DM... useful in PIM-SM
...@@ -434,44 +399,40 @@ class Kernel: ...@@ -434,44 +399,40 @@ class Kernel:
"""
def get_routing_entry(self, source_group: tuple):
with self.rwlock.genRlock():
return self.routing[source_group]
"""
def get_routing_entry(self, source_group: tuple, create_if_not_existent=True): def get_routing_entry(self, source_group: tuple, create_if_not_existent=True):
ip_src = source_group[0] ip_src = source_group[0]
ip_dst = source_group[1] ip_dst = source_group[1]
with self.rwlock.genRlock(): with self.rwlock.genRlock():
if source_group in self.routing: if ip_src in self.routing and ip_dst in self.routing[ip_src]:
return self.routing[(ip_src, ip_dst)] return self.routing[ip_src][ip_dst]
with self.rwlock.genWlock(): with self.rwlock.genWlock():
if source_group in self.routing: if ip_src in self.routing and ip_dst in self.routing[ip_src]:
return self.routing[(ip_src, ip_dst)] return self.routing[ip_src][ip_dst]
elif create_if_not_existent: elif create_if_not_existent:
kernel_entry = KernelEntry(ip_src, ip_dst, 0) kernel_entry = KernelEntry(ip_src, ip_dst, 0)
self.routing[source_group] = kernel_entry if ip_src not in self.routing:
kernel_entry.change() self.routing[ip_src] = {}
#self.set_multicast_route(kernel_entry)
self.routing[ip_src][ip_dst] = kernel_entry
return kernel_entry return kernel_entry
else: else:
return None return None
# notify KernelEntries about changes at the unicast routing table
def notify_unicast_changes(self, subnet): def notify_unicast_changes(self, subnet):
# todo
with self.rwlock.genWlock(): with self.rwlock.genWlock():
for (source_ip, group) in self.routing.keys(): for source_ip in self.routing.keys():
source_ip_obj = ipaddress.ip_address(source_ip) source_ip_obj = ipaddress.ip_address(source_ip)
if source_ip_obj in subnet: if source_ip_obj not in subnet:
self.routing[(source_ip, group)].network_update() continue
print(source_ip) for group_ip in self.routing[source_ip].keys():
self.routing[source_ip][group_ip].network_update()
pass
# When interface changes number of neighbors verify if olist changes and prune/forward respectively # When interface changes number of neighbors verify if olist changes and prune/forward respectively
def interface_change_number_of_neighbors(self): def interface_change_number_of_neighbors(self):
with self.rwlock.genWlock(): with self.rwlock.genWlock():
for entry in self.routing.values(): for groups_dict in self.routing.values():
entry.change_at_number_of_neighbors() for entry in groups_dict.values():
entry.change_at_number_of_neighbors()
...@@ -2,17 +2,17 @@ import netifaces ...@@ -2,17 +2,17 @@ import netifaces
import time import time
from prettytable import PrettyTable from prettytable import PrettyTable
from InterfacePIM import InterfacePim #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 import UnicastRouting
interfaces = {} # interfaces with multicast routing enabled interfaces = {} # interfaces with multicast routing enabled
igmp_interfaces = {} # igmp interfaces igmp_interfaces = {} # igmp interfaces
kernel = None kernel = None
igmp = None
unicast_routing = None unicast_routing = None
logger = None
def add_pim_interface(interface_name, state_refresh_capable:bool=False): def add_pim_interface(interface_name, state_refresh_capable:bool=False):
kernel.create_pim_interface(interface_name=interface_name, state_refresh_capable=state_refresh_capable) kernel.create_pim_interface(interface_name=interface_name, state_refresh_capable=state_refresh_capable)
...@@ -119,7 +119,10 @@ def list_igmp_state(): ...@@ -119,7 +119,10 @@ def list_igmp_state():
def list_routing_state(): def list_routing_state():
routing_entries = kernel.routing.values() routing_entries = []
for a in list(kernel.routing.values()):
for b in list(a.values()):
routing_entries.append(b)
vif_indexes = kernel.vif_index_to_name_dic.keys() vif_indexes = kernel.vif_index_to_name_dic.keys()
t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"]) t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"])
...@@ -133,17 +136,17 @@ def list_routing_state(): ...@@ -133,17 +136,17 @@ def list_routing_state():
interface_name = kernel.vif_index_to_name_dic[index] interface_name = kernel.vif_index_to_name_dic[index]
local_membership = type(interface_state._local_membership_state).__name__ local_membership = type(interface_state._local_membership_state).__name__
try: try:
assert_state = type(interface_state._assert_state).__name__
if index != upstream_if_index: if index != upstream_if_index:
prune_state = type(interface_state._prune_state).__name__ prune_state = type(interface_state._prune_state).__name__
assert_state = type(interface_state._assert_state).__name__
is_forwarding = interface_state.is_forwarding() is_forwarding = interface_state.is_forwarding()
else: else:
prune_state = type(interface_state._graft_prune_state).__name__ prune_state = type(interface_state._graft_prune_state).__name__
assert_state = "-"
is_forwarding = "upstream" is_forwarding = "upstream"
except: except:
prune_state = "-" prune_state = "-"
assert_state = "-" assert_state = "-"
is_forwarding = "-"
t.add_row([ip, group, interface_name, prune_state, assert_state, local_membership, is_forwarding]) t.add_row([ip, group, interface_name, prune_state, assert_state, local_membership, is_forwarding])
return str(t) return str(t)
...@@ -155,8 +158,27 @@ def stop(): ...@@ -155,8 +158,27 @@ def stop():
unicast_routing.stop() unicast_routing.stop()
def test(router_name, server_logger_ip):
global logger
import logging.handlers
from TestLogger import RootFilter
socketHandler = logging.handlers.SocketHandler(server_logger_ip,
logging.handlers.DEFAULT_TCP_LOGGING_PORT)
# don't bother with a formatter, since a socket handler sends the event as
# an unformatted pickle
socketHandler.addFilter(RootFilter(router_name))
logger.addHandler(socketHandler)
def main(): def main():
# logging
global logger
import sys
import logging, logging.handlers
logger = logging.getLogger('pim')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler(sys.stdout))
global kernel global kernel
kernel = Kernel() kernel = Kernel()
......
...@@ -30,13 +30,13 @@ class PacketPimAssert: ...@@ -30,13 +30,13 @@ class PacketPimAssert:
PIM_HDR_ASSERT_v4_LEN = struct.calcsize(PIM_HDR_ASSERT_v4) PIM_HDR_ASSERT_v4_LEN = struct.calcsize(PIM_HDR_ASSERT_v4)
PIM_HDR_ASSERT_v6_LEN = struct.calcsize(PIM_HDR_ASSERT_v6) PIM_HDR_ASSERT_v6_LEN = struct.calcsize(PIM_HDR_ASSERT_v6)
def __init__(self, multicast_group_address: str or bytes, source_address: str or bytes, metric_preference: int, metric: int or float): def __init__(self, multicast_group_address: str or bytes, source_address: str or bytes, metric_preference: int or float, metric: int or float):
if type(multicast_group_address) is bytes: if type(multicast_group_address) is bytes:
multicast_group_address = socket.inet_ntoa(multicast_group_address) multicast_group_address = socket.inet_ntoa(multicast_group_address)
if type(source_address) is bytes: if type(source_address) is bytes:
source_address = socket.inet_ntoa(source_address) source_address = socket.inet_ntoa(source_address)
if metric_preference > ASSERT_CANCEL_METRIC: if metric_preference > 0x7FFFFFFF:
metric_preference = ASSERT_CANCEL_METRIC metric_preference = 0x7FFFFFFF
if metric > ASSERT_CANCEL_METRIC: if metric > ASSERT_CANCEL_METRIC:
metric = ASSERT_CANCEL_METRIC metric = ASSERT_CANCEL_METRIC
self.multicast_group_address = multicast_group_address self.multicast_group_address = multicast_group_address
...@@ -67,6 +67,6 @@ class PacketPimAssert: ...@@ -67,6 +67,6 @@ class PacketPimAssert:
data = data[source_addr_len:] data = data[source_addr_len:]
(metric_preference, metric) = struct.unpack(PacketPimAssert.PIM_HDR_ASSERT_WITHOUT_ADDRESS, data[:PacketPimAssert.PIM_HDR_ASSERT_WITHOUT_ADDRESS_LEN]) (metric_preference, metric) = struct.unpack(PacketPimAssert.PIM_HDR_ASSERT_WITHOUT_ADDRESS, data[:PacketPimAssert.PIM_HDR_ASSERT_WITHOUT_ADDRESS_LEN])
pim_payload = PacketPimAssert(multicast_group_addr_obj.group_address, source_addr_obj.unicast_address, metric_preference, metric) pim_payload = PacketPimAssert(multicast_group_addr_obj.group_address, source_addr_obj.unicast_address, 0x7FFFFFFF & metric_preference, metric)
return pim_payload return pim_payload
...@@ -81,6 +81,9 @@ class MyDaemon(Daemon): ...@@ -81,6 +81,9 @@ class MyDaemon(Daemon):
elif 'stop' in args and args.stop: elif 'stop' in args and args.stop:
Main.stop() Main.stop()
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
elif 'test' in args and args.test:
Main.test(args.test[0], args.test[1])
connection.shutdown(socket.SHUT_RDWR)
except Exception: except Exception:
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
traceback.print_exc() traceback.print_exc()
...@@ -107,6 +110,7 @@ if __name__ == "__main__": ...@@ -107,6 +110,7 @@ if __name__ == "__main__":
group.add_argument("-ri", "--remove_interface", nargs=1, metavar='INTERFACE_NAME', help="Remove PIM interface") group.add_argument("-ri", "--remove_interface", nargs=1, metavar='INTERFACE_NAME', help="Remove PIM interface")
group.add_argument("-riigmp", "--remove_interface_igmp", nargs=1, metavar='INTERFACE_NAME', help="Remove IGMP interface") group.add_argument("-riigmp", "--remove_interface_igmp", nargs=1, metavar='INTERFACE_NAME', help="Remove IGMP interface")
group.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose (print all debug messages)") group.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose (print all debug messages)")
group.add_argument("-t", "--test", nargs=2, metavar=('ROUTER_NAME', 'SERVER_LOG_IP'), help="Tester... send log information to SERVER_LOG_IP. Set the router name to ROUTER_NAME")
args = parser.parse_args() args = parser.parse_args()
print(parser.parse_args()) print(parser.parse_args())
......
import logging
class RootFilter(logging.Filter):
"""
This is a filter which injects contextual information into the log.
Rather than use actual contextual information, we just use random
data in this demo.
"""
def __init__(self, router_name, tree=''):
super().__init__()
self.router_name = router_name
def filter(self, record):
record.routername = self.router_name
if not hasattr(record, 'tree'):
record.tree = ''
if not hasattr(record, 'vif'):
record.vif = ''
return True
class NonRootFilter(logging.Filter):
"""
This is a filter which injects contextual information into the log.
Rather than use actual contextual information, we just use random
data in this demo.
"""
def __init__(self, tree):
super().__init__()
self.tree = tree
def filter(self, record):
record.tree = self.tree
return True
class InterfaceFilter(logging.Filter):
"""
This is a filter which injects contextual information into the log.
Rather than use actual contextual information, we just use random
data in this demo.
"""
def __init__(self, vif):
super().__init__()
self.vif = vif
def filter(self, record):
record.vif = self.vif
return True
from queue import Queue
from threading import Thread
from pyroute2 import IPDB, IPRoute from pyroute2 import IPDB, IPRoute
import socket import socket
import RWLock import RWLock
...@@ -23,17 +20,10 @@ class UnicastRouting(object): ...@@ -23,17 +20,10 @@ class UnicastRouting(object):
ipdb = None ipdb = None
def __init__(self): def __init__(self):
self.event_queue = Queue(maxsize=0)
UnicastRouting.ipr = IPRoute() UnicastRouting.ipr = IPRoute()
UnicastRouting.ipdb = IPDB() UnicastRouting.ipdb = IPDB()
self._ipdb = UnicastRouting.ipdb self._ipdb = UnicastRouting.ipdb
self._ipdb.register_callback(UnicastRouting.unicast_changes) self._ipdb.register_callback(UnicastRouting.unicast_changes)
#self.working = True
#self.worker_thread = Thread(target=self.worker)
#self.worker_thread.daemon = True
#self.worker_thread.start()
@staticmethod @staticmethod
...@@ -70,30 +60,6 @@ class UnicastRouting(object): ...@@ -70,30 +60,6 @@ class UnicastRouting(object):
entry_cost = 0 entry_cost = 0
return (entry_protocol, entry_cost, mask) return (entry_protocol, entry_cost, mask)
"""
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 # get output interface IP, used to send data to IP ip_dst
# (root interface IP to ip_dst) # (root interface IP to ip_dst)
...@@ -111,8 +77,6 @@ class UnicastRouting(object): ...@@ -111,8 +77,6 @@ class UnicastRouting(object):
@staticmethod @staticmethod
def unicast_changes(ipdb, msg, action): def unicast_changes(ipdb, msg, action):
#unicast_event = QueueItem(ipdb, msg, action)
#self.event_queue.put(unicast_event)
print("unicast change?") print("unicast change?")
print(action) print(action)
UnicastRouting.ipdb = ipdb UnicastRouting.ipdb = ipdb
...@@ -134,102 +98,16 @@ class UnicastRouting(object): ...@@ -134,102 +98,16 @@ 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))
#Main.kernel.notify_unicast_changes(subnet) Main.kernel.notify_unicast_changes(subnet)
elif action == "RTM_NEWADDR" or action == "RTM_DELADDR": elif action == "RTM_NEWADDR" or action == "RTM_DELADDR":
# TODO ALTERACOES NA INTERFACE
print("a") print("a")
'''
def worker(self):
global ipdb
while self.working:
item = self.event_queue.get()
ipdb = item.ipdb
if item.action == "RTM_NEWROUTE" or item.action == "RTM_DELROUTE":
mask_len = item.action["dst_len"]
network_address = None
attrs = item.action["attrs"]
for (key, value) in attrs:
if key == "RTA_DST":
network_address = value
break
subnet = ipaddress.ip_network(network_address + "/" + mask_len)
Main.kernel.notify_kernel_about_unicast_change(subnet)
elif item.action == "RTM_NEWADDR" or item.action == "RTM_DELADDR":
print("a")
'''
#print(ipdb)
#print(msg)
#print(action)
"""
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(self): def stop(self):
#self.working = False
if UnicastRouting.ipr: if UnicastRouting.ipr:
UnicastRouting.ipr.close() UnicastRouting.ipr.close()
if UnicastRouting.ipdb: if UnicastRouting.ipdb:
UnicastRouting.ipdb = None UnicastRouting.ipdb = None
if self._ipdb: if self._ipdb:
self._ipdb.release() self._ipdb.release()
#ip = input("ip=")
#get_metric(ip)
'''
class QueueItem(object):
def __init__(self, ipdb, msg, action):
self.ipdb = ipdb
self.msg = msg
self.action = action
'''
...@@ -8,7 +8,8 @@ ETH_P_IP = 0x0800 # Internet Protocol packet ...@@ -8,7 +8,8 @@ ETH_P_IP = 0x0800 # Internet Protocol packet
SO_RCVBUFFORCE = 33 SO_RCVBUFFORCE = 33
def get_s_g_bpf_filter_code(source, group, interface_name): def get_s_g_bpf_filter_code(source, group, interface_name):
cmd = "tcpdump -ddd \"(udp or icmp) and host %s and dst %s\"" % (source, group) #cmd = "tcpdump -ddd \"(udp or icmp) and host %s and dst %s\"" % (source, group)
cmd = "tcpdump -ddd \"(ip proto not 2) and host %s and dst %s\"" % (source, group)
result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
bpf_filter = b'' bpf_filter = b''
......
...@@ -8,13 +8,22 @@ from .tree_interface import TreeInterface ...@@ -8,13 +8,22 @@ from .tree_interface import TreeInterface
from threading import Timer, Lock, RLock from threading import Timer, Lock, RLock
from tree.metric import AssertMetric from tree.metric import AssertMetric
import UnicastRouting import UnicastRouting
from Packet.PacketPimStateRefresh import PacketPimStateRefresh from time import time
import Main
from TestLogger import NonRootFilter, logging
class KernelEntry: class KernelEntry:
TREE_TIMEOUT = 180 TREE_TIMEOUT = 180
def __init__(self, source_ip: str, group_ip: str, inbound_interface_index: int): def __init__(self, source_ip: str, group_ip: str, inbound_interface_index: int):
self.kernel_entry_logger = Main.logger.getChild('KernelEntry')
ch = logging.NullHandler()
ch.addFilter(NonRootFilter('(' + source_ip + ',' + group_ip + ')'))
self.kernel_entry_logger.addHandler(ch)
self.kernel_entry_logger.debug('Create KernelEntry')
self.source_ip = source_ip self.source_ip = source_ip
self.group_ip = group_ip self.group_ip = group_ip
...@@ -59,9 +68,9 @@ class KernelEntry: ...@@ -59,9 +68,9 @@ class KernelEntry:
self._multicast_change = Lock() self._multicast_change = Lock()
self._lock_test2 = RLock() self._lock_test2 = RLock()
self.CHANGE_STATE_LOCK = RLock() self.CHANGE_STATE_LOCK = RLock()
#self._was_olist_null = self.is_olist_null()
self.change() self.change()
self.evaluate_olist_change() self.evaluate_olist_change()
self.timestamp_of_last_state_refresh_message_received = 0
print('Tree created') print('Tree created')
#self._lock = threading.RLock() #self._lock = threading.RLock()
...@@ -138,7 +147,11 @@ class KernelEntry: ...@@ -138,7 +147,11 @@ class KernelEntry:
return return
if self.interface_state[iif].get_neighbor_RPF() != source_of_state_refresh: if self.interface_state[iif].get_neighbor_RPF() != source_of_state_refresh:
return return
# todo refresh limit # refresh limit
timestamp = time()
if (timestamp - self.timestamp_of_last_state_refresh_message_received) < interval:
return
self.timestamp_of_last_state_refresh_message_received = timestamp
if ttl == 0: if ttl == 0:
return return
...@@ -157,10 +170,8 @@ class KernelEntry: ...@@ -157,10 +170,8 @@ class KernelEntry:
# Unicast Changes to RPF # Unicast Changes to RPF
############################################################### ###############################################################
def network_update(self): def network_update(self):
# 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"]
#rpf_node = self.source_ip if next_hop is None else next_hop
next_hop = UnicastRouting.get_route(self.source_ip)["gateway"] next_hop = UnicastRouting.get_route(self.source_ip)["gateway"]
multipaths = UnicastRouting.get_route(self.source_ip)["multipath"] multipaths = UnicastRouting.get_route(self.source_ip)["multipath"]
...@@ -179,20 +190,35 @@ class KernelEntry: ...@@ -179,20 +190,35 @@ class KernelEntry:
print(self.rpf_node == self.source_ip) print(self.rpf_node == self.source_ip)
new_inbound_interface_index = Main.kernel.vif_dic[self.check_rpf()] new_inbound_interface_index = Main.kernel.vif_dic.get(self.check_rpf(), None)
if new_inbound_interface_index is None:
self.delete()
return
if new_inbound_interface_index != self.inbound_interface_index: if new_inbound_interface_index != self.inbound_interface_index:
# todo: criar novo upstream e downstream interface self.rpf_node = rpf_node
# todo: stop upstream e downstream
#self.interface_state[self.inbound_interface_index].stop() # get old interfaces
#self.interface_state[new_inbound_interface_index].stop() old_upstream_interface = self.interface_state[self.inbound_interface_index]
#Unicast routing or Assert state causes RPF'(S) to change, old_downstream_interface = self.interface_state[new_inbound_interface_index]
self.interface_state[self.inbound_interface_index] = TreeInterfaceDownstream
self.interface_state[new_inbound_interface_index] = TreeInterfaceUpstream # 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, False)
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
if self.rpf_node != rpf_node: # remove old interfaces
old_upstream_interface.delete(change_type_interface=True)
old_downstream_interface.delete(change_type_interface=True)
# atualizar tabela de encaminhamento multicast
self._was_olist_null = False
self.change()
self.evaluate_olist_change()
elif self.rpf_node != rpf_node:
self.rpf_node = rpf_node self.rpf_node = rpf_node
self.interface_state[self.inbound_interface_index].change_rpf(self._was_olist_null) self.interface_state[self.inbound_interface_index].change_on_unicast_routing()
# check if add/removal of neighbors from interface afects olist and forward/prune state of interface # check if add/removal of neighbors from interface afects olist and forward/prune state of interface
...@@ -231,10 +257,11 @@ class KernelEntry: ...@@ -231,10 +257,11 @@ class KernelEntry:
Main.kernel.set_multicast_route(self) Main.kernel.set_multicast_route(self)
def delete(self): def delete(self):
for state in self.interface_state.values(): with self._multicast_change:
state.delete() for state in self.interface_state.values():
state.delete()
Main.kernel.remove_multicast_route(self) Main.kernel.remove_multicast_route(self)
###################################### ######################################
...@@ -252,7 +279,6 @@ class KernelEntry: ...@@ -252,7 +279,6 @@ class KernelEntry:
if self.inbound_interface_index == index: if self.inbound_interface_index == index:
self.delete() self.delete()
else: else:
self.interface_state[index].delete() self.interface_state.pop(index).delete()
del self.interface_state[index]
self.change() self.change()
self.evaluate_olist_change() self.evaluate_olist_change()
...@@ -107,18 +107,10 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -107,18 +107,10 @@ class AssertStateABC(metaclass=ABCMeta):
interface.set_assert_timer(pim_globals.ASSERT_TIME) interface.set_assert_timer(pim_globals.ASSERT_TIME)
interface.send_assert() interface.send_assert()
@staticmethod
def rprint(interface: "TreeInterfaceDownstream", msg, *entrys):
'''
Method used for simplifiyng the process of reporting changes in a assert state
Tree Interface.
@type interface: TreeInterface
'''
print(msg, 'assert state', *entrys)
# Override # Override
def __str__(self) -> str: def __str__(self) -> str:
return "PruneSM:" + self.__class__.__name__ return "AssertSM:" + self.__class__.__name__
class NoInfoState(AssertStateABC): class NoInfoState(AssertStateABC):
...@@ -137,7 +129,8 @@ class NoInfoState(AssertStateABC): ...@@ -137,7 +129,8 @@ class NoInfoState(AssertStateABC):
NoInfoState._sendAssert_setAT(interface) NoInfoState._sendAssert_setAT(interface)
print('receivedDataFromDownstreamIf, NI -> W') #print('receivedDataFromDownstreamIf, NI -> W')
interface.assert_logger.debug('receivedDataFromDownstreamIf, NI -> W')
@staticmethod @staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
...@@ -150,8 +143,8 @@ class NoInfoState(AssertStateABC): ...@@ -150,8 +143,8 @@ class NoInfoState(AssertStateABC):
NoInfoState._sendAssert_setAT(interface) NoInfoState._sendAssert_setAT(interface)
print( #print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W') interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
@staticmethod @staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
...@@ -174,7 +167,8 @@ class NoInfoState(AssertStateABC): ...@@ -174,7 +167,8 @@ class NoInfoState(AssertStateABC):
if interface.could_assert(): if interface.could_assert():
interface.send_prune(holdtime=assert_timer_value) interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, NI -> L') #print('receivedPreferedMetric, NI -> L')
interface.assert_logger.debug('receivedPreferedMetric, NI -> L')
@staticmethod @staticmethod
def sendStateRefresh(interface: "TreeInterfaceDownstream", time): def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
...@@ -186,11 +180,13 @@ class NoInfoState(AssertStateABC): ...@@ -186,11 +180,13 @@ class NoInfoState(AssertStateABC):
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
print('couldAssertIsNowFalse, NI -> NI') #print('couldAssertIsNowFalse, NI -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, NI -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
print('couldAssertIsNowTrue, NI -> NI') #print('couldAssertIsNowTrue, NI -> NI')
interface.assert_logger.debug('couldAssertIsNowTrue, NI -> NI')
@staticmethod @staticmethod
def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"): def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
...@@ -198,7 +194,11 @@ class NoInfoState(AssertStateABC): ...@@ -198,7 +194,11 @@ class NoInfoState(AssertStateABC):
@staticmethod @staticmethod
def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
print('receivedPruneOrJoinOrGraft, NI -> NI') #print('receivedPruneOrJoinOrGraft, NI -> NI')
interface.assert_logger.debug('receivedPruneOrJoinOrGraft, NI -> NI')
def __str__(self) -> str:
return "NI"
class WinnerState(AssertStateABC): class WinnerState(AssertStateABC):
...@@ -216,7 +216,8 @@ class WinnerState(AssertStateABC): ...@@ -216,7 +216,8 @@ class WinnerState(AssertStateABC):
""" """
WinnerState._sendAssert_setAT(interface) WinnerState._sendAssert_setAT(interface)
print('receivedDataFromDownstreamIf, W -> W') #print('receivedDataFromDownstreamIf, W -> W')
interface.assert_logger.debug('receivedDataFromDownstreamIf, W -> W')
@staticmethod @staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
...@@ -226,8 +227,8 @@ class WinnerState(AssertStateABC): ...@@ -226,8 +227,8 @@ class WinnerState(AssertStateABC):
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"): def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
WinnerState._sendAssert_setAT(interface) WinnerState._sendAssert_setAT(interface)
print( #print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W') interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
@staticmethod @staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
...@@ -247,7 +248,8 @@ class WinnerState(AssertStateABC): ...@@ -247,7 +248,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_state(AssertState.Loser) interface.set_assert_state(AssertState.Loser)
interface.send_prune(holdtime=assert_timer_value) interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, W -> L') #print('receivedPreferedMetric, W -> L')
interface.assert_logger.debug('receivedPreferedMetric, W -> L')
@staticmethod @staticmethod
def sendStateRefresh(interface: "TreeInterfaceDownstream", state_refresh_interval): def sendStateRefresh(interface: "TreeInterfaceDownstream", state_refresh_interval):
...@@ -258,7 +260,8 @@ class WinnerState(AssertStateABC): ...@@ -258,7 +260,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric()) interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo) interface.set_assert_state(AssertState.NoInfo)
print('assertTimerExpires, W -> NI') #print('assertTimerExpires, W -> NI')
interface.assert_logger.debug('assertTimerExpires, W -> NI')
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
...@@ -269,7 +272,8 @@ class WinnerState(AssertStateABC): ...@@ -269,7 +272,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric()) interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo) interface.set_assert_state(AssertState.NoInfo)
print('couldAssertIsNowFalse, W -> NI') #print('couldAssertIsNowFalse, W -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, W -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
...@@ -283,6 +287,10 @@ class WinnerState(AssertStateABC): ...@@ -283,6 +287,10 @@ class WinnerState(AssertStateABC):
def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
pass pass
def __str__(self) -> str:
return "W"
class LoserState(AssertStateABC): class LoserState(AssertStateABC):
''' '''
...@@ -296,18 +304,20 @@ class LoserState(AssertStateABC): ...@@ -296,18 +304,20 @@ class LoserState(AssertStateABC):
""" """
@type interface: TreeInterface @type interface: TreeInterface
""" """
print('receivedDataFromDownstreamIf, L -> L') #print('receivedDataFromDownstreamIf, L -> L')
interface.assert_logger.debug('receivedDataFromDownstreamIf, L -> L')
@staticmethod @staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) LoserState._to_NoInfo(interface)
print('receivedInferiorMetricFromWinner, L -> NI') #print('receivedInferiorMetricFromWinner, L -> NI')
interface.assert_logger.debug('receivedInferiorMetricFromWinner, L -> NI')
@staticmethod @staticmethod
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"): def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
print( #print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L') interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
@staticmethod @staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
...@@ -322,12 +332,13 @@ class LoserState(AssertStateABC): ...@@ -322,12 +332,13 @@ class LoserState(AssertStateABC):
interface.set_assert_timer(assert_timer_value) interface.set_assert_timer(assert_timer_value)
interface.set_assert_winner_metric(better_metric) interface.set_assert_winner_metric(better_metric)
interface.set_assert_state(AssertState.Loser)
if interface.could_assert(): if interface.could_assert():
# todo enviar holdtime = assert_timer_value???!
interface.send_prune(holdtime=assert_timer_value) interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, L -> L') #print('receivedPreferedMetric, L -> L')
interface.assert_logger.debug('receivedPreferedMetric, L -> L')
@staticmethod @staticmethod
def sendStateRefresh(interface: "TreeInterfaceDownstream", time): def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
...@@ -336,29 +347,34 @@ class LoserState(AssertStateABC): ...@@ -336,29 +347,34 @@ class LoserState(AssertStateABC):
@staticmethod @staticmethod
def assertTimerExpires(interface: "TreeInterfaceDownstream"): def assertTimerExpires(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) LoserState._to_NoInfo(interface)
print('assertTimerExpires, L -> NI') #print('assertTimerExpires, L -> NI')
interface.assert_logger.debug('assertTimerExpires, L -> NI')
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) LoserState._to_NoInfo(interface)
print('couldAssertIsNowFalse, L -> NI') #print('couldAssertIsNowFalse, L -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, L -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) LoserState._to_NoInfo(interface)
print('couldAssertIsNowTrue, L -> NI') #print('couldAssertIsNowTrue, L -> NI')
interface.assert_logger.debug('couldAssertIsNowTrue, L -> NI')
@staticmethod @staticmethod
def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"): def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) LoserState._to_NoInfo(interface)
print('winnerLivelinessTimerExpires, L -> NI') #print('winnerLivelinessTimerExpires, L -> NI')
interface.assert_logger.debug('winnerLivelinessTimerExpires, L -> NI')
@staticmethod @staticmethod
def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
interface.send_assert() interface.send_assert()
print('receivedPruneOrJoinOrGraft, L -> L') #print('receivedPruneOrJoinOrGraft, L -> L')
interface.assert_logger.debug('receivedPruneOrJoinOrGraft, L -> L')
@staticmethod @staticmethod
def _to_NoInfo(interface: "TreeInterfaceDownstream"): def _to_NoInfo(interface: "TreeInterfaceDownstream"):
...@@ -366,6 +382,8 @@ class LoserState(AssertStateABC): ...@@ -366,6 +382,8 @@ class LoserState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric()) interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo) interface.set_assert_state(AssertState.NoInfo)
def __str__(self) -> str:
return "L"
class AssertState(): class AssertState():
NoInfo = NoInfoState() NoInfo = NoInfoState()
......
...@@ -353,7 +353,8 @@ class Pruned(DownstreamStateABS): ...@@ -353,7 +353,8 @@ class Pruned(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream @type interface: TreeInterfaceDownstreamDownstream
""" """
interface.set_prune_timer(interface.get_received_prune_holdtime()) if interface.get_interface().is_state_refresh_capable():
interface.set_prune_timer(interface.get_received_prune_holdtime())
print('send_state_refresh, P -> P') print('send_state_refresh, P -> P')
......
import ipaddress import ipaddress
class AssertMetric(object):
'''
Note: we consider the node name the ip of the metric.
'''
def __init__(self, metric_preference: int or float = float("Inf"), route_metric: int or float = float("Inf"), ip_address: str = "0.0.0.0", state_refresh_interval:int = None): class AssertMetric(object):
def __init__(self, metric_preference: int = 0x7FFFFFFF, route_metric: int = 0xFFFFFFFF, ip_address: str = "0.0.0.0", state_refresh_interval:int = None):
if type(ip_address) is str: if type(ip_address) is str:
ip_address = ipaddress.ip_address(ip_address) ip_address = ipaddress.ip_address(ip_address)
...@@ -30,7 +27,7 @@ class AssertMetric(object): ...@@ -30,7 +27,7 @@ class AssertMetric(object):
''' '''
@type metric: AssertMetric @type metric: AssertMetric
''' '''
return AssertMetric(metric_preference=float("Inf"), route_metric=float("Inf"), ip_address="0.0.0.0") return AssertMetric()
@staticmethod @staticmethod
def spt_assert_metric(tree_if): def spt_assert_metric(tree_if):
......
...@@ -3,29 +3,22 @@ Created on Jul 16, 2015 ...@@ -3,29 +3,22 @@ Created on Jul 16, 2015
@author: alex @author: alex
''' '''
#from convergence import Convergence
#from des.event.timer import Timer
from threading import Timer from threading import Timer
from CustomTimer.RemainingTimer import RemainingTimer from CustomTimer.RemainingTimer import RemainingTimer
from .assert_ import AssertState, AssertStateABC from .assert_ import AssertState, AssertStateABC
#from .messages.assert_msg import SFMRAssertMsg
#from .messages.reset import SFMResetMsg
from .metric import AssertMetric
from .downstream_prune import DownstreamState, DownstreamStateABS from .downstream_prune import DownstreamState, DownstreamStateABS
from .tree_interface import TreeInterface from .tree_interface import TreeInterface
from Packet.ReceivedPacket import ReceivedPacket
from threading import Lock
from Packet.PacketPimStateRefresh import PacketPimStateRefresh from Packet.PacketPimStateRefresh import PacketPimStateRefresh
from Packet.Packet import Packet from Packet.Packet import Packet
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
import traceback import traceback
class TreeInterfaceDownstream(TreeInterface): class TreeInterfaceDownstream(TreeInterface):
def __init__(self, kernel_entry, interface_id): def __init__(self, kernel_entry, interface_id):
TreeInterface.__init__(self, kernel_entry, interface_id) logger = kernel_entry.kernel_entry_logger.getChild('DownstreamInterface')
TreeInterface.__init__(self, kernel_entry, interface_id, logger)
self.logger.debug('Created DownstreamInterface')
########################################## ##########################################
...@@ -177,8 +170,8 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -177,8 +170,8 @@ class TreeInterfaceDownstream(TreeInterface):
return return
# Override # Override
def delete(self): def delete(self, change_type_interface=False):
TreeInterface.delete(self) super().delete(change_type_interface)
self.clear_assert_timer() self.clear_assert_timer()
self.clear_prune_timer() self.clear_prune_timer()
self.clear_prune_pending_timer() self.clear_prune_pending_timer()
......
...@@ -18,12 +18,15 @@ import threading ...@@ -18,12 +18,15 @@ import threading
class TreeInterfaceUpstream(TreeInterface): class TreeInterfaceUpstream(TreeInterface):
def __init__(self, kernel_entry, interface_id, is_originater: bool): def __init__(self, kernel_entry, interface_id, is_originater: bool):
TreeInterface.__init__(self, kernel_entry, interface_id) logger = kernel_entry.kernel_entry_logger.getChild('UpstreamInterface')
TreeInterface.__init__(self, kernel_entry, interface_id, logger)
# Graft/Prune State: # Graft/Prune State:
self._graft_prune_state = UpstreamState.Forward self._graft_prune_state = UpstreamState.Forward
self._graft_retry_timer = None self._graft_retry_timer = None
self._override_timer = None self._override_timer = None
self._prune_limit_timer = None self._prune_limit_timer = None
self._last_rpf = self.get_neighbor_RPF()
# Originator state # Originator state
self._originator_state = OriginatorState.NotOriginator self._originator_state = OriginatorState.NotOriginator
...@@ -48,6 +51,8 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -48,6 +51,8 @@ class TreeInterfaceUpstream(TreeInterface):
receive_thread.daemon = True receive_thread.daemon = True
receive_thread.start() receive_thread.start()
self.logger.debug('Created UpstreamInterface')
def socket_recv(self): def socket_recv(self):
while self.socket_is_enabled: while self.socket_is_enabled:
...@@ -216,24 +221,41 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -216,24 +221,41 @@ class TreeInterfaceUpstream(TreeInterface):
def olist_is_not_null(self): def olist_is_not_null(self):
self._graft_prune_state.olistIsNowNotNull(self) self._graft_prune_state.olistIsNowNotNull(self)
########################################### ###########################################
# Changes on Unicast Routing Table # Changes to RPF'(s)
########################################### ###########################################
# caused by assert transition:
def set_assert_state(self, new_state):
super().set_assert_state(new_state)
self.change_rpf(self.is_olist_null())
# caused by unicast routing table:
def change_on_unicast_routing(self):
self.change_rpf(self.is_olist_null())
def change_rpf(self, olist_is_null): def change_rpf(self, olist_is_null):
if olist_is_null: current_rpf = self.get_neighbor_RPF()
self._graft_prune_state.RPFnbrChanges_olistIsNull() if self._last_rpf != current_rpf:
else: self._last_rpf = current_rpf
self._graft_prune_state.RPFnbrChanges_olistIsNotNull() if olist_is_null:
self._graft_prune_state.RPFnbrChanges_olistIsNull(self)
else:
self._graft_prune_state.RPFnbrChanges_olistIsNotNull(self)
####################################################################
#Override #Override
def is_forwarding(self): def is_forwarding(self):
return False return False
#Override #Override
def delete(self): def delete(self, change_type_interface=False):
super().delete()
self.socket_is_enabled = False self.socket_is_enabled = False
self.socket_pkt.close() self.socket_pkt.close()
super().delete(change_type_interface)
self.clear_graft_retry_timer() self.clear_graft_retry_timer()
self.clear_assert_timer() self.clear_assert_timer()
self.clear_prune_limit_timer() self.clear_prune_limit_timer()
...@@ -241,6 +263,12 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -241,6 +263,12 @@ class TreeInterfaceUpstream(TreeInterface):
self.clear_state_refresh_timer() self.clear_state_refresh_timer()
self.clear_source_active_timer() self.clear_source_active_timer()
# Clear Graft/Prune State:
self._graft_prune_state = None
# Clear Originator state
self._originator_state = None
def is_downstream(self): def is_downstream(self):
return False return False
......
...@@ -8,9 +8,6 @@ import Main ...@@ -8,9 +8,6 @@ import Main
from threading import Lock, RLock from threading import Lock, RLock
import traceback import traceback
#from convergence import Convergence
#from sfmr.messages.prune import SFMRPruneMsg
#from .router_interface import SFMRInterface
from .downstream_prune import DownstreamState from .downstream_prune import DownstreamState
from .assert_ import AssertState, AssertStateABC from .assert_ import AssertState, AssertStateABC
...@@ -27,11 +24,18 @@ from .metric import AssertMetric ...@@ -27,11 +24,18 @@ from .metric import AssertMetric
from threading import Timer from threading import Timer
from .local_membership import LocalMembership from .local_membership import LocalMembership
from .globals import * from .globals import *
from TestLogger import InterfaceFilter, logging
class TreeInterface(metaclass=ABCMeta): class TreeInterface(metaclass=ABCMeta):
def __init__(self, kernel_entry, interface_id): def __init__(self, kernel_entry, interface_id, logger):
self._kernel_entry = kernel_entry self._kernel_entry = kernel_entry
self._interface_id = interface_id self._interface_id = interface_id
self.logger = logger
ch = logging.NullHandler()
ch.addFilter(InterfaceFilter(interface_id))
self.logger.addHandler(ch)
self.assert_logger = logger.getChild('Assert')
self.join_prune_logger = logger.getChild('JoinPrune')
# Local Membership State # Local Membership State
try: try:
...@@ -60,7 +64,6 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -60,7 +64,6 @@ class TreeInterface(metaclass=ABCMeta):
self._igmp_lock = RLock() self._igmp_lock = RLock()
#self.rprint('new ' + self.__class__.__name__)
############################################ ############################################
# Set ASSERT State # Set ASSERT State
...@@ -69,6 +72,7 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -69,6 +72,7 @@ class TreeInterface(metaclass=ABCMeta):
with self.get_state_lock(): with self.get_state_lock():
if new_state != self._assert_state: if new_state != self._assert_state:
self._assert_state = new_state self._assert_state = new_state
self.assert_logger.debug(str(new_state))
self.change_tree() self.change_tree()
self.evaluate_ingroup() self.evaluate_ingroup()
...@@ -243,7 +247,7 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -243,7 +247,7 @@ class TreeInterface(metaclass=ABCMeta):
try: try:
(source, group) = self.get_tree_id() (source, group) = self.get_tree_id()
ph = PacketPimAssert(multicast_group_address=group, source_address=source, metric_preference=1, metric=float("Inf")) ph = PacketPimAssert(multicast_group_address=group, source_address=source, metric_preference=float("Inf"), metric=float("Inf"))
pckt = Packet(payload=PacketPimHeader(ph)) pckt = Packet(payload=PacketPimHeader(ph))
self.get_interface().send(pckt.bytes()) self.get_interface().send(pckt.bytes())
...@@ -276,7 +280,32 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -276,7 +280,32 @@ class TreeInterface(metaclass=ABCMeta):
pass pass
@abstractmethod @abstractmethod
def delete(self): def delete(self, change_type_interface=False):
if change_type_interface:
if self.could_assert():
self._assert_state.couldAssertIsNowFalse(self)
else:
self._assert_state.couldAssertIsNowTrue(self)
(s, g) = self.get_tree_id()
# unsubscribe igmp information
try:
interface_name = Main.kernel.vif_index_to_name_dic[self._interface_id]
igmp_interface = Main.igmp_interfaces[interface_name] # type: InterfaceIGMP
group_state = igmp_interface.interface_state.get_group_state(g)
group_state.remove_multicast_routing_entry(self)
except:
pass
# Prune State
self._prune_state = None
# Assert State
self._assert_state = None
self.set_assert_winner_metric(AssertMetric.infinite_assert_metric()) # unsubscribe from current AssertWinner NeighborLivenessTimer
self._assert_winner_metric = None
self.clear_assert_timer()
print('Tree Interface deleted') print('Tree Interface deleted')
def is_olist_null(self): def is_olist_null(self):
...@@ -293,7 +322,6 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -293,7 +322,6 @@ class TreeInterface(metaclass=ABCMeta):
with self.get_state_lock(): with self.get_state_lock():
with self._igmp_lock: with self._igmp_lock:
if has_members != self._local_membership_state.has_members(): if has_members != self._local_membership_state.has_members():
#self._igmp_has_members = has_members
self._local_membership_state = LocalMembership.Include if has_members else LocalMembership.NoInfo self._local_membership_state = LocalMembership.Include if has_members else LocalMembership.NoInfo
self.change_tree() self.change_tree()
self.evaluate_ingroup() self.evaluate_ingroup()
...@@ -301,12 +329,8 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -301,12 +329,8 @@ class TreeInterface(metaclass=ABCMeta):
def igmp_has_members(self): def igmp_has_members(self):
with self._igmp_lock: with self._igmp_lock:
#return self._igmp_has_members
return self._local_membership_state.has_members() return self._local_membership_state.has_members()
def rprint(self, msg, *entrys):
return
def __str__(self): def __str__(self):
return '{}<{}>'.format(self.__class__, self._interface.get_link()) return '{}<{}>'.format(self.__class__, self._interface.get_link())
......
...@@ -265,10 +265,7 @@ class Forward(UpstreamStateABC): ...@@ -265,10 +265,7 @@ class Forward(UpstreamStateABC):
""" """
if not interface.is_S_directly_conn(): if not interface.is_S_directly_conn():
interface.send_graft() interface.send_graft()
#interface.get_grt().start()
interface.set_graft_retry_timer() interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending) interface.set_state(UpstreamState.AckPending)
print('RPFnbrChanges_olistIsNotNull, F -> AP') print('RPFnbrChanges_olistIsNotNull, F -> AP')
...@@ -344,10 +341,8 @@ class Pruned(UpstreamStateABC): ...@@ -344,10 +341,8 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_plt().reset()
interface.set_prune_limit_timer() interface.set_prune_limit_timer()
print('stateRefreshArrivesRPFnbr_pruneIs1, P -> P')
interface.rprint('stateRefreshArrivesRPFnbr_pruneIs1, P -> P')
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -358,12 +353,6 @@ class Pruned(UpstreamStateABC): ...@@ -358,12 +353,6 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
# todo: desnecessario pq PLT stopped????!!!
#plt = interface.get_plt()
#if not plt.is_ticking():
# plt.start()
# interface.send_prune()
interface.send_prune() interface.send_prune()
interface.set_prune_limit_timer() interface.set_prune_limit_timer()
print( print(
...@@ -438,12 +427,12 @@ class Pruned(UpstreamStateABC): ...@@ -438,12 +427,12 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
if not interface.is_S_directly_conn(): if not interface.is_S_directly_conn():
interface.send_graft() interface.set_state(UpstreamState.AckPending)
#interface.get_grt().start() interface.clear_prune_limit_timer()
interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending) interface.send_graft()
interface.set_graft_retry_timer()
print('olistIsNowNotNull, P -> AP') print('olistIsNowNotNull, P -> AP')
...@@ -455,7 +444,6 @@ class Pruned(UpstreamStateABC): ...@@ -455,7 +444,6 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_plt().stop()
if not interface.is_S_directly_conn(): if not interface.is_S_directly_conn():
interface.clear_prune_limit_timer() interface.clear_prune_limit_timer()
...@@ -522,7 +510,6 @@ class AckPending(UpstreamStateABC): ...@@ -522,7 +510,6 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.set_ot()
interface.set_override_timer() interface.set_override_timer()
print('stateRefreshArrivesRPFnbr_pruneIs1, AP -> AP') print('stateRefreshArrivesRPFnbr_pruneIs1, AP -> AP')
...@@ -536,9 +523,7 @@ class AckPending(UpstreamStateABC): ...@@ -536,9 +523,7 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Forward) interface.set_state(UpstreamState.Forward)
#interface.get_grt().cancel()
interface.clear_graft_retry_timer() interface.clear_graft_retry_timer()
print( print(
...@@ -551,8 +536,6 @@ class AckPending(UpstreamStateABC): ...@@ -551,8 +536,6 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.cancel_ot()
interface.clear_override_timer() interface.clear_override_timer()
print('seeJoinToRPFnbr, AP -> AP') print('seeJoinToRPFnbr, AP -> AP')
...@@ -564,11 +547,9 @@ class AckPending(UpstreamStateABC): ...@@ -564,11 +547,9 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.set_ot()
interface.set_override_timer() interface.set_override_timer()
interface.rprint('seePrune, AP -> AP') print('seePrune, AP -> AP')
@staticmethod @staticmethod
def OTexpires(interface: "TreeInterfaceUpstream"): def OTexpires(interface: "TreeInterfaceUpstream"):
...@@ -579,7 +560,7 @@ class AckPending(UpstreamStateABC): ...@@ -579,7 +560,7 @@ class AckPending(UpstreamStateABC):
""" """
interface.send_join() interface.send_join()
interface.rprint('OTexpires, AP -> AP') print('OTexpires, AP -> AP')
@staticmethod @staticmethod
def olistIsNowNull(interface: "TreeInterfaceUpstream"): def olistIsNowNull(interface: "TreeInterfaceUpstream"):
...@@ -624,8 +605,6 @@ class AckPending(UpstreamStateABC): ...@@ -624,8 +605,6 @@ class AckPending(UpstreamStateABC):
""" """
if not interface.is_S_directly_conn(): if not interface.is_S_directly_conn():
interface.send_graft() interface.send_graft()
#interface.get_grt().reset()
interface.set_graft_retry_timer() interface.set_graft_retry_timer()
print('olistIsNowNotNull, AP -> AP') print('olistIsNowNotNull, AP -> AP')
...@@ -638,9 +617,9 @@ class AckPending(UpstreamStateABC): ...@@ -638,9 +617,9 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_grt().cancel()
if not interface.is_S_directly_conn(): if not interface.is_S_directly_conn():
interface.clear_graft_retry_timer() interface.clear_graft_retry_timer()
interface.set_state(UpstreamState.Pruned)
print('RPFnbrChanges_olistIsNull, AP -> P') print('RPFnbrChanges_olistIsNull, AP -> P')
......
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