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):
# set receive socket and send socket
self._send_socket = send_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
receive_thread = threading.Thread(target=self.receive)
receive_thread.daemon = True
......
......@@ -6,7 +6,7 @@ from Interface import Interface
from ctypes import create_string_buffer, addressof
from ipaddress import IPv4Address
from utils import Version_1_Membership_Report, Version_2_Membership_Report, Leave_Group, Membership_Query
import subprocess
if not hasattr(socket, 'SO_BINDTODEVICE'):
socket.SO_BINDTODEVICE = 25
......@@ -15,6 +15,7 @@ class InterfaceIGMP(Interface):
ETH_P_IP = 0x0800 # Internet Protocol packet
SO_ATTACH_FILTER = 26
# TODO filtro nao esta a funcionar bem no netkit
FILTER_IGMP = [
struct.pack('HBBI', 0x28, 0, 0, 0x0000000c),
struct.pack('HBBI', 0x15, 0, 3, 0x00000800),
......@@ -25,31 +26,36 @@ class InterfaceIGMP(Interface):
]
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
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
filters = b''.join(InterfaceIGMP.FILTER_IGMP)
b = create_string_buffer(filters)
# TODO filtro nao esta a funcionar bem no netkit
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)
fprog = struct.pack('HL', len(InterfaceIGMP.FILTER_IGMP), mem_addr_of_filters)
rcv_s.setsockopt(socket.SOL_SOCKET, InterfaceIGMP.SO_ATTACH_FILTER, fprog)
# bind to interface
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)
from igmp.RouterState import RouterState
self.interface_state = RouterState(self)
super()._enable()
def get_ip(self):
......
......@@ -13,6 +13,8 @@ from threading import Timer
from tree.globals import REFRESH_INTERVAL
import socket
import netifaces
class InterfacePim(Interface):
MCAST_GRP = '224.0.0.13'
PROPAGATION_DELAY = 0.5
......@@ -23,9 +25,34 @@ class InterfacePim(Interface):
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']
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)
......@@ -49,36 +76,10 @@ class InterfacePim(Interface):
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
super().__init__(interface_name, s, s, vif_index)
# 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
super()._enable()
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):
return self.ip_interface
......@@ -144,7 +145,7 @@ class InterfacePim(Interface):
self._had_neighbors = has_neighbors
Main.kernel.interface_change_number_of_neighbors()
'''
def add_neighbor(self, ip, random_number, hello_hold_time):
with self.neighbors_lock.genWlock():
if ip not in self.neighbors:
......@@ -153,6 +154,7 @@ class InterfacePim(Interface):
self.neighbors[ip] = Neighbor(self, ip, random_number, hello_hold_time)
self.force_send_hello()
self.check_number_of_neighbors()
'''
def get_neighbors(self):
with self.neighbors_lock.genRlock():
......@@ -171,6 +173,19 @@ class InterfacePim(Interface):
def is_state_refresh_enabled(self):
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
......
import socket
import struct
import netifaces
import threading
from threading import Lock
import traceback
import ipaddress
......@@ -56,7 +56,7 @@ class Kernel:
self.vif_index_to_name_dic = {}
self.vif_name_to_index_dic = {}
# KEY : (source_ip, group_ip), VALUE : KernelEntry ???? TODO
# KEY : source_ip, VALUE : {group_ip: KernelEntry}
self.routing = {}
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
......@@ -76,24 +76,14 @@ class Kernel:
# todo useless in PIM-DM... useful in PIM-SM
#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.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
handler_thread = threading.Thread(target=self.handler)
handler_thread.daemon = True
......@@ -152,9 +142,11 @@ class Kernel:
self.vif_name_to_index_dic[interface_name] = index
with self.rwlock.genWlock():
for kernel_entry in list(self.routing.values()):
for source_dict in list(self.routing.values()):
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
......@@ -273,13 +265,15 @@ class Kernel:
del self.vif_dic[ip_interface]
del self.vif_name_to_index_dic[self.vif_index_to_name_dic[index]]
del self.vif_index_to_name_dic[index]
# TODO alterar MFC's para colocar a 0 esta interface
interface_name = self.vif_index_to_name_dic.pop(index)
# alterar MFC's para colocar a 0 esta interface
with self.rwlock.genWlock():
for kernel_entry in list(self.routing.values()):
for source_dict in list(self.routing.values()):
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:
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)
# 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):
source_ip = socket.inet_aton(kernel_entry.source_ip)
......@@ -326,9 +317,10 @@ class Kernel:
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)
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):
self.running = False
......@@ -389,39 +381,12 @@ class Kernel:
# receive multicast (S,G) packet and multicast routing table has no (S,G) entry
def igmpmsg_nocache_handler(self, ip_src, ip_dst, iif):
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)
# receive multicast (S,G) packet in a outbound_interface
def igmpmsg_wrongvif_handler(self, ip_src, ip_dst, iif):
#kernel_entry = self.routing[(ip_src, ip_dst)]
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)
''' useless in PIM-DM... useful in PIM-SM
......@@ -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):
ip_src = source_group[0]
ip_dst = source_group[1]
with self.rwlock.genRlock():
if source_group in self.routing:
return self.routing[(ip_src, ip_dst)]
if ip_src in self.routing and ip_dst in self.routing[ip_src]:
return self.routing[ip_src][ip_dst]
with self.rwlock.genWlock():
if source_group in self.routing:
return self.routing[(ip_src, ip_dst)]
if ip_src in self.routing and ip_dst in self.routing[ip_src]:
return self.routing[ip_src][ip_dst]
elif create_if_not_existent:
kernel_entry = KernelEntry(ip_src, ip_dst, 0)
self.routing[source_group] = kernel_entry
kernel_entry.change()
#self.set_multicast_route(kernel_entry)
if ip_src not in self.routing:
self.routing[ip_src] = {}
self.routing[ip_src][ip_dst] = kernel_entry
return kernel_entry
else:
return None
# notify KernelEntries about changes at the unicast routing table
def notify_unicast_changes(self, subnet):
# todo
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)
if source_ip_obj in subnet:
self.routing[(source_ip, group)].network_update()
print(source_ip)
if source_ip_obj not in subnet:
continue
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
def interface_change_number_of_neighbors(self):
with self.rwlock.genWlock():
for entry in self.routing.values():
for groups_dict in self.routing.values():
for entry in groups_dict.values():
entry.change_at_number_of_neighbors()
......@@ -2,17 +2,17 @@ import netifaces
import time
from prettytable import PrettyTable
from InterfacePIM import InterfacePim
from InterfaceIGMP import InterfaceIGMP
#from InterfacePIM import InterfacePim
#from InterfaceIGMP import InterfaceIGMP
from Kernel import Kernel
from threading import Lock
#from threading import Lock
import UnicastRouting
interfaces = {} # interfaces with multicast routing enabled
igmp_interfaces = {} # igmp interfaces
kernel = None
igmp = None
unicast_routing = None
logger = None
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)
......@@ -119,7 +119,10 @@ def list_igmp_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()
t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"])
......@@ -133,17 +136,17 @@ def list_routing_state():
interface_name = kernel.vif_index_to_name_dic[index]
local_membership = type(interface_state._local_membership_state).__name__
try:
assert_state = type(interface_state._assert_state).__name__
if index != upstream_if_index:
prune_state = type(interface_state._prune_state).__name__
assert_state = type(interface_state._assert_state).__name__
is_forwarding = interface_state.is_forwarding()
else:
prune_state = type(interface_state._graft_prune_state).__name__
assert_state = "-"
is_forwarding = "upstream"
except:
prune_state = "-"
assert_state = "-"
is_forwarding = "-"
t.add_row([ip, group, interface_name, prune_state, assert_state, local_membership, is_forwarding])
return str(t)
......@@ -155,8 +158,27 @@ def 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():
# 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
kernel = Kernel()
......
......@@ -30,13 +30,13 @@ class PacketPimAssert:
PIM_HDR_ASSERT_v4_LEN = struct.calcsize(PIM_HDR_ASSERT_v4)
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:
multicast_group_address = socket.inet_ntoa(multicast_group_address)
if type(source_address) is bytes:
source_address = socket.inet_ntoa(source_address)
if metric_preference > ASSERT_CANCEL_METRIC:
metric_preference = ASSERT_CANCEL_METRIC
if metric_preference > 0x7FFFFFFF:
metric_preference = 0x7FFFFFFF
if metric > ASSERT_CANCEL_METRIC:
metric = ASSERT_CANCEL_METRIC
self.multicast_group_address = multicast_group_address
......@@ -67,6 +67,6 @@ class PacketPimAssert:
data = data[source_addr_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
......@@ -81,6 +81,9 @@ class MyDaemon(Daemon):
elif 'stop' in args and args.stop:
Main.stop()
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:
connection.shutdown(socket.SHUT_RDWR)
traceback.print_exc()
......@@ -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("-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("-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()
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
import socket
import RWLock
......@@ -23,17 +20,10 @@ class UnicastRouting(object):
ipdb = None
def __init__(self):
self.event_queue = Queue(maxsize=0)
UnicastRouting.ipr = IPRoute()
UnicastRouting.ipdb = IPDB()
self._ipdb = UnicastRouting.ipdb
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
......@@ -70,30 +60,6 @@ class UnicastRouting(object):
entry_cost = 0
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
# (root interface IP to ip_dst)
......@@ -111,8 +77,6 @@ class UnicastRouting(object):
@staticmethod
def unicast_changes(ipdb, msg, action):
#unicast_event = QueueItem(ipdb, msg, action)
#self.event_queue.put(unicast_event)
print("unicast change?")
print(action)
UnicastRouting.ipdb = ipdb
......@@ -134,102 +98,16 @@ class UnicastRouting(object):
print(network_address + "/" + str(mask_len))
subnet = ipaddress.ip_network(network_address + "/" + str(mask_len))
print(str(subnet))
#Main.kernel.notify_unicast_changes(subnet)
Main.kernel.notify_unicast_changes(subnet)
elif action == "RTM_NEWADDR" or action == "RTM_DELADDR":
# TODO ALTERACOES NA INTERFACE
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):
#self.working = False
if UnicastRouting.ipr:
UnicastRouting.ipr.close()
if UnicastRouting.ipdb:
UnicastRouting.ipdb = None
if self._ipdb:
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
SO_RCVBUFFORCE = 33
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)
bpf_filter = b''
......
......@@ -8,13 +8,22 @@ from .tree_interface import TreeInterface
from threading import Timer, Lock, RLock
from tree.metric import AssertMetric
import UnicastRouting
from Packet.PacketPimStateRefresh import PacketPimStateRefresh
from time import time
import Main
from TestLogger import NonRootFilter, logging
class KernelEntry:
TREE_TIMEOUT = 180
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.group_ip = group_ip
......@@ -59,9 +68,9 @@ class KernelEntry:
self._multicast_change = Lock()
self._lock_test2 = RLock()
self.CHANGE_STATE_LOCK = RLock()
#self._was_olist_null = self.is_olist_null()
self.change()
self.evaluate_olist_change()
self.timestamp_of_last_state_refresh_message_received = 0
print('Tree created')
#self._lock = threading.RLock()
......@@ -138,7 +147,11 @@ class KernelEntry:
return
if self.interface_state[iif].get_neighbor_RPF() != source_of_state_refresh:
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:
return
......@@ -157,10 +170,8 @@ class KernelEntry:
# Unicast Changes to RPF
###############################################################
def network_update(self):
# TODO TALVEZ OUTRO LOCK PARA BLOQUEAR ENTRADA DE PACOTES
with self.CHANGE_STATE_LOCK:
#next_hop = UnicastRouting.get_route(self.source_ip)["gateway"]
#rpf_node = self.source_ip if next_hop is None else next_hop
next_hop = UnicastRouting.get_route(self.source_ip)["gateway"]
multipaths = UnicastRouting.get_route(self.source_ip)["multipath"]
......@@ -179,20 +190,35 @@ class KernelEntry:
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:
# todo: criar novo upstream e downstream interface
# todo: stop upstream e downstream
#self.interface_state[self.inbound_interface_index].stop()
#self.interface_state[new_inbound_interface_index].stop()
#Unicast routing or Assert state causes RPF'(S) to change,
self.interface_state[self.inbound_interface_index] = TreeInterfaceDownstream
self.interface_state[new_inbound_interface_index] = TreeInterfaceUpstream
self.rpf_node = rpf_node
# get old interfaces
old_upstream_interface = self.interface_state[self.inbound_interface_index]
old_downstream_interface = self.interface_state[new_inbound_interface_index]
# 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
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.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
......@@ -231,6 +257,7 @@ class KernelEntry:
Main.kernel.set_multicast_route(self)
def delete(self):
with self._multicast_change:
for state in self.interface_state.values():
state.delete()
......@@ -252,7 +279,6 @@ class KernelEntry:
if self.inbound_interface_index == index:
self.delete()
else:
self.interface_state[index].delete()
del self.interface_state[index]
self.interface_state.pop(index).delete()
self.change()
self.evaluate_olist_change()
......@@ -107,18 +107,10 @@ class AssertStateABC(metaclass=ABCMeta):
interface.set_assert_timer(pim_globals.ASSERT_TIME)
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
def __str__(self) -> str:
return "PruneSM:" + self.__class__.__name__
return "AssertSM:" + self.__class__.__name__
class NoInfoState(AssertStateABC):
......@@ -137,7 +129,8 @@ class NoInfoState(AssertStateABC):
NoInfoState._sendAssert_setAT(interface)
print('receivedDataFromDownstreamIf, NI -> W')
#print('receivedDataFromDownstreamIf, NI -> W')
interface.assert_logger.debug('receivedDataFromDownstreamIf, NI -> W')
@staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
......@@ -150,8 +143,8 @@ class NoInfoState(AssertStateABC):
NoInfoState._sendAssert_setAT(interface)
print(
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
#print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
@staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
......@@ -174,7 +167,8 @@ class NoInfoState(AssertStateABC):
if interface.could_assert():
interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, NI -> L')
#print('receivedPreferedMetric, NI -> L')
interface.assert_logger.debug('receivedPreferedMetric, NI -> L')
@staticmethod
def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
......@@ -186,11 +180,13 @@ class NoInfoState(AssertStateABC):
@staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
print('couldAssertIsNowFalse, NI -> NI')
#print('couldAssertIsNowFalse, NI -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, NI -> NI')
@staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
print('couldAssertIsNowTrue, NI -> NI')
#print('couldAssertIsNowTrue, NI -> NI')
interface.assert_logger.debug('couldAssertIsNowTrue, NI -> NI')
@staticmethod
def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
......@@ -198,7 +194,11 @@ class NoInfoState(AssertStateABC):
@staticmethod
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):
......@@ -216,7 +216,8 @@ class WinnerState(AssertStateABC):
"""
WinnerState._sendAssert_setAT(interface)
print('receivedDataFromDownstreamIf, W -> W')
#print('receivedDataFromDownstreamIf, W -> W')
interface.assert_logger.debug('receivedDataFromDownstreamIf, W -> W')
@staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
......@@ -226,8 +227,8 @@ class WinnerState(AssertStateABC):
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
WinnerState._sendAssert_setAT(interface)
print(
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
#print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
@staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
......@@ -247,7 +248,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_state(AssertState.Loser)
interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, W -> L')
#print('receivedPreferedMetric, W -> L')
interface.assert_logger.debug('receivedPreferedMetric, W -> L')
@staticmethod
def sendStateRefresh(interface: "TreeInterfaceDownstream", state_refresh_interval):
......@@ -258,7 +260,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo)
print('assertTimerExpires, W -> NI')
#print('assertTimerExpires, W -> NI')
interface.assert_logger.debug('assertTimerExpires, W -> NI')
@staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
......@@ -269,7 +272,8 @@ class WinnerState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo)
print('couldAssertIsNowFalse, W -> NI')
#print('couldAssertIsNowFalse, W -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, W -> NI')
@staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
......@@ -283,6 +287,10 @@ class WinnerState(AssertStateABC):
def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
pass
def __str__(self) -> str:
return "W"
class LoserState(AssertStateABC):
'''
......@@ -296,18 +304,20 @@ class LoserState(AssertStateABC):
"""
@type interface: TreeInterface
"""
print('receivedDataFromDownstreamIf, L -> L')
#print('receivedDataFromDownstreamIf, L -> L')
interface.assert_logger.debug('receivedDataFromDownstreamIf, L -> L')
@staticmethod
def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
print('receivedInferiorMetricFromWinner, L -> NI')
#print('receivedInferiorMetricFromWinner, L -> NI')
interface.assert_logger.debug('receivedInferiorMetricFromWinner, L -> NI')
@staticmethod
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
print(
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
#print('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
interface.assert_logger.debug('receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
@staticmethod
def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric):
......@@ -322,12 +332,13 @@ class LoserState(AssertStateABC):
interface.set_assert_timer(assert_timer_value)
interface.set_assert_winner_metric(better_metric)
interface.set_assert_state(AssertState.Loser)
if interface.could_assert():
# todo enviar 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
def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
......@@ -336,29 +347,34 @@ class LoserState(AssertStateABC):
@staticmethod
def assertTimerExpires(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
print('assertTimerExpires, L -> NI')
#print('assertTimerExpires, L -> NI')
interface.assert_logger.debug('assertTimerExpires, L -> NI')
@staticmethod
def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
print('couldAssertIsNowFalse, L -> NI')
#print('couldAssertIsNowFalse, L -> NI')
interface.assert_logger.debug('couldAssertIsNowFalse, L -> NI')
@staticmethod
def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
print('couldAssertIsNowTrue, L -> NI')
#print('couldAssertIsNowTrue, L -> NI')
interface.assert_logger.debug('couldAssertIsNowTrue, L -> NI')
@staticmethod
def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
print('winnerLivelinessTimerExpires, L -> NI')
#print('winnerLivelinessTimerExpires, L -> NI')
interface.assert_logger.debug('winnerLivelinessTimerExpires, L -> NI')
@staticmethod
def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
interface.send_assert()
print('receivedPruneOrJoinOrGraft, L -> L')
#print('receivedPruneOrJoinOrGraft, L -> L')
interface.assert_logger.debug('receivedPruneOrJoinOrGraft, L -> L')
@staticmethod
def _to_NoInfo(interface: "TreeInterfaceDownstream"):
......@@ -366,6 +382,8 @@ class LoserState(AssertStateABC):
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
interface.set_assert_state(AssertState.NoInfo)
def __str__(self) -> str:
return "L"
class AssertState():
NoInfo = NoInfoState()
......
......@@ -353,6 +353,7 @@ class Pruned(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream
"""
if interface.get_interface().is_state_refresh_capable():
interface.set_prune_timer(interface.get_received_prune_holdtime())
print('send_state_refresh, P -> P')
......
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:
ip_address = ipaddress.ip_address(ip_address)
......@@ -30,7 +27,7 @@ class AssertMetric(object):
'''
@type metric: AssertMetric
'''
return AssertMetric(metric_preference=float("Inf"), route_metric=float("Inf"), ip_address="0.0.0.0")
return AssertMetric()
@staticmethod
def spt_assert_metric(tree_if):
......
......@@ -3,29 +3,22 @@ Created on Jul 16, 2015
@author: alex
'''
#from convergence import Convergence
#from des.event.timer import Timer
from threading import Timer
from CustomTimer.RemainingTimer import RemainingTimer
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 .tree_interface import TreeInterface
from Packet.ReceivedPacket import ReceivedPacket
from threading import Lock
from Packet.PacketPimStateRefresh import PacketPimStateRefresh
from Packet.Packet import Packet
from Packet.PacketPimHeader import PacketPimHeader
import traceback
class TreeInterfaceDownstream(TreeInterface):
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):
return
# Override
def delete(self):
TreeInterface.delete(self)
def delete(self, change_type_interface=False):
super().delete(change_type_interface)
self.clear_assert_timer()
self.clear_prune_timer()
self.clear_prune_pending_timer()
......
......@@ -18,12 +18,15 @@ import threading
class TreeInterfaceUpstream(TreeInterface):
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:
self._graft_prune_state = UpstreamState.Forward
self._graft_retry_timer = None
self._override_timer = None
self._prune_limit_timer = None
self._last_rpf = self.get_neighbor_RPF()
# Originator state
self._originator_state = OriginatorState.NotOriginator
......@@ -48,6 +51,8 @@ class TreeInterfaceUpstream(TreeInterface):
receive_thread.daemon = True
receive_thread.start()
self.logger.debug('Created UpstreamInterface')
def socket_recv(self):
while self.socket_is_enabled:
......@@ -216,24 +221,41 @@ class TreeInterfaceUpstream(TreeInterface):
def olist_is_not_null(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):
current_rpf = self.get_neighbor_RPF()
if self._last_rpf != current_rpf:
self._last_rpf = current_rpf
if olist_is_null:
self._graft_prune_state.RPFnbrChanges_olistIsNull()
self._graft_prune_state.RPFnbrChanges_olistIsNull(self)
else:
self._graft_prune_state.RPFnbrChanges_olistIsNotNull()
self._graft_prune_state.RPFnbrChanges_olistIsNotNull(self)
####################################################################
#Override
def is_forwarding(self):
return False
#Override
def delete(self):
super().delete()
def delete(self, change_type_interface=False):
self.socket_is_enabled = False
self.socket_pkt.close()
super().delete(change_type_interface)
self.clear_graft_retry_timer()
self.clear_assert_timer()
self.clear_prune_limit_timer()
......@@ -241,6 +263,12 @@ class TreeInterfaceUpstream(TreeInterface):
self.clear_state_refresh_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):
return False
......
......@@ -8,9 +8,6 @@ import Main
from threading import Lock, RLock
import traceback
#from convergence import Convergence
#from sfmr.messages.prune import SFMRPruneMsg
#from .router_interface import SFMRInterface
from .downstream_prune import DownstreamState
from .assert_ import AssertState, AssertStateABC
......@@ -27,11 +24,18 @@ from .metric import AssertMetric
from threading import Timer
from .local_membership import LocalMembership
from .globals import *
from TestLogger import InterfaceFilter, logging
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._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
try:
......@@ -60,7 +64,6 @@ class TreeInterface(metaclass=ABCMeta):
self._igmp_lock = RLock()
#self.rprint('new ' + self.__class__.__name__)
############################################
# Set ASSERT State
......@@ -69,6 +72,7 @@ class TreeInterface(metaclass=ABCMeta):
with self.get_state_lock():
if new_state != self._assert_state:
self._assert_state = new_state
self.assert_logger.debug(str(new_state))
self.change_tree()
self.evaluate_ingroup()
......@@ -243,7 +247,7 @@ class TreeInterface(metaclass=ABCMeta):
try:
(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))
self.get_interface().send(pckt.bytes())
......@@ -276,7 +280,32 @@ class TreeInterface(metaclass=ABCMeta):
pass
@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')
def is_olist_null(self):
......@@ -293,7 +322,6 @@ class TreeInterface(metaclass=ABCMeta):
with self.get_state_lock():
with self._igmp_lock:
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.change_tree()
self.evaluate_ingroup()
......@@ -301,12 +329,8 @@ class TreeInterface(metaclass=ABCMeta):
def igmp_has_members(self):
with self._igmp_lock:
#return self._igmp_has_members
return self._local_membership_state.has_members()
def rprint(self, msg, *entrys):
return
def __str__(self):
return '{}<{}>'.format(self.__class__, self._interface.get_link())
......
......@@ -265,10 +265,7 @@ class Forward(UpstreamStateABC):
"""
if not interface.is_S_directly_conn():
interface.send_graft()
#interface.get_grt().start()
interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending)
print('RPFnbrChanges_olistIsNotNull, F -> AP')
......@@ -344,10 +341,8 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.get_plt().reset()
interface.set_prune_limit_timer()
interface.rprint('stateRefreshArrivesRPFnbr_pruneIs1, P -> P')
print('stateRefreshArrivesRPFnbr_pruneIs1, P -> P')
@staticmethod
def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"):
......@@ -358,12 +353,6 @@ class Pruned(UpstreamStateABC):
@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.set_prune_limit_timer()
print(
......@@ -438,12 +427,12 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
if not interface.is_S_directly_conn():
interface.send_graft()
interface.set_state(UpstreamState.AckPending)
#interface.get_grt().start()
interface.set_graft_retry_timer()
interface.clear_prune_limit_timer()
interface.set_state(UpstreamState.AckPending)
interface.send_graft()
interface.set_graft_retry_timer()
print('olistIsNowNotNull, P -> AP')
......@@ -455,7 +444,6 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.get_plt().stop()
if not interface.is_S_directly_conn():
interface.clear_prune_limit_timer()
......@@ -522,7 +510,6 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.set_ot()
interface.set_override_timer()
print('stateRefreshArrivesRPFnbr_pruneIs1, AP -> AP')
......@@ -536,9 +523,7 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
interface.set_state(UpstreamState.Forward)
#interface.get_grt().cancel()
interface.clear_graft_retry_timer()
print(
......@@ -551,8 +536,6 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.cancel_ot()
interface.clear_override_timer()
print('seeJoinToRPFnbr, AP -> AP')
......@@ -564,11 +547,9 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.set_ot()
interface.set_override_timer()
interface.rprint('seePrune, AP -> AP')
print('seePrune, AP -> AP')
@staticmethod
def OTexpires(interface: "TreeInterfaceUpstream"):
......@@ -579,7 +560,7 @@ class AckPending(UpstreamStateABC):
"""
interface.send_join()
interface.rprint('OTexpires, AP -> AP')
print('OTexpires, AP -> AP')
@staticmethod
def olistIsNowNull(interface: "TreeInterfaceUpstream"):
......@@ -624,8 +605,6 @@ class AckPending(UpstreamStateABC):
"""
if not interface.is_S_directly_conn():
interface.send_graft()
#interface.get_grt().reset()
interface.set_graft_retry_timer()
print('olistIsNowNotNull, AP -> AP')
......@@ -638,9 +617,9 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream
"""
#interface.get_grt().cancel()
if not interface.is_S_directly_conn():
interface.clear_graft_retry_timer()
interface.set_state(UpstreamState.Pruned)
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