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