Commit b5bd0d28 authored by Pedro Oliveira's avatar Pedro Oliveira

assert, unicast routing update... not tested (just for backup)

parent 215be907
from time import time
try:
from threading import _Timer as Timer
except ImportError:
from threading import Timer
class RemainingTimer(Timer):
def __init__(self, interval, function):
super().__init__(interval, function)
self.start_time = time()
def time_remaining(self):
delta_time = time() - self.start_time
return self.interval - delta_time
'''
def test():
print("ola")
x = RemainingTimer(10, test)
x.start()
from time import sleep
for i in range(0, 10):
print(x.time_remaining())
sleep(1)
'''
...@@ -15,6 +15,7 @@ class Interface(object): ...@@ -15,6 +15,7 @@ class Interface(object):
def __init__(self, interface_name: str): def __init__(self, interface_name: str):
self.interface_name = interface_name self.interface_name = interface_name
ip_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['addr'] ip_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['addr']
self.ip_mask_interface = netifaces.ifaddresses(interface_name)[netifaces.AF_INET][0]['netmask']
self.ip_interface = ip_interface self.ip_interface = ip_interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM) s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM)
......
...@@ -125,7 +125,10 @@ class InterfacePim(Interface): ...@@ -125,7 +125,10 @@ class InterfacePim(Interface):
def get_neighbor(self, ip): def get_neighbor(self, ip):
with self.neighbors_lock.genRlock(): with self.neighbors_lock.genRlock():
return self.neighbors[ip] if ip in self.neighbors:
return self.neighbors[ip]
else:
return None
def remove_neighbor(self, ip): def remove_neighbor(self, ip):
with self.neighbors_lock.genWlock(): with self.neighbors_lock.genWlock():
......
...@@ -3,6 +3,9 @@ import struct ...@@ -3,6 +3,9 @@ import struct
import netifaces import netifaces
import threading import threading
import traceback import traceback
import ipaddress
from RWLock.RWLock import RWLockWrite from RWLock.RWLock import RWLockWrite
import Main import Main
...@@ -364,8 +367,15 @@ class Kernel: ...@@ -364,8 +367,15 @@ class Kernel:
return None return None
def neighbor_removed(self, interface_name, neighbor_ip): def notify_unicast_changes(self, subnet):
# todo # todo
with self.rwlock.genWlock():
for (source_ip, group) 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)
pass pass
......
...@@ -173,7 +173,7 @@ def list_routing_state(): ...@@ -173,7 +173,7 @@ def list_routing_state():
routing_entries = kernel.routing.values() routing_entries = kernel.routing.values()
vif_indexes = kernel.vif_index_to_name_dic.keys() vif_indexes = kernel.vif_index_to_name_dic.keys()
t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', "Is Forwarding?"]) t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"])
for entry in routing_entries: for entry in routing_entries:
ip = entry.source_ip ip = entry.source_ip
group = entry.group_ip group = entry.group_ip
...@@ -182,19 +182,21 @@ def list_routing_state(): ...@@ -182,19 +182,21 @@ def list_routing_state():
for index in vif_indexes: for index in vif_indexes:
interface_state = entry.interface_state[index] interface_state = entry.interface_state[index]
interface_name = kernel.vif_index_to_name_dic[index] interface_name = kernel.vif_index_to_name_dic[index]
is_forwarding = interface_state.is_forwarding() local_membership = type(interface_state._local_membership_state).__name__
try: try:
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__ assert_state = type(interface_state._assert_state).__name__
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 = "-" assert_state = "-"
is_forwarding = "upstream"
except: except:
prune_state = "-" prune_state = "-"
assert_state = "-" assert_state = "-"
t.add_row([ip, group, interface_name, prune_state, assert_state, is_forwarding]) t.add_row([ip, group, interface_name, prune_state, assert_state, local_membership, is_forwarding])
return str(t) return str(t)
...@@ -222,3 +224,6 @@ def main(): ...@@ -222,3 +224,6 @@ def main():
global igmp global igmp
igmp = IGMP() igmp = IGMP()
global u
u = UnicastRouting.UnicastRouting()
...@@ -2,6 +2,7 @@ from threading import Timer ...@@ -2,6 +2,7 @@ from threading import Timer
import time import time
from utils import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT, TYPE_CHECKING from utils import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT, TYPE_CHECKING
from threading import Lock from threading import Lock
from RWLock.RWLock import RWLockWrite
import Main import Main
if TYPE_CHECKING: if TYPE_CHECKING:
from InterfacePIM import InterfacePim from InterfacePIM import InterfacePim
...@@ -24,6 +25,10 @@ class Neighbor: ...@@ -24,6 +25,10 @@ class Neighbor:
self.time_of_last_update = time.time() self.time_of_last_update = time.time()
self.neighbor_lock = Lock() self.neighbor_lock = Lock()
self.tree_interface_nlt_subscribers = []
self.tree_interface_nlt_subscribers_lock = RWLockWrite()
# send hello to new neighbor # send hello to new neighbor
#self.contact_interface.send_hello() #self.contact_interface.send_hello()
# todo RANDOM DELAY??? => DO NOTHING... EVENTUALLY THE HELLO MESSAGE WILL BE SENT # todo RANDOM DELAY??? => DO NOTHING... EVENTUALLY THE HELLO MESSAGE WILL BE SENT
...@@ -71,11 +76,14 @@ class Neighbor: ...@@ -71,11 +76,14 @@ class Neighbor:
del self.contact_interface.neighbors[self.ip] del self.contact_interface.neighbors[self.ip]
# notify interfaces which have this neighbor as AssertWinner
with self.tree_interface_nlt_subscribers_lock.genRlock():
for tree_if in self.tree_interface_nlt_subscribers:
tree_if.assert_winner_nlt_expires()
def reset(self): def reset(self):
interface_name = self.contact_interface.interface_name return
neighbor_ip = self.ip
Main.kernel.neighbor_removed(interface_name, neighbor_ip)
# todo new neighbor
def receive_hello(self, generation_id, hello_hold_time): def receive_hello(self, generation_id, hello_hold_time):
...@@ -85,3 +93,15 @@ class Neighbor: ...@@ -85,3 +93,15 @@ class Neighbor:
self.time_of_last_update = time.time() self.time_of_last_update = time.time()
self.set_generation_id(generation_id) self.set_generation_id(generation_id)
self.set_hello_hold_time(hello_hold_time) self.set_hello_hold_time(hello_hold_time)
def subscribe_nlt_expiration(self, tree_if):
with self.tree_interface_nlt_subscribers_lock.genWlock():
if tree_if not in self.tree_interface_nlt_subscribers:
self.tree_interface_nlt_subscribers.append(tree_if)
def unsubscribe_nlt_expiration(self, tree_if):
with self.tree_interface_nlt_subscribers_lock.genWlock():
if tree_if in self.tree_interface_nlt_subscribers:
self.tree_interface_nlt_subscribers.remove(tree_if)
...@@ -2,6 +2,7 @@ import struct ...@@ -2,6 +2,7 @@ import struct
import socket import socket
from Packet.PacketPimEncodedGroupAddress import PacketPimEncodedGroupAddress from Packet.PacketPimEncodedGroupAddress import PacketPimEncodedGroupAddress
from Packet.PacketPimEncodedUnicastAddress import PacketPimEncodedUnicastAddress from Packet.PacketPimEncodedUnicastAddress import PacketPimEncodedUnicastAddress
from tree.globals import ASSERT_CANCEL_METRIC
''' '''
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
...@@ -29,12 +30,15 @@ class PacketPimAssert: ...@@ -29,12 +30,15 @@ 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, metric): def __init__(self, multicast_group_address: str or bytes, source_address: str or bytes, metric_preference: int, 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:
metric_preference = ASSERT_CANCEL_METRIC
if metric > ASSERT_CANCEL_METRIC:
metric = ASSERT_CANCEL_METRIC
self.multicast_group_address = multicast_group_address self.multicast_group_address = multicast_group_address
self.source_address = source_address self.source_address = source_address
self.metric_preference = metric_preference self.metric_preference = metric_preference
......
...@@ -65,9 +65,10 @@ class PacketPimHeader(PacketPayload): ...@@ -65,9 +65,10 @@ class PacketPimHeader(PacketPayload):
raise Exception raise Exception
msg_to_checksum = data[0:2] + b'\x00\x00' + data[4:] msg_to_checksum = data[0:2] + b'\x00\x00' + data[4:]
print("checksum calculated: " + str(checksum(msg_to_checksum)))
if checksum(msg_to_checksum) != rcv_checksum: if checksum(msg_to_checksum) != rcv_checksum:
print("wrong checksum") print("wrong checksum")
print("checksum calculated: " + str(checksum(msg_to_checksum)))
print("checksum recv: " + str(rcv_checksum))
raise Exception raise Exception
pim_payload = data[PacketPimHeader.PIM_HDR_LEN:] pim_payload = data[PacketPimHeader.PIM_HDR_LEN:]
......
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 Main
import ipaddress
#ipdb = IPDB()
ipr = IPRoute()
def get_route(ip_dst: str): def get_route(ip_dst: str):
with IPDB() as ipdb: return UnicastRouting.get_route(ip_dst)
def get_metric(ip_dst: str):
return UnicastRouting.get_metric(ip_dst)
def check_rpf(ip_dst):
return UnicastRouting.check_rpf(ip_dst)
class UnicastRouting(object):
ipr = None
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
def get_route(ip_dst: str):
ipdb = UnicastRouting.ipdb
ip_bytes = socket.inet_aton(ip_dst) ip_bytes = socket.inet_aton(ip_dst)
ip_int = int.from_bytes(ip_bytes, byteorder='big') ip_int = int.from_bytes(ip_bytes, byteorder='big')
info = None info = None
...@@ -25,97 +59,174 @@ def get_route(ip_dst: str): ...@@ -25,97 +59,174 @@ def get_route(ip_dst: str):
return info return info
# get metrics (routing preference and cost) to IP ip_dst # get metrics (routing preference and cost) to IP ip_dst
def get_metric(ip_dst: str): @staticmethod
unicast_routing_entry = get_route(ip_dst) def get_metric(ip_dst: str):
entry_protocol = unicast_routing_entry["proto"] unicast_routing_entry = UnicastRouting.get_route(ip_dst)
entry_cost = unicast_routing_entry["priority"] entry_protocol = unicast_routing_entry["proto"]
return (entry_protocol, entry_cost) entry_cost = unicast_routing_entry["priority"]
return (entry_protocol, entry_cost)
"""
def get_rpf(ip_dst: str): """
unicast_routing_entry = get_route(ip_dst) def get_rpf(ip_dst: str):
#interface_oif = unicast_routing_entry['oif'] unicast_routing_entry = get_route(ip_dst)
if not unicast_routing_entry['multipath']: #interface_oif = unicast_routing_entry['oif']
interface_oif = unicast_routing_entry['oif'] if not unicast_routing_entry['multipath']:
else: interface_oif = unicast_routing_entry['oif']
multiple_entries = unicast_routing_entry['multipath'] else:
print(multiple_entries) multiple_entries = unicast_routing_entry['multipath']
(entry0, _) = multiple_entries print(multiple_entries)
print(entry0) (entry0, _) = multiple_entries
interface_oif = entry0['oif'] print(entry0)
interface_oif = entry0['oif']
print("ola")
print(ipdb.interfaces[interface_oif]['ipaddr']) print("ola")
print(ipdb.interfaces[interface_oif]['ipaddr'])
for i in range(len(ipdb.interfaces[interface_oif]['ipaddr'])):
print("ola2") for i in range(len(ipdb.interfaces[interface_oif]['ipaddr'])):
interface = ipdb.interfaces[interface_oif]['ipaddr'][i] print("ola2")
print(interface) interface = ipdb.interfaces[interface_oif]['ipaddr'][i]
if interface['family'] == socket.AF_INET: print(interface)
return interface['address'] if interface['family'] == socket.AF_INET:
return None return interface['address']
""" return None
"""
# get output interface IP, used to send data to IP ip_dst
# (root interface IP to ip_dst) # get output interface IP, used to send data to IP ip_dst
def check_rpf(ip_dst): # (root interface IP to ip_dst)
# obter index da interface @staticmethod
# rpf_interface_index = ipr.get_routes(family=socket.AF_INET, dst=ip)[0]['attrs'][2][1] def check_rpf(ip_dst):
# interface_name = if_indextoname(rpf_interface_index) # obter index da interface
# return interface_name # rpf_interface_index = ipr.get_routes(family=socket.AF_INET, dst=ip)[0]['attrs'][2][1]
# interface_name = if_indextoname(rpf_interface_index)
# obter ip da interface de saida # return interface_name
rpf_interface_source = ipr.get_routes(family=socket.AF_INET, dst=ip_dst)[0]['attrs'][3][1]
return rpf_interface_source # obter ip da interface de saida
rpf_interface_source = UnicastRouting.ipr.get_routes(family=socket.AF_INET, dst=ip_dst)[0]['attrs'][3][1]
return rpf_interface_source
"""
def get_metric(ip_dst: str):
ip_bytes = socket.inet_aton(ip_dst) @staticmethod
ip_int = int.from_bytes(ip_bytes, byteorder='big') def unicast_changes(ipdb, msg, action):
info = None #unicast_event = QueueItem(ipdb, msg, action)
for mask_len in range(32, 0, -1): #self.event_queue.put(unicast_event)
ip_bytes = (ip_int & (0xFFFFFFFF << (32 - mask_len))).to_bytes(4, "big") print("unicast change?")
ip_dst = socket.inet_ntoa(ip_bytes) + "/" + str(mask_len) print(action)
print(ip_dst) UnicastRouting.ipdb = ipdb
try: if action == "RTM_NEWROUTE" or action == "RTM_DELROUTE":
info = ipdb.routes[ip_dst] print(ipdb.routes)
break mask_len = msg["dst_len"]
except: network_address = None
continue attrs = msg["attrs"]
if not info: print(attrs)
print("0.0.0.0/0") for (key, value) in attrs:
info = ipdb.routes["default"] print((key,value))
print(info) if key == "RTA_DST":
print("metric=", info["priority"]) network_address = value
print("proto=", info["proto"]) break
#print(info.keys()) if network_address is None:
#if info["gateway"]: network_address = "0.0.0.0"
# print("next_hop=", info["gateway"]) print(network_address)
#elif info["prefsrc"]: print(mask_len)
# print("next_hop=", info["prefsrc"]) print(network_address + "/" + str(mask_len))
return (info["proto"], info["priority"]) subnet = ipaddress.ip_network(network_address + "/" + str(mask_len))
print(str(subnet))
#Main.kernel.notify_unicast_changes(subnet)
def check_rpf(ip_dst: str): elif action == "RTM_NEWADDR" or action == "RTM_DELADDR":
from pyroute2 import IPRoute print("a")
# from utils import if_indextoname
'''
ipr = IPRoute() def worker(self):
# obter index da interface global ipdb
# rpf_interface_index = ipr.get_routes(family=socket.AF_INET, dst=ip)[0]['attrs'][2][1] while self.working:
# interface_name = if_indextoname(rpf_interface_index) item = self.event_queue.get()
# return interface_name ipdb = item.ipdb
if item.action == "RTM_NEWROUTE" or item.action == "RTM_DELROUTE":
# obter ip da interface de saida mask_len = item.action["dst_len"]
rpf_interface_source = ipr.get_routes(family=socket.AF_INET, dst=ip_dst)[0]['attrs'][3][1] network_address = None
return rpf_interface_source attrs = item.action["attrs"]
""" for (key, value) in attrs:
if key == "RTA_DST":
network_address = value
def stop(): break
ipr.close() subnet = ipaddress.ip_network(network_address + "/" + mask_len)
Main.kernel.notify_kernel_about_unicast_change(subnet)
#ip = input("ip=") elif item.action == "RTM_NEWADDR" or item.action == "RTM_DELADDR":
#get_metric(ip) print("a")
\ No newline at end of file '''
#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
'''
...@@ -6,6 +6,7 @@ from tree.tree_if_upstream import TreeInterfaceUpstream ...@@ -6,6 +6,7 @@ from tree.tree_if_upstream import TreeInterfaceUpstream
from tree.tree_if_downstream import TreeInterfaceDownstream from tree.tree_if_downstream import TreeInterfaceDownstream
from .tree_interface import TreeInterface from .tree_interface import TreeInterface
from threading import Timer, Lock, RLock from threading import Timer, Lock, RLock
from tree.metric import AssertMetric
import UnicastRouting import UnicastRouting
class KernelEntry: class KernelEntry:
...@@ -17,7 +18,25 @@ class KernelEntry: ...@@ -17,7 +18,25 @@ class KernelEntry:
self.group_ip = group_ip self.group_ip = group_ip
# ip of neighbor of the rpf # ip of neighbor of the rpf
self._rpf_node = None #next_hop = UnicastRouting.get_route(source_ip)["gateway"]
#self.rpf_node = source_ip if next_hop is None else next_hop
next_hop = UnicastRouting.get_route(source_ip)["gateway"]
multipaths = UnicastRouting.get_route(source_ip)["multipath"]
self.rpf_node = next_hop if next_hop is not None else source_ip
print("MUL", multipaths)
#self.rpf_node = multipaths[0]["gateway"]
for m in multipaths:
if m["gateway"] is None:
self.rpf_node = source_ip
break
else:
self.rpf_node = m["gateway"]
print("RPF_NODE:", UnicastRouting.get_route(source_ip))
print(self.rpf_node == source_ip)
# (S,G) starts IG state # (S,G) starts IG state
self._was_olist_null = None self._was_olist_null = None
...@@ -81,20 +100,29 @@ class KernelEntry: ...@@ -81,20 +100,29 @@ class KernelEntry:
def recv_assert_msg(self, index, packet): def recv_assert_msg(self, index, packet):
print("recv assert") print("recv assert")
self.interface_state[index].recv_assert_msg() pkt_assert = packet.payload.payload
metric = pkt_assert.metric
metric_preference = pkt_assert.metric_preference
assert_sender_ip = packet.ip_header.ip_src
received_metric = AssertMetric(metric_preference=metric_preference, route_metric=metric, ip_address=assert_sender_ip)
self.interface_state[index].recv_assert_msg(received_metric)
def recv_prune_msg(self, index, packet): def recv_prune_msg(self, index, packet):
print("recv prune msg") print("recv prune msg")
self.interface_state[index].recv_prune_msg() holdtime = packet.payload.payload.hold_time
upstream_neighbor_address = packet.payload.payload.upstream_neighbor_address
self.interface_state[index].recv_prune_msg(upstream_neighbor_address=upstream_neighbor_address, holdtime=holdtime)
def recv_join_msg(self, index, packet): def recv_join_msg(self, index, packet):
print("recv join msg") print("recv join msg")
print("type: ") upstream_neighbor_address = packet.payload.payload.upstream_neighbor_address
self.interface_state[index].recv_join_msg() self.interface_state[index].recv_join_msg(upstream_neighbor_address)
def recv_graft_msg(self, index, packet): def recv_graft_msg(self, index, packet):
print("recv graft msg") print("recv graft msg")
self.interface_state[index].recv_graft_msg() upstream_neighbor_address = packet.payload.payload.upstream_neighbor_address
self.interface_state[index].recv_graft_msg(upstream_neighbor_address)
def recv_graft_ack_msg(self, index, packet): def recv_graft_ack_msg(self, index, packet):
print("recv graft ack msg") print("recv graft ack msg")
...@@ -105,13 +133,47 @@ class KernelEntry: ...@@ -105,13 +133,47 @@ class KernelEntry:
prune_indicator = 1 prune_indicator = 1
self.interface_state[index].recv_state_refresh_msg(prune_indicator) self.interface_state[index].recv_state_refresh_msg(prune_indicator)
def network_update(self, change, args):
#todo ###############################################################
return # Unicast Changes to RPF
###############################################################
def network_update(self):
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"]
rpf_node = next_hop
print("MUL", multipaths)
# self.rpf_node = multipaths[0]["gateway"]
for m in multipaths:
if m["gateway"] is None:
rpf_node = self.source_ip
break
else:
rpf_node = m["gateway"]
print("RPF_NODE:", UnicastRouting.get_route(self.source_ip))
print(self.rpf_node == self.source_ip)
new_inbound_interface_index = Main.kernel.vif_dic[self.check_rpf()]
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.inbound_interface_index = new_inbound_interface_index
if self.rpf_node != rpf_node:
self.rpf_node = rpf_node
self.interface_state[self.inbound_interface_index].change_rpf(self._was_olist_null)
def update(self, caller, arg): def update(self, caller, arg):
#todo #todo
......
...@@ -2,11 +2,14 @@ from abc import ABCMeta, abstractstaticmethod ...@@ -2,11 +2,14 @@ from abc import ABCMeta, abstractstaticmethod
import tree.globals as pim_globals import tree.globals as pim_globals
from .metric import AssertMetric from .metric import AssertMetric
from utils import TYPE_CHECKING
if TYPE_CHECKING:
from .tree_if_downstream import TreeInterfaceDownstream
class AssertStateABC(metaclass=ABCMeta): class AssertStateABC(metaclass=ABCMeta):
@abstractstaticmethod @abstractstaticmethod
def receivedDataFromDownstreamIf(interface): def receivedDataFromDownstreamIf(interface: "TreeInterfaceDownstream"):
""" """
An (S,G) Data packet received on downstream interface An (S,G) Data packet received on downstream interface
...@@ -15,7 +18,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -15,7 +18,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def receivedInferiorMetricFromWinner(interface): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
""" """
Receive Inferior (Assert OR State Refresh) from Assert Winner Receive Inferior (Assert OR State Refresh) from Assert Winner
...@@ -24,7 +27,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -24,7 +27,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface): def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
""" """
Receive Inferior (Assert OR State Refresh) from non-Assert Winner Receive Inferior (Assert OR State Refresh) from non-Assert Winner
AND CouldAssert==TRUE AND CouldAssert==TRUE
...@@ -34,7 +37,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -34,7 +37,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def receivedPreferedMetric(interface, assert_time, better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", assert_time, better_metric):
""" """
Receive Preferred Assert OR State Refresh Receive Preferred Assert OR State Refresh
...@@ -45,7 +48,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -45,7 +48,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def sendStateRefresh(interface, time): def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
""" """
Send State Refresh Send State Refresh
...@@ -56,7 +59,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -56,7 +59,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def assertTimerExpires(interface): def assertTimerExpires(interface: "TreeInterfaceDownstream"):
""" """
AT(S,G) Expires AT(S,G) Expires
...@@ -65,7 +68,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -65,7 +68,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def couldAssertIsNowFalse(interface): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
""" """
CouldAssert -> FALSE CouldAssert -> FALSE
...@@ -74,7 +77,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -74,7 +77,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def couldAssertIsNowTrue(interface): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
""" """
CouldAssert -> TRUE CouldAssert -> TRUE
...@@ -83,7 +86,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -83,7 +86,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def winnerLivelinessTimerExpires(interface): def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
""" """
Winner’s NLT(N,I) Expires Winner’s NLT(N,I) Expires
...@@ -92,7 +95,7 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -92,7 +95,7 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
@abstractstaticmethod @abstractstaticmethod
def receivedPruneOrJoinOrGraft(interface): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
""" """
Receive Prune(S,G), Join(S,G) or Graft(S,G) Receive Prune(S,G), Join(S,G) or Graft(S,G)
...@@ -101,264 +104,302 @@ class AssertStateABC(metaclass=ABCMeta): ...@@ -101,264 +104,302 @@ class AssertStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
def _sendAssert_setAT(interface): def _sendAssert_setAT(interface: "TreeInterfaceDownstream"):
interface.send_assert() interface.send_assert()
interface.assert_timer.set_timer(pim_globals.ASSERT_TIME) #interface.assert_timer.set_timer(pim_globals.ASSERT_TIME)
interface.assert_timer.reset() interface.set_assert_timer(pim_globals.ASSERT_TIME)
#interface.assert_timer.reset()
@staticmethod @staticmethod
def rprint(interface, msg, *entrys): def rprint(interface: "TreeInterfaceDownstream", msg, *entrys):
''' '''
Method used for simplifiyng the process of reporting changes in a assert state Method used for simplifiyng the process of reporting changes in a assert state
Tree Interface. Tree Interface.
@type interface: TreeInterface @type interface: TreeInterface
''' '''
interface.rprint(msg, 'assert state', *entrys) print(msg, 'assert state', *entrys)
# Override # Override
def __str__(self) -> str: def __str__(self) -> str:
return "PruneSM:" + self.__class__.__name__ return "PruneSM:" + self.__class__.__name__
class LoserState(AssertStateABC): class NoInfoState(AssertStateABC):
''' '''
I am Assert Loser (L) NoInfoState (NI)
This router has lost an (S,G) Assert on interface I. It must not This router has no (S,G) Assert state on interface I.
forward packets from S destined for G onto interface I.
''' '''
@staticmethod @staticmethod
def receivedDataFromDownstreamIf(interface): def receivedDataFromDownstreamIf(interface: "TreeInterfaceDownstream"):
""" """
@type interface: TreeInterface @type interface: TreeInterface
""" """
interface.rprint('receivedDataFromDownstreamIf, L -> L') NoInfoState._sendAssert_setAT(interface)
@staticmethod interface.set_assert_state(AssertState.Winner)
def receivedInferiorMetricFromWinner(interface): #interface.assert_winner_metric = interface.assert_metric
LoserState._to_NoInfo(interface) interface.set_assert_winner_metric(interface.my_assert_metric())
interface.rprint('receivedInferiorMetricFromWinner, L -> NI') print('receivedDataFromDownstreamIf, NI -> W')
@staticmethod @staticmethod
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
interface.rprint( assert False, "this should never ocurr"
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
@staticmethod @staticmethod
def receivedPreferedMetric(interface, assert_time, better_metric): def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
''' NoInfoState._sendAssert_setAT(interface)
@type better_metric: AssertMetric
'''
interface.assert_timer.set_timer(assert_time)
interface.assert_timer.reset()
has_winner_changed = interface.assert_winner_metric.node != better_metric.node
interface.assert_winner_metric = better_metric
if interface.could_assert() and has_winner_changed:
interface.send_prune()
interface.rprint('receivedPreferedMetric, L -> L', 'from:', #interface.assert_state = AssertState.Winner
better_metric.node) interface.set_assert_state(AssertState.Winner)
#interface.assert_winner_metric = interface.assert_metric
interface.set_assert_winner_metric(interface.my_assert_metric())
@staticmethod print(
def sendStateRefresh(interface, time): 'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W')
assert False, "this should never ocurr"
@staticmethod @staticmethod
def assertTimerExpires(interface): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric, state_refresh_interval = None):
LoserState._to_NoInfo(interface) '''
@type interface: TreeInterface
'''
#interface.assert_timer.set_timer(assert_time)
if state_refresh_interval is None:
# event caused by Assert Msg
assert_timer_value = pim_globals.ASSERT_TIME
else:
# event caused by StateRefreshMsg
assert_timer_value = state_refresh_interval*3
interface.set_assert_timer(assert_timer_value)
#interface.assert_timer.reset()
#interface.assert_state = AssertState.Loser
interface.set_assert_state(AssertState.Loser)
#interface.assert_winner_metric = better_metric
interface.set_assert_winner_metric(better_metric)
# todo MUST also multicast a Prune(S,G) to the Assert winner <- TO THE colocar endereco do winner
if interface.could_assert():
interface.send_prune(holdtime=assert_timer_value)
interface.rprint('assertTimerExpires, L -> NI') print('receivedPreferedMetric, NI -> L')
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface): def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
LoserState._to_NoInfo(interface) pass
interface.rprint('couldAssertIsNowFalse, L -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface): def assertTimerExpires(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) assert False, "this should never ocurr"
interface.rprint('couldAssertIsNowTrue, L -> NI')
@staticmethod @staticmethod
def winnerLivelinessTimerExpires(interface): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface) print('couldAssertIsNowFalse, NI -> NI')
interface.rprint('winnerLivelinessTimerExpires, L -> NI')
@staticmethod @staticmethod
def receivedPruneOrJoinOrGraft(interface): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
interface.send_assert() print('couldAssertIsNowTrue, NI -> NI')
interface.rprint('receivedPruneOrJoinOrGraft, L -> L') @staticmethod
def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr"
@staticmethod @staticmethod
def _to_NoInfo(interface): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
interface.assert_timer.stop() print('receivedPruneOrJoinOrGraft, NI -> NI')
interface.assert_state = AssertState.NoInfo
interface.assert_winner_metric = AssertMetric.infinite_assert_metric()
class NoInfoState(AssertStateABC): class WinnerState(AssertStateABC):
''' '''
NoInfoState (NI) I am Assert Winner (W)
This router has no (S,G) Assert state on interface I. This router has won an (S,G) Assert on interface I. It is now
responsible for forwarding traffic from S destined for G via
interface I.
''' '''
@staticmethod @staticmethod
def receivedDataFromDownstreamIf(interface): def receivedDataFromDownstreamIf(interface: "TreeInterfaceDownstream"):
""" """
@type interface: TreeInterface @type interface: TreeInterface
""" """
NoInfoState._sendAssert_setAT(interface) WinnerState._sendAssert_setAT(interface)
interface.assert_state = AssertState.Winner
interface.assert_winner_metric = interface.assert_metric
interface.rprint('receivedDataFromDownstreamIf, NI -> W') print('receivedDataFromDownstreamIf, W -> W')
@staticmethod @staticmethod
def receivedInferiorMetricFromWinner(interface): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" assert False, "this should never ocurr"
@staticmethod @staticmethod
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface): def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
NoInfoState._sendAssert_setAT(interface) WinnerState._sendAssert_setAT(interface)
interface.assert_state = AssertState.Winner
interface.assert_winner_metric = interface.assert_metric
interface.rprint( print(
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, NI -> W') 'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W')
@staticmethod @staticmethod
def receivedPreferedMetric(interface, assert_time, better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric, state_refresh_interval = None):
''' '''
@type interface: TreeInterface @type better_metric: AssertMetric
''' '''
interface.assert_timer.set_timer(assert_time)
interface.assert_timer.reset()
interface.assert_state = AssertState.Loser #interface.assert_timer.set_timer(assert_time)
interface.assert_winner_metric = better_metric #interface.assert_timer.reset()
if interface.could_assert(): if state_refresh_interval is None:
interface.send_prune() # event caused by AssertMsg
assert_timer_value = pim_globals.ASSERT_TIME
else:
# event caused by State Refresh Msg
assert_timer_value = state_refresh_interval*3
interface.set_assert_timer(assert_timer_value)
interface.set_assert_winner_metric(better_metric)
interface.rprint('receivedPreferedMetric, NI -> L') #interface.assert_state = AssertState.Loser
interface.set_assert_state(AssertState.Loser)
if interface.could_assert:
interface.send_prune(holdtime=assert_timer_value)
print('receivedPreferedMetric, W -> L')
@staticmethod @staticmethod
def sendStateRefresh(interface, time): def sendStateRefresh(interface: "TreeInterfaceDownstream", state_refresh_interval):
pass #interface.assert_timer.set_timer(time)
interface.set_assert_timer(state_refresh_interval*3)
#interface.assert_timer.reset()
@staticmethod @staticmethod
def assertTimerExpires(interface): def assertTimerExpires(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" #interface.assert_state = AssertState.NoInfo
interface.set_assert_state(AssertState.NoInfo)
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
print('assertTimerExpires, W -> NI')
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
interface.rprint('couldAssertIsNowFalse, NI -> NI') interface.send_assert_cancel()
#interface.assert_timer.stop()
interface.clear_assert_timer()
#interface.assert_state = AssertState.NoInfo
interface.set_assert_state(AssertState.NoInfo)
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
print('couldAssertIsNowFalse, W -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface): def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
interface.rprint('couldAssertIsNowTrue, NI -> NI') assert False, "this should never ocurr"
@staticmethod @staticmethod
def winnerLivelinessTimerExpires(interface): def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" assert False, "this should never ocurr"
@staticmethod @staticmethod
def receivedPruneOrJoinOrGraft(interface): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
interface.rprint('receivedPruneOrJoinOrGraft, NI -> NI') pass
class WinnerState(AssertStateABC): class LoserState(AssertStateABC):
''' '''
I am Assert Winner (W) I am Assert Loser (L)
This router has won an (S,G) Assert on interface I. It is now This router has lost an (S,G) Assert on interface I. It must not
responsible for forwarding traffic from S destined for G via forward packets from S destined for G onto interface I.
interface I.
''' '''
@staticmethod @staticmethod
def receivedDataFromDownstreamIf(interface): def receivedDataFromDownstreamIf(interface: "TreeInterfaceDownstream"):
""" """
@type interface: TreeInterface @type interface: TreeInterface
""" """
WinnerState._sendAssert_setAT(interface) print('receivedDataFromDownstreamIf, L -> L')
interface.rprint('receivedDataFromDownstreamIf, W -> W')
@staticmethod @staticmethod
def receivedInferiorMetricFromWinner(interface): def receivedInferiorMetricFromWinner(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" LoserState._to_NoInfo(interface)
@staticmethod print('receivedInferiorMetricFromWinner, L -> NI')
def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface):
WinnerState._sendAssert_setAT(interface)
interface.rprint( @staticmethod
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, W -> W') def receivedInferiorMetricFromNonWinner_couldAssertIsTrue(interface: "TreeInterfaceDownstream"):
print(
'receivedInferiorMetricFromNonWinner_couldAssertIsTrue, L -> L')
@staticmethod @staticmethod
def receivedPreferedMetric(interface, assert_time, better_metric): def receivedPreferedMetric(interface: "TreeInterfaceDownstream", better_metric, state_refresh_interval = None):
''' '''
@type better_metric: AssertMetric @type better_metric: AssertMetric
''' '''
#interface.assert_timer.set_timer(assert_time)
#interface.assert_timer.reset()
if state_refresh_interval is None:
assert_timer_value = pim_globals.ASSERT_TIME
else:
assert_timer_value = state_refresh_interval*3
interface.assert_timer.set_timer(assert_time) interface.set_assert_timer(assert_timer_value)
interface.assert_timer.reset()
interface.assert_winner_metric = better_metric #has_winner_changed = interface.assert_winner_metric.node != better_metric.node
interface.assert_state = AssertState.Loser interface.set_assert_winner_metric(better_metric)
if interface.could_assert: if interface.could_assert():
# todo enviar holdtime = assert_timer_value???!
interface.send_prune() interface.send_prune()
interface.rprint('receivedPreferedMetric, W -> L', 'from:', print('receivedPreferedMetric, L -> L')
str(better_metric.node))
@staticmethod @staticmethod
def sendStateRefresh(interface, time): def sendStateRefresh(interface: "TreeInterfaceDownstream", time):
interface.assert_timer.set_timer(time) assert False, "this should never ocurr"
interface.assert_timer.reset()
@staticmethod @staticmethod
def assertTimerExpires(interface): def assertTimerExpires(interface: "TreeInterfaceDownstream"):
interface.assert_state = AssertState.NoInfo LoserState._to_NoInfo(interface)
interface.assert_winner_metric = AssertMetric.infinite_assert_metric()
interface.rprint('assertTimerExpires, W -> NI') if interface.could_assert():
interface.evaluate_ingroup()
print('assertTimerExpires, L -> NI')
@staticmethod @staticmethod
def couldAssertIsNowFalse(interface): def couldAssertIsNowFalse(interface: "TreeInterfaceDownstream"):
interface.send_assert_cancel() LoserState._to_NoInfo(interface)
interface.assert_timer.stop() print('couldAssertIsNowFalse, L -> NI')
interface.assert_state = AssertState.NoInfo @staticmethod
interface.assert_winner_metric = AssertMetric.infinite_assert_metric() def couldAssertIsNowTrue(interface: "TreeInterfaceDownstream"):
LoserState._to_NoInfo(interface)
interface.rprint('couldAssertIsNowFalse, W -> NI') print('couldAssertIsNowTrue, L -> NI')
@staticmethod @staticmethod
def couldAssertIsNowTrue(interface): def winnerLivelinessTimerExpires(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" LoserState._to_NoInfo(interface)
print('winnerLivelinessTimerExpires, L -> NI')
@staticmethod @staticmethod
def winnerLivelinessTimerExpires(interface): def receivedPruneOrJoinOrGraft(interface: "TreeInterfaceDownstream"):
assert False, "this should never ocurr" interface.send_assert()
print('receivedPruneOrJoinOrGraft, L -> L')
@staticmethod @staticmethod
def receivedPruneOrJoinOrGraft(interface): def _to_NoInfo(interface: "TreeInterfaceDownstream"):
pass #interface.assert_timer.stop()
interface.clear_assert_timer()
interface.set_assert_state(AssertState.NoInfo)
interface.set_assert_winner_metric(AssertMetric.infinite_assert_metric())
class AssertState(): class AssertState():
......
...@@ -133,7 +133,8 @@ class NoInfo(DownstreamStateABS): ...@@ -133,7 +133,8 @@ class NoInfo(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream @type interface: TreeInterfaceDownstreamDownstream
""" """
assert False #assert False
return
@staticmethod @staticmethod
def PTexpires(interface: "TreeInterfaceDownstream"): def PTexpires(interface: "TreeInterfaceDownstream"):
...@@ -142,7 +143,8 @@ class NoInfo(DownstreamStateABS): ...@@ -142,7 +143,8 @@ class NoInfo(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream @type interface: TreeInterfaceDownstreamDownstream
""" """
assert False #assert False
return
@staticmethod @staticmethod
def is_now_RPF_Interface(interface: "TreeInterfaceDownstream"): def is_now_RPF_Interface(interface: "TreeInterfaceDownstream"):
...@@ -230,7 +232,8 @@ class PrunePending(DownstreamStateABS): ...@@ -230,7 +232,8 @@ class PrunePending(DownstreamStateABS):
#pt = interface.get_pt() #pt = interface.get_pt()
#pt.start(interface.get_lpht() - pim_globals.JT_OVERRIDE_INTERVAL) #pt.start(interface.get_lpht() - pim_globals.JT_OVERRIDE_INTERVAL)
interface.set_prune_timer(prune_holdtime - pim_globals.JT_OVERRIDE_INTERVAL) #interface.set_prune_timer(prune_holdtime - pim_globals.JT_OVERRIDE_INTERVAL)
interface.set_prune_timer(interface.get_received_prune_holdtime() - pim_globals.JT_OVERRIDE_INTERVAL)
interface.send_pruneecho() interface.send_pruneecho()
...@@ -245,7 +248,8 @@ class PrunePending(DownstreamStateABS): ...@@ -245,7 +248,8 @@ class PrunePending(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream @type interface: TreeInterfaceDownstreamDownstream
""" """
assert False #assert False
return
@staticmethod @staticmethod
def is_now_RPF_Interface(interface: "TreeInterfaceDownstream"): def is_now_RPF_Interface(interface: "TreeInterfaceDownstream"):
...@@ -259,6 +263,8 @@ class PrunePending(DownstreamStateABS): ...@@ -259,6 +263,8 @@ class PrunePending(DownstreamStateABS):
#interface.get_ppt().stop() #interface.get_ppt().stop()
interface.clear_prune_pending_timer() interface.clear_prune_pending_timer()
interface.set_prune_state(DownstreamState.NoInfo)
print('is_now_RPF_Interface, PP -> NI') print('is_now_RPF_Interface, PP -> NI')
@staticmethod @staticmethod
...@@ -293,7 +299,8 @@ class Pruned(DownstreamStateABS): ...@@ -293,7 +299,8 @@ class Pruned(DownstreamStateABS):
# ppt.set_timer(interface.get_lpht()) # ppt.set_timer(interface.get_lpht())
# ppt.reset() # ppt.reset()
# todo nao percebo... corrigir 0 # todo nao percebo... corrigir 0
if holdtime > 0: #if holdtime > 0:
if interface.get_received_prune_holdtime() > interface.remaining_prune_timer():
interface.set_prune_timer(holdtime) interface.set_prune_timer(holdtime)
print('receivedPrune, P -> P') print('receivedPrune, P -> P')
...@@ -334,7 +341,8 @@ class Pruned(DownstreamStateABS): ...@@ -334,7 +341,8 @@ class Pruned(DownstreamStateABS):
@type interface: TreeInterfaceDownstreamDownstream @type interface: TreeInterfaceDownstreamDownstream
""" """
assert False #assert False
return
@staticmethod @staticmethod
def PTexpires(interface: "TreeInterfaceDownstream"): def PTexpires(interface: "TreeInterfaceDownstream"):
...@@ -358,6 +366,7 @@ class Pruned(DownstreamStateABS): ...@@ -358,6 +366,7 @@ class Pruned(DownstreamStateABS):
# todo ver melhor # todo ver melhor
#interface.get_pt().stop() #interface.get_pt().stop()
interface.clear_prune_timer() interface.clear_prune_timer()
interface.set_prune_state(DownstreamState.NoInfo)
print('is_now_RPF_Interface, P -> NI') print('is_now_RPF_Interface, P -> NI')
...@@ -372,7 +381,8 @@ class Pruned(DownstreamStateABS): ...@@ -372,7 +381,8 @@ class Pruned(DownstreamStateABS):
#pt = interface.get_pt() #pt = interface.get_pt()
#pt.set_timer(interface.get_lpht()) #pt.set_timer(interface.get_lpht())
#pt.reset() #pt.reset()
interface.set_prune_timer(interface.get_lpht()) #interface.set_prune_timer(interface.get_lpht())
interface.set_prune_timer(interface.get_received_prune_holdtime())
print('send_state_refresh, P -> P') print('send_state_refresh, P -> P')
......
...@@ -13,3 +13,7 @@ OVERRIDE_INTERVAL = 2.5 ...@@ -13,3 +13,7 @@ OVERRIDE_INTERVAL = 2.5
REFRESH_INTERVAL = 60 # State Refresh Interval REFRESH_INTERVAL = 60 # State Refresh Interval
SOURCE_LIFETIME = 210 SOURCE_LIFETIME = 210
T_LIMIT = 210 T_LIMIT = 210
ASSERT_CANCEL_METRIC = 0xFFFFFFFF
\ No newline at end of file
from abc import ABCMeta, abstractmethod
class LocalMembershipStateABC(metaclass=ABCMeta):
@staticmethod
@abstractmethod
def has_members():
raise NotImplementedError
class NoInfo(LocalMembershipStateABC):
@staticmethod
def has_members():
return False
class Include(LocalMembershipStateABC):
@staticmethod
def has_members():
return True
class LocalMembership():
NoInfo = NoInfo()
Include = Include()
\ No newline at end of file
''' import ipaddress
Created on Sep 8, 2014
@author: alex
'''
class AssertMetric(object): class AssertMetric(object):
''' '''
Note: we consider the node name the ip of the metric. Note: we consider the node name the ip of the metric.
''' '''
def __init__(self): def __init__(self, metric_preference: int or float = float("Inf"), route_metric: int or float = float("Inf"), ip_address: str = "0.0.0.0"):
''' if type(ip_address) is str:
@type tree_if: TreeInterface ip_address = ipaddress.ip_address(ip_address)
'''
self._pref = None
self._metric = None
self._node = None
def is_worse_than(self, other):
if self._pref != other.pref:
return self._pref > other.pref
elif self._metric != other.metric: self._metric_preference = metric_preference
return self._metric > other.metric self._route_metric = route_metric
self._ip_address = ip_address
def is_better_than(self, other):
if self.metric_preference != other.metric_preference:
return self.metric_preference < other.metric_preference
elif self.route_metric != other.route_metric:
return self.route_metric < other.route_metric
else: else:
return self._node.__str__() <= other.node.__str__() return self.ip_address > other.ip_address
@property def is_worse(self, other):
def pref(self): return not self.is_better_than(other)
return self._pref
@property
def metric(self):
return self._metric
@property
def node(self):
return self._node
@staticmethod @staticmethod
def infinite_assert_metric(): def infinite_assert_metric():
''' '''
@type metric: AssertMetric @type metric: AssertMetric
''' '''
metric = AssertMetric() return AssertMetric(metric_preference=float("Inf"), route_metric=float("Inf"), ip_address="0.0.0.0")
metric._pref = 1
metric._metric = float("Inf")
metric._node = ""
return metric
@staticmethod @staticmethod
def spt_assert_metric(tree_if): def spt_assert_metric(tree_if):
...@@ -59,15 +37,40 @@ class AssertMetric(object): ...@@ -59,15 +37,40 @@ class AssertMetric(object):
@type metric: AssertMetric @type metric: AssertMetric
@type tree_if: TreeInterface @type tree_if: TreeInterface
''' '''
metric = AssertMetric() (source_ip, _) = tree_if.get_tree_id()
import UnicastRouting
metric_preference, metric_cost = UnicastRouting.get_metric(source_ip)
return AssertMetric(metric_preference, metric_cost, tree_if.get_ip())
def i_am_assert_winner(self, tree_if):
interface_ip = ipaddress.ip_address(tree_if.get_ip())
return self._ip_address == interface_ip
@property
def metric_preference(self):
return self._metric_preference
@metric_preference.setter
def metric_preference(self, value):
self._metric_preference = value
metric._pref = 1 # TODO: ver isto melhor no route preference @property
metric._metric = tree_if.metric def route_metric(self):
metric._node = tree_if.node return self._route_metric
@route_metric.setter
def route_metric(self, value):
self._route_metric = value
@property
def ip_address(self):
return self._ip_address
return metric @ip_address.setter
def ip_address(self, value):
if type(value) is str:
value = ipaddress.ip_address(value)
# overrides self._ip_address = value
def __str__(self):
return "AssertMetric<{}:{}:{}>".format(self._pref, self._metric,
self._node)
...@@ -7,6 +7,7 @@ Created on Jul 16, 2015 ...@@ -7,6 +7,7 @@ Created on Jul 16, 2015
#from convergence import Convergence #from convergence import Convergence
#from des.event.timer import Timer #from des.event.timer import Timer
from threading import Timer from threading import Timer
from CustomTimer.RemainingTimer import RemainingTimer
from .assert_ import AssertState, AssertStateABC from .assert_ import AssertState, AssertStateABC
#from .messages.assert_msg import SFMRAssertMsg #from .messages.assert_msg import SFMRAssertMsg
#from .messages.reset import SFMResetMsg #from .messages.reset import SFMResetMsg
...@@ -22,18 +23,18 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -22,18 +23,18 @@ class TreeInterfaceDownstream(TreeInterface):
TreeInterface.__init__(self, kernel_entry, interface_id) TreeInterface.__init__(self, kernel_entry, interface_id)
# State # State
self._local_membership_state = None # todo NoInfo or Include #self._local_membership_state = None # todo NoInfo or Include
# Prune State # Prune State
self._prune_state = DownstreamState.NoInfo #self._prune_state = DownstreamState.NoInfo
self._prune_pending_timer = None #self._prune_pending_timer = None
self._prune_timer = None #self._prune_timer = None
# Assert Winner State # Assert Winner State
self._assert_state = AssertState.Winner #self._assert_state = AssertState.NoInfo
self._assert_timer = None #self._assert_timer = None
self._assert_winner_ip = None #self._assert_winner_ip = None
self._assert_winner_metric = None #self._assert_winner_metric = None
#self.set_dipt_timer() #self.set_dipt_timer()
#self.send_prune() #self.send_prune()
...@@ -58,6 +59,9 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -58,6 +59,9 @@ class TreeInterfaceDownstream(TreeInterface):
def is_prune_timer_running(self): def is_prune_timer_running(self):
return self._prune_timer is not None and self._prune_timer.is_alive() return self._prune_timer is not None and self._prune_timer.is_alive()
def remaining_prune_timer(self):
return 0 if not self._prune_timer else self._prune_timer.time_remaining()
########################################## ##########################################
# Set timers # Set timers
########################################## ##########################################
...@@ -72,7 +76,8 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -72,7 +76,8 @@ class TreeInterfaceDownstream(TreeInterface):
def set_prune_timer(self, time): def set_prune_timer(self, time):
self.clear_prune_timer() self.clear_prune_timer()
self._prune_timer = Timer(time, self.prune_timeout) #self._prune_timer = Timer(time, self.prune_timeout)
self._prune_timer = RemainingTimer(time, self.prune_timeout)
self._prune_timer.start() self._prune_timer.start()
def clear_prune_timer(self): def clear_prune_timer(self):
...@@ -88,27 +93,32 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -88,27 +93,32 @@ class TreeInterfaceDownstream(TreeInterface):
def prune_timeout(self): def prune_timeout(self):
self._prune_state.PTexpires(self) self._prune_state.PTexpires(self)
########################################### ###########################################
# Recv packets # Recv packets
########################################### ###########################################
def recv_data_msg(self):
self._assert_state.receivedDataFromDownstreamIf(self)
# Override # Override
def recv_prune_msg(self): def recv_prune_msg(self, upstream_neighbor_address, holdtime):
self._prune_state.receivedPrune(self, 0) super().recv_prune_msg(upstream_neighbor_address, holdtime)
# set here???
self.set_receceived_prune_holdtime(holdtime)
self._prune_state.receivedPrune(self, holdtime)
# Override # Override
def recv_join_msg(self): def recv_join_msg(self, upstream_neighbor_address):
super().recv_join_msg(upstream_neighbor_address)
self._prune_state.receivedJoin(self) self._prune_state.receivedJoin(self)
# Override # Override
def recv_graft_msg(self): def recv_graft_msg(self, upstream_neighbor_address):
super().recv_graft_msg(upstream_neighbor_address)
self._prune_state.receivedGraft(self) self._prune_state.receivedGraft(self)
# Override # Override
def is_forwarding(self): def is_forwarding(self):
return ((len(self.get_interface().neighbors) >= 1 and not self.is_pruned()) or self.igmp_has_members()) and not self.lost_assert() return ((len(self.get_interface().neighbors) >= 1 and not self.is_pruned()) or self.igmp_has_members()) and not self.lost_assert()
...@@ -133,15 +143,6 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -133,15 +143,6 @@ class TreeInterfaceDownstream(TreeInterface):
def get_metric(self): def get_metric(self):
return AssertMetric.spt_assert_metric(self) return AssertMetric.spt_assert_metric(self)
def _set_assert_state(self, value: AssertStateABC):
with self.get_state_lock():
if value != self._assert_state:
self._assert_state = value
self.change_tree()
self.evaluate_ingroup()
#Convergence.mark_change()
def _get_winner_metric(self): def _get_winner_metric(self):
''' '''
@rtype: SFMRAssertMetric @rtype: SFMRAssertMetric
......
...@@ -24,6 +24,9 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -24,6 +24,9 @@ class TreeInterfaceUpstream(TreeInterface):
self._originator_state = None self._originator_state = None
if self.is_S_directly_conn():
self._graft_prune_state.sourceIsNowDirectConnect(self)
########################################## ##########################################
# Set state # Set state
########################################## ##########################################
...@@ -95,7 +98,7 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -95,7 +98,7 @@ class TreeInterfaceUpstream(TreeInterface):
########################################### ###########################################
def recv_data_msg(self): def recv_data_msg(self):
# todo check olist # todo check olist
if self.is_olist_null() and not self.is_prune_limit_timer_running(): if self.is_olist_null() and not self.is_prune_limit_timer_running() and not self.is_S_directly_conn():
self._graft_prune_state.dataArrivesRPFinterface_OListNull_PLTstoped(self) self._graft_prune_state.dataArrivesRPFinterface_OListNull_PLTstoped(self)
def recv_state_refresh_msg(self, prune_indicator: int): def recv_state_refresh_msg(self, prune_indicator: int):
...@@ -105,11 +108,13 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -105,11 +108,13 @@ class TreeInterfaceUpstream(TreeInterface):
elif prune_indicator == 0 and not self.is_prune_limit_timer_running(): elif prune_indicator == 0 and not self.is_prune_limit_timer_running():
self._graft_prune_state.stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(self) self._graft_prune_state.stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(self)
def recv_join_msg(self): def recv_join_msg(self, upstream_neighbor_address):
super().recv_join_msg(upstream_neighbor_address)
# todo check rpf nbr # todo check rpf nbr
self._graft_prune_state.seeJoinToRPFnbr(self) self._graft_prune_state.seeJoinToRPFnbr(self)
def recv_prune_msg(self): def recv_prune_msg(self, upstream_neighbor_address, holdtime):
super().recv_prune_msg(upstream_neighbor_address, holdtime)
self._graft_prune_state.seePrune(self) self._graft_prune_state.seePrune(self)
def recv_graft_ack_msg(self): def recv_graft_ack_msg(self):
...@@ -128,8 +133,11 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -128,8 +133,11 @@ class TreeInterfaceUpstream(TreeInterface):
########################################### ###########################################
# Changes on Unicast Routing Table # Changes on Unicast Routing Table
########################################### ###########################################
# todo def change_rpf(self, olist_is_null):
if olist_is_null:
self._graft_prune_state.RPFnbrChanges_olistIsNull()
else:
self._graft_prune_state.RPFnbrChanges_olistIsNotNull()
#Override #Override
def is_forwarding(self): def is_forwarding(self):
...@@ -149,5 +157,5 @@ class TreeInterfaceUpstream(TreeInterface): ...@@ -149,5 +157,5 @@ class TreeInterfaceUpstream(TreeInterface):
@property @property
def t_override(self): def t_override(self):
oi = self.get_interface()._override_internal oi = self.get_interface()._override_interval
return random.uniform(0, oi) return random.uniform(0, oi)
...@@ -12,7 +12,7 @@ import traceback ...@@ -12,7 +12,7 @@ import traceback
#from sfmr.messages.prune import SFMRPruneMsg #from sfmr.messages.prune import SFMRPruneMsg
#from .router_interface import SFMRInterface #from .router_interface import SFMRInterface
from .downstream_prune import DownstreamState from .downstream_prune import DownstreamState
from .assert_ import AssertState from .assert_ import AssertState, AssertStateABC
from Packet.PacketPimGraft import PacketPimGraft from Packet.PacketPimGraft import PacketPimGraft
from Packet.PacketPimGraftAck import PacketPimGraftAck from Packet.PacketPimGraftAck import PacketPimGraftAck
...@@ -23,6 +23,10 @@ from Packet.Packet import Packet ...@@ -23,6 +23,10 @@ from Packet.Packet import Packet
from Packet.PacketPimJoinPrune import PacketPimJoinPrune from Packet.PacketPimJoinPrune import PacketPimJoinPrune
from Packet.PacketPimAssert import PacketPimAssert from Packet.PacketPimAssert import PacketPimAssert
from Packet.PacketPimStateRefresh import PacketPimStateRefresh from Packet.PacketPimStateRefresh import PacketPimStateRefresh
from .metric import AssertMetric
from threading import Timer
from .local_membership import LocalMembership
from .globals import *
class TreeInterface(metaclass=ABCMeta): class TreeInterface(metaclass=ABCMeta):
def __init__(self, kernel_entry, interface_id): def __init__(self, kernel_entry, interface_id):
...@@ -44,14 +48,16 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -44,14 +48,16 @@ class TreeInterface(metaclass=ABCMeta):
interface_name = Main.kernel.vif_index_to_name_dic[interface_id] interface_name = Main.kernel.vif_index_to_name_dic[interface_id]
igmp_interface = Main.igmp_interfaces[interface_name] # type: InterfaceIGMP igmp_interface = Main.igmp_interfaces[interface_name] # type: InterfaceIGMP
group_state = igmp_interface.interface_state.get_group_state(kernel_entry.group_ip) group_state = igmp_interface.interface_state.get_group_state(kernel_entry.group_ip)
self._igmp_has_members = group_state.add_multicast_routing_entry(self) #self._igmp_has_members = group_state.add_multicast_routing_entry(self)
igmp_has_members = group_state.add_multicast_routing_entry(self)
self._local_membership_state = LocalMembership.Include if igmp_has_members else LocalMembership.NoInfo
except: except:
#traceback.print_exc() #traceback.print_exc()
self._igmp_has_members = False self._local_membership_state = LocalMembership.NoInfo
# Local Membership State # Local Membership State
self._local_membership_state = None # todo NoInfo or Include #self._local_membership_state = None # todo NoInfo or Include
# Prune State # Prune State
self._prune_state = DownstreamState.NoInfo self._prune_state = DownstreamState.NoInfo
...@@ -59,35 +65,104 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -59,35 +65,104 @@ class TreeInterface(metaclass=ABCMeta):
self._prune_timer = None self._prune_timer = None
# Assert Winner State # Assert Winner State
self._assert_state = AssertState.Winner self._assert_state = AssertState.NoInfo
self._assert_winner_metric = AssertMetric()
self._assert_timer = None self._assert_timer = None
self._assert_winner_ip = None #self._assert_winner_ip = None
self._assert_winner_metric = None #self._assert_winner_metric = None
# Received prune hold time
self._received_prune_holdtime = None
self._igmp_lock = RLock() self._igmp_lock = RLock()
#self.rprint('new ' + self.__class__.__name__) #self.rprint('new ' + self.__class__.__name__)
############################################
# Set ASSERT State
############################################
def set_assert_state(self, new_state: AssertStateABC):
with self.get_state_lock():
if new_state != self._assert_state:
self._assert_state = new_state
self.change_tree()
self.evaluate_ingroup()
def set_assert_winner_metric(self, new_assert_metric: AssertMetric):
import ipaddress
with self.get_state_lock():
try:
old_neighbor = self.get_interface().get_neighbor(str(self._assert_winner_metric.ip_address))
new_neighbor = self.get_interface().get_neighbor(str(new_assert_metric.ip_address))
if old_neighbor is not None:
old_neighbor.unsubscribe_nlt_expiration(self)
if new_neighbor is not None:
new_neighbor.subscribe_nlt_expiration(self)
'''
if new_assert_metric.ip_address == ipaddress.ip_address("0.0.0.0") or new_assert_metric.ip_address is None:
if old_neighbor is not None:
old_neighbor.unsubscribe_nlt_expiration(self)
else:
old_neighbor.unsubscribe_nlt_expiration(self)
new_neighbor.subscribe_nlt_expiration(self)
'''
finally:
self._assert_winner_metric = new_assert_metric
############################################
# ASSERT Timer
############################################
def set_assert_timer(self, time):
self.clear_assert_timer()
self._assert_timer = Timer(time, self.assert_timeout)
self._assert_timer.start()
def clear_assert_timer(self):
if self._assert_timer is not None:
self._assert_timer.cancel()
def assert_timeout(self):
self._assert_state.assertTimerExpires(self)
def recv_data_msg(self): def recv_data_msg(self):
pass pass
def recv_assert_msg(self): def recv_assert_msg(self, received_metric: AssertMetric):
pass if self._assert_winner_metric.is_better_than(received_metric):
# received inferior assert
if self._assert_winner_metric.ip_address == received_metric.ip_address:
# received from assert winner
self._assert_state.receivedInferiorMetricFromWinner(self)
elif self.could_assert():
# received from non assert winner and could_assert
self._assert_state.receivedInferiorMetricFromNonWinner_couldAssertIsTrue(self)
else:
#received preferred assert
self._assert_state.receivedPreferedMetric(self, received_metric)
def recv_reset_msg(self): def recv_reset_msg(self):
pass pass
def recv_prune_msg(self): def recv_prune_msg(self, upstream_neighbor_address, holdtime):
pass if upstream_neighbor_address == self.get_ip():
self._assert_state.receivedPruneOrJoinOrGraft(self)
def recv_join_msg(self): def recv_join_msg(self, upstream_neighbor_address):
pass if upstream_neighbor_address == self.get_ip():
self._assert_state.receivedPruneOrJoinOrGraft(self)
def recv_graft_msg(self): def recv_graft_msg(self, upstream_neighbor_address):
pass if upstream_neighbor_address == self.get_ip():
self._assert_state.receivedPruneOrJoinOrGraft(self)
def recv_graft_ack_msg(self): def recv_graft_ack_msg(self):
pass pass
...@@ -139,12 +214,17 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -139,12 +214,17 @@ class TreeInterface(metaclass=ABCMeta):
def send_prune(self): def send_prune(self, holdtime=None):
if holdtime is None:
holdtime = T_LIMIT
print("send prune") print("send prune")
try: try:
(source, group) = self.get_tree_id() (source, group) = self.get_tree_id()
# todo help ip of ph # todo help ip of ph
ph = PacketPimJoinPrune("123.123.123.123", 210) #ph = PacketPimJoinPrune("123.123.123.123", 210)
ph = PacketPimJoinPrune("123.123.123.123", holdtime)
ph.add_multicast_group(PacketPimJoinPruneMulticastGroup(group, pruned_src_addresses=[source])) ph.add_multicast_group(PacketPimJoinPruneMulticastGroup(group, pruned_src_addresses=[source]))
pckt = Packet(payload=PacketPimHeader(ph)) pckt = Packet(payload=PacketPimHeader(ph))
...@@ -155,13 +235,22 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -155,13 +235,22 @@ class TreeInterface(metaclass=ABCMeta):
def send_pruneecho(self): def send_pruneecho(self):
print("send prune echo") holdtime = T_LIMIT
try:
(source, group) = self.get_tree_id()
# todo help ip of ph
ph = PacketPimJoinPrune(self.get_ip(), holdtime)
ph.add_multicast_group(PacketPimJoinPruneMulticastGroup(group, pruned_src_addresses=[source]))
pckt = Packet(payload=PacketPimHeader(ph))
self.get_interface().send(pckt.bytes())
print("send prune echo")
except:
return
# todo # todo
#msg = PruneMsg(self.get_tree().tree_id, #msg = PruneMsg(self.get_tree().tree_id,
# self.get_node(), self._assert_timer.time_left()) # self.get_node(), self._assert_timer.time_left())
#self.pim_if.send_mcast(msg) #self.pim_if.send_mcast(msg)
return
def send_join(self): def send_join(self):
print("send join") print("send join")
...@@ -183,17 +272,13 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -183,17 +272,13 @@ class TreeInterface(metaclass=ABCMeta):
def send_assert(self): def send_assert(self):
print("send assert") print("send assert")
import UnicastRouting
try: try:
(source, group) = self.get_tree_id() (source, group) = self.get_tree_id()
(entry_protocol, entry_cost) = UnicastRouting.get_metric(source) assert_metric = self.my_assert_metric()
# todo help ip of ph ph = PacketPimAssert(multicast_group_address=group, source_address=source, metric_preference=assert_metric.metric_preference, metric=assert_metric.route_metric)
ph = PacketPimAssert(multicast_group_address=group, source_address=source, metric_preference=entry_protocol, metric=entry_cost)
pckt = Packet(payload=PacketPimHeader(ph)) pckt = Packet(payload=PacketPimHeader(ph))
self.get_interface().send(pckt.bytes()) self.get_interface().send(pckt.bytes())
#msg = AssertMsg(self.tree_id, self.assert_metric)
#self.pim_if.send_mcast(msg)
except: except:
return return
...@@ -201,22 +286,37 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -201,22 +286,37 @@ class TreeInterface(metaclass=ABCMeta):
def send_assert_cancel(self): def send_assert_cancel(self):
print("send cancel") print("send assert cancel")
try:
(source, group) = self.get_tree_id()
ph = PacketPimAssert(multicast_group_address=group, source_address=source, metric_preference=1, metric=float("Inf"))
pckt = Packet(payload=PacketPimHeader(ph))
self.get_interface().send(pckt.bytes())
except:
return
#msg = AssertMsg.new_assert_cancel(self.tree_id) #msg = AssertMsg.new_assert_cancel(self.tree_id)
#self.pim_if.send_mcast(msg) #self.pim_if.send_mcast(msg)
pass
def send_state_refresh(self):
# todo time
self._assert_state.sendStateRefresh(self)
@abstractmethod @abstractmethod
def is_forwarding(self): def is_forwarding(self):
pass pass
def nbr_died(self, node): def nbr_died(self):
pass pass
def nbr_connected(self): def nbr_connected(self):
pass pass
def assert_winner_nlt_expires(self):
self._assert_state.winnerLivelinessTimerExpires(self)
#@abstractmethod #@abstractmethod
def is_now_root(self): def is_now_root(self):
pass pass
...@@ -231,18 +331,24 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -231,18 +331,24 @@ class TreeInterface(metaclass=ABCMeta):
def evaluate_ingroup(self): def evaluate_ingroup(self):
self._kernel_entry.evaluate_olist_change() self._kernel_entry.evaluate_olist_change()
#############################################################
# Local Membership (IGMP)
############################################################
def notify_igmp(self, has_members: bool): def notify_igmp(self, has_members: bool):
with self.get_state_lock(): with self.get_state_lock():
#with self._igmp_lock: with self._igmp_lock:
if has_members != self._igmp_has_members: if has_members != self._local_membership_state.has_members():
self._igmp_has_members = has_members #self._igmp_has_members = has_members
self.change_tree() self._local_membership_state = LocalMembership.Include if has_members else LocalMembership.NoInfo
self.evaluate_ingroup() self.change_tree()
self.evaluate_ingroup()
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._igmp_has_members
return self._local_membership_state.has_members()
def rprint(self, msg, *entrys): def rprint(self, msg, *entrys):
return return
...@@ -294,7 +400,41 @@ class TreeInterface(metaclass=ABCMeta): ...@@ -294,7 +400,41 @@ class TreeInterface(metaclass=ABCMeta):
if not self.is_assert_winner(): if not self.is_assert_winner():
return self._assert_winner_ip return self._assert_winner_ip
else: else:
return self._kernel_entry._rpf_node return self._kernel_entry.rpf_node
def is_assert_winner(self): def is_assert_winner(self):
return not self.is_downstream() and not self._assert_state == AssertState.Loser return not self.is_downstream() and not self._assert_state == AssertState.Loser
\ No newline at end of file
def is_S_directly_conn(self):
return self._kernel_entry.rpf_node == self._kernel_entry.source_ip
def set_receceived_prune_holdtime(self, holdtime):
self._received_prune_holdtime = holdtime
def get_received_prune_holdtime(self):
return self._received_prune_holdtime
###################################################
# ASSERT
###################################################
def lost_assert(self):
if not self.is_downstream():
return False
else:
return not AssertMetric.i_am_assert_winner(self) and \
self._assert_winner_metric.is_better_than(AssertMetric.spt_assert_metric(self))
def could_assert(self):
return self.is_downstream()
def my_assert_metric(self):
'''
The assert metric of this interface for usage in assert state machine
@rtype: AssertMetric
'''
if self.could_assert():
return AssertMetric.spt_assert_metric(self)
else:
return AssertMetric.infinite_assert_metric()
...@@ -130,15 +130,12 @@ class UpstreamStateABC(metaclass=ABCMeta): ...@@ -130,15 +130,12 @@ class UpstreamStateABC(metaclass=ABCMeta):
raise NotImplementedError() raise NotImplementedError()
class AckPending(UpstreamStateABC): class Forward(UpstreamStateABC):
""" """
AckPending (AP) Forwarding (F)
The router was in the Pruned(P) state, but a transition has This is the starting state of the Upsteam(S,G) state machine.
occurred in the Downstream(S,G) state machine for one of this The state machine is in this state if it just started or if
(S,G) entry’s outgoing interfaces, indicating that traffic from S oiflist(S,G) != NULL.
addressed to G should again be forwarded. A Graft message has
been sent to RPF’(S), but a Graft Ack message has not yet been
received.
""" """
@staticmethod @staticmethod
...@@ -150,9 +147,19 @@ class AckPending(UpstreamStateABC): ...@@ -150,9 +147,19 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
if not interface.is_S_directly_conn():
interface.set_state(UpstreamState.Pruned)
#assert False #interface.get_ot().stop()
return
#timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
interface.send_prune()
print("dataArrivesRPFinterface_OListNull_PLTstoped, F -> P")
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"):
...@@ -165,7 +172,7 @@ class AckPending(UpstreamStateABC): ...@@ -165,7 +172,7 @@ class AckPending(UpstreamStateABC):
#interface.set_ot() #interface.set_ot()
interface.set_override_timer() interface.set_override_timer()
print('stateRefreshArrivesRPFnbr_pruneIs1, AP -> AP') print('stateRefreshArrivesRPFnbr_pruneIs1, F -> F')
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -177,13 +184,8 @@ class AckPending(UpstreamStateABC): ...@@ -177,13 +184,8 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print(UpstreamState.Forward)
interface.set_state(UpstreamState.Forward)
#interface.get_grt().cancel()
interface.clear_graft_retry_timer()
print( print(
'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, AP -> P') 'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, F -> F')
@staticmethod @staticmethod
def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"): def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"):
...@@ -196,7 +198,7 @@ class AckPending(UpstreamStateABC): ...@@ -196,7 +198,7 @@ class AckPending(UpstreamStateABC):
#interface.cancel_ot() #interface.cancel_ot()
interface.clear_override_timer() interface.clear_override_timer()
print('seeJoinToRPFnbr, P -> P') print('seeJoinToRPFnbr, F -> F')
@staticmethod @staticmethod
def seePrune(interface: "TreeInterfaceUpstream"): def seePrune(interface: "TreeInterfaceUpstream"):
...@@ -205,11 +207,11 @@ class AckPending(UpstreamStateABC): ...@@ -205,11 +207,11 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.set_ot() #interface.set_ot()
interface.set_override_timer() if not interface.is_S_directly_conn():
interface.set_override_timer()
interface.rprint('seePrune, AP -> AP') print('seePrune, F -> F')
@staticmethod @staticmethod
def OTexpires(interface: "TreeInterfaceUpstream"): def OTexpires(interface: "TreeInterfaceUpstream"):
...@@ -218,9 +220,10 @@ class AckPending(UpstreamStateABC): ...@@ -218,9 +220,10 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_join() if not interface.is_S_directly_conn():
interface.send_join()
interface.rprint('OTexpires, AP -> AP') print('OTexpires, F -> F')
@staticmethod @staticmethod
def olistIsNowNull(interface: "TreeInterfaceUpstream"): def olistIsNowNull(interface: "TreeInterfaceUpstream"):
...@@ -229,20 +232,18 @@ class AckPending(UpstreamStateABC): ...@@ -229,20 +232,18 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Pruned) print("is direct con -> ", interface.is_S_directly_conn())
if not interface.is_S_directly_conn():
#timer = interface._prune_limit_timer interface.set_state(UpstreamState.Pruned)
#timer.set_timer(interface.t_override)
interface.set_prune_limit_timer()
#timer.start()
#interface.get_grt().stop() #timer = interface._prune_limit_timer
interface.clear_graft_retry_timer() #timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
interface.send_prune() interface.send_prune()
print("olistIsNowNull, AP -> P") print("olistIsNowNull, F -> P")
@staticmethod @staticmethod
def olistIsNowNotNull(interface: "TreeInterfaceUpstream"): def olistIsNowNotNull(interface: "TreeInterfaceUpstream"):
...@@ -263,12 +264,15 @@ class AckPending(UpstreamStateABC): ...@@ -263,12 +264,15 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_graft() if not interface.is_S_directly_conn():
interface.send_graft()
#interface.get_grt().reset() #interface.get_grt().start()
interface.set_graft_retry_timer() interface.set_graft_retry_timer()
print('olistIsNowNotNull, AP -> AP') interface.set_state(UpstreamState.AckPending)
print('RPFnbrChanges_olistIsNotNull, F -> AP')
@staticmethod @staticmethod
def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"): def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"):
...@@ -278,10 +282,9 @@ class AckPending(UpstreamStateABC): ...@@ -278,10 +282,9 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_grt().cancel() interface.set_state(UpstreamState.Pruned)
interface.clear_graft_retry_timer()
print('RPFnbrChanges_olistIsNull, AP -> P') print('RPFnbrChanges_olistIsNull, F -> P')
@staticmethod @staticmethod
def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"): def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"):
...@@ -290,11 +293,7 @@ class AckPending(UpstreamStateABC): ...@@ -290,11 +293,7 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Forward) print("sourceIsNowDirectConnect, F -> F")
#interface.get_grt().stop()
interface.clear_graft_retry_timer()
print("sourceIsNowDirectConnect, AP -> F")
@staticmethod @staticmethod
def GRTexpires(interface: "TreeInterfaceUpstream"): def GRTexpires(interface: "TreeInterfaceUpstream"):
...@@ -303,12 +302,8 @@ class AckPending(UpstreamStateABC): ...@@ -303,12 +302,8 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#assert False
#interface.get_grt().start() return
interface.set_graft_retry_timer()
interface.send_graft()
print('GRTexpires, AP -> AP')
@staticmethod @staticmethod
def recvGraftAckFromRPFnbr(interface: "TreeInterfaceUpstream"): def recvGraftAckFromRPFnbr(interface: "TreeInterfaceUpstream"):
...@@ -317,21 +312,15 @@ class AckPending(UpstreamStateABC): ...@@ -317,21 +312,15 @@ class AckPending(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print('recvGraftAckFromRPFnbr, F -> F')
interface.set_state(UpstreamState.Forward)
#interface.get_grt().stop()
interface.clear_graft_retry_timer()
print('recvGraftAckFromRPFnbr, AP -> F')
class Forward(UpstreamStateABC): class Pruned(UpstreamStateABC):
""" '''
Forwarding (F) Pruned (P)
This is the starting state of the Upsteam(S,G) state machine. The set, olist(S,G), is empty.
The state machine is in this state if it just started or if The router will not forward data from S addressed to group G.
oiflist(S,G) != NULL. '''
"""
@staticmethod @staticmethod
def dataArrivesRPFinterface_OListNull_PLTstoped(interface: "TreeInterfaceUpstream"): def dataArrivesRPFinterface_OListNull_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -342,18 +331,17 @@ class Forward(UpstreamStateABC): ...@@ -342,18 +331,17 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Pruned) if not interface.is_S_directly_conn():
#interface.set_state(UpstreamState.Pruned)
#interface.get_ot().stop() # todo send prune?!?!?!?!
#timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
interface.send_prune() #timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
print("dataArrivesRPFinterface_OListNull_PLTstoped, F -> P") print("dataArrivesRPFinterface_OListNull_PLTstoped, P -> P")
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"):
...@@ -363,10 +351,10 @@ class Forward(UpstreamStateABC): ...@@ -363,10 +351,10 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.set_ot() #interface.get_plt().reset()
interface.set_override_timer() interface.set_prune_limit_timer()
print('stateRefreshArrivesRPFnbr_pruneIs1, F -> F') interface.rprint('stateRefreshArrivesRPFnbr_pruneIs1, P -> P')
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -377,9 +365,16 @@ class Forward(UpstreamStateABC): ...@@ -377,9 +365,16 @@ class Forward(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.set_prune_limit_timer()
print( print(
'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, F -> F') 'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, P -> P')
@staticmethod @staticmethod
def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"): def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"):
...@@ -388,11 +383,9 @@ class Forward(UpstreamStateABC): ...@@ -388,11 +383,9 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
# Do nothing
#interface.cancel_ot() print('seeJoinToRPFnbr, P -> P')
interface.clear_override_timer()
print('seeJoinToRPFnbr, F -> F')
@staticmethod @staticmethod
def seePrune(interface: "TreeInterfaceUpstream"): def seePrune(interface: "TreeInterfaceUpstream"):
...@@ -401,10 +394,8 @@ class Forward(UpstreamStateABC): ...@@ -401,10 +394,8 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.set_ot()
interface.set_override_timer()
print('seePrune, F -> F') print('seePrune, P -> P')
@staticmethod @staticmethod
def OTexpires(interface: "TreeInterfaceUpstream"): def OTexpires(interface: "TreeInterfaceUpstream"):
...@@ -413,9 +404,9 @@ class Forward(UpstreamStateABC): ...@@ -413,9 +404,9 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_join()
print('OTexpires, F -> F') #assert False
return
@staticmethod @staticmethod
def olistIsNowNull(interface: "TreeInterfaceUpstream"): def olistIsNowNull(interface: "TreeInterfaceUpstream"):
...@@ -424,16 +415,8 @@ class Forward(UpstreamStateABC): ...@@ -424,16 +415,8 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Pruned) #assert False
return
#timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
interface.send_prune()
print("olistIsNowNull, F -> P")
@staticmethod @staticmethod
def olistIsNowNotNull(interface: "TreeInterfaceUpstream"): def olistIsNowNotNull(interface: "TreeInterfaceUpstream"):
...@@ -442,8 +425,15 @@ class Forward(UpstreamStateABC): ...@@ -442,8 +425,15 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#assert False if not interface.is_S_directly_conn():
return interface.send_graft()
#interface.get_grt().start()
interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending)
print('olistIsNowNotNull, P -> AP')
@staticmethod @staticmethod
def RPFnbrChanges_olistIsNotNull(interface: "TreeInterfaceUpstream"): def RPFnbrChanges_olistIsNotNull(interface: "TreeInterfaceUpstream"):
...@@ -454,14 +444,15 @@ class Forward(UpstreamStateABC): ...@@ -454,14 +444,15 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_graft() if not interface.is_S_directly_conn():
interface.send_graft()
#interface.get_grt().start() #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('olistIsNowNotNull, P -> AP')
@staticmethod @staticmethod
def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"): def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"):
...@@ -471,9 +462,11 @@ class Forward(UpstreamStateABC): ...@@ -471,9 +462,11 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Pruned) #interface.get_plt().stop()
if not interface.is_S_directly_conn():
interface.clear_prune_limit_timer()
print('RPFnbrChanges_olistIsNull, F -> P') print('RPFnbrChanges_olistIsNull, P -> P')
@staticmethod @staticmethod
def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"): def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"):
...@@ -482,7 +475,7 @@ class Forward(UpstreamStateABC): ...@@ -482,7 +475,7 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print("sourceIsNowDirectConnect, F -> F") print("sourceIsNowDirectConnect, P -> P")
@staticmethod @staticmethod
def GRTexpires(interface: "TreeInterfaceUpstream"): def GRTexpires(interface: "TreeInterfaceUpstream"):
...@@ -501,15 +494,19 @@ class Forward(UpstreamStateABC): ...@@ -501,15 +494,19 @@ class Forward(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print('recvGraftAckFromRPFnbr, P -> P')
print('recvGraftAckFromRPFnbr, P -> P')
class Pruned(UpstreamStateABC): class AckPending(UpstreamStateABC):
''' """
Pruned (P) AckPending (AP)
The set, olist(S,G), is empty. The router was in the Pruned(P) state, but a transition has
The router will not forward data from S addressed to group G. occurred in the Downstream(S,G) state machine for one of this
''' (S,G) entry’s outgoing interfaces, indicating that traffic from S
addressed to G should again be forwarded. A Graft message has
been sent to RPF’(S), but a Graft Ack message has not yet been
received.
"""
@staticmethod @staticmethod
def dataArrivesRPFinterface_OListNull_PLTstoped(interface: "TreeInterfaceUpstream"): def dataArrivesRPFinterface_OListNull_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -520,16 +517,9 @@ class Pruned(UpstreamStateABC): ...@@ -520,16 +517,9 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.set_state(UpstreamState.Pruned)
# todo send prune?!?!?!?!
#timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
#timer.start()
interface.set_prune_limit_timer()
print("dataArrivesRPFinterface_OListNull_PLTstoped, P -> P") #assert False
return
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs1(interface: "TreeInterfaceUpstream"):
...@@ -539,10 +529,10 @@ class Pruned(UpstreamStateABC): ...@@ -539,10 +529,10 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_plt().reset() #interface.set_ot()
interface.set_prune_limit_timer() interface.set_override_timer()
interface.rprint('stateRefreshArrivesRPFnbr_pruneIs1, P -> P') print('stateRefreshArrivesRPFnbr_pruneIs1, AP -> AP')
@staticmethod @staticmethod
def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"): def stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped(interface: "TreeInterfaceUpstream"):
...@@ -553,16 +543,13 @@ class Pruned(UpstreamStateABC): ...@@ -553,16 +543,13 @@ 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.set_state(UpstreamState.Forward)
interface.set_prune_limit_timer() #interface.get_grt().cancel()
interface.clear_graft_retry_timer()
print( print(
'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, P -> P') 'stateRefreshArrivesRPFnbr_pruneIs0_PLTstoped, AP -> P')
@staticmethod @staticmethod
def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"): def seeJoinToRPFnbr(interface: "TreeInterfaceUpstream"):
...@@ -571,9 +558,11 @@ class Pruned(UpstreamStateABC): ...@@ -571,9 +558,11 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
# Do nothing
print('seeJoinToRPFnbr, P -> P') #interface.cancel_ot()
interface.clear_override_timer()
print('seeJoinToRPFnbr, AP -> AP')
@staticmethod @staticmethod
def seePrune(interface: "TreeInterfaceUpstream"): def seePrune(interface: "TreeInterfaceUpstream"):
...@@ -583,7 +572,10 @@ class Pruned(UpstreamStateABC): ...@@ -583,7 +572,10 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print('seePrune, P -> P') #interface.set_ot()
interface.set_override_timer()
interface.rprint('seePrune, AP -> AP')
@staticmethod @staticmethod
def OTexpires(interface: "TreeInterfaceUpstream"): def OTexpires(interface: "TreeInterfaceUpstream"):
...@@ -592,9 +584,9 @@ class Pruned(UpstreamStateABC): ...@@ -592,9 +584,9 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_join()
#assert False interface.rprint('OTexpires, AP -> AP')
return
@staticmethod @staticmethod
def olistIsNowNull(interface: "TreeInterfaceUpstream"): def olistIsNowNull(interface: "TreeInterfaceUpstream"):
...@@ -603,8 +595,20 @@ class Pruned(UpstreamStateABC): ...@@ -603,8 +595,20 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#assert False interface.set_state(UpstreamState.Pruned)
return
#timer = interface._prune_limit_timer
#timer.set_timer(interface.t_override)
interface.set_prune_limit_timer()
#timer.start()
#interface.get_grt().stop()
interface.clear_graft_retry_timer()
interface.send_prune()
print("olistIsNowNull, AP -> P")
@staticmethod @staticmethod
def olistIsNowNotNull(interface: "TreeInterfaceUpstream"): def olistIsNowNotNull(interface: "TreeInterfaceUpstream"):
...@@ -613,14 +617,8 @@ class Pruned(UpstreamStateABC): ...@@ -613,14 +617,8 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_graft() #assert False
return
#interface.get_grt().start()
interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending)
print('olistIsNowNotNull, P -> AP')
@staticmethod @staticmethod
def RPFnbrChanges_olistIsNotNull(interface: "TreeInterfaceUpstream"): def RPFnbrChanges_olistIsNotNull(interface: "TreeInterfaceUpstream"):
...@@ -631,14 +629,13 @@ class Pruned(UpstreamStateABC): ...@@ -631,14 +629,13 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
interface.send_graft() if not interface.is_S_directly_conn():
interface.send_graft()
#interface.get_grt().start()
interface.set_graft_retry_timer()
interface.set_state(UpstreamState.AckPending) #interface.get_grt().reset()
interface.set_graft_retry_timer()
print('olistIsNowNotNull, P -> AP') print('olistIsNowNotNull, AP -> AP')
@staticmethod @staticmethod
def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"): def RPFnbrChanges_olistIsNull(interface: "TreeInterfaceUpstream"):
...@@ -648,10 +645,11 @@ class Pruned(UpstreamStateABC): ...@@ -648,10 +645,11 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#interface.get_plt().stop() #interface.get_grt().cancel()
interface.clear_prune_limit_timer() if not interface.is_S_directly_conn():
interface.clear_graft_retry_timer()
print('RPFnbrChanges_olistIsNull, P -> P') print('RPFnbrChanges_olistIsNull, AP -> P')
@staticmethod @staticmethod
def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"): def sourceIsNowDirectConnect(interface: "TreeInterfaceUpstream"):
...@@ -660,7 +658,11 @@ class Pruned(UpstreamStateABC): ...@@ -660,7 +658,11 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print("sourceIsNowDirectConnect, P -> P") interface.set_state(UpstreamState.Forward)
#interface.get_grt().stop()
interface.clear_graft_retry_timer()
print("sourceIsNowDirectConnect, AP -> F")
@staticmethod @staticmethod
def GRTexpires(interface: "TreeInterfaceUpstream"): def GRTexpires(interface: "TreeInterfaceUpstream"):
...@@ -669,8 +671,12 @@ class Pruned(UpstreamStateABC): ...@@ -669,8 +671,12 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
#assert False
return #interface.get_grt().start()
interface.set_graft_retry_timer()
interface.send_graft()
print('GRTexpires, AP -> AP')
@staticmethod @staticmethod
def recvGraftAckFromRPFnbr(interface: "TreeInterfaceUpstream"): def recvGraftAckFromRPFnbr(interface: "TreeInterfaceUpstream"):
...@@ -680,8 +686,11 @@ class Pruned(UpstreamStateABC): ...@@ -680,8 +686,11 @@ class Pruned(UpstreamStateABC):
@type interface: TreeInterfaceUpstream @type interface: TreeInterfaceUpstream
""" """
print('recvGraftAckFromRPFnbr, P -> P') interface.set_state(UpstreamState.Forward)
#interface.get_grt().stop()
interface.clear_graft_retry_timer()
print('recvGraftAckFromRPFnbr, AP -> F')
class UpstreamState(): class UpstreamState():
Forward = Forward() Forward = Forward()
......
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