Commit a890f223 authored by Pedro Oliveira's avatar Pedro Oliveira

react to new neighbors (resend state refresh msg/clear prune limit timer <-...

react to new neighbors (resend state refresh msg/clear prune limit timer <- based on downstream/upstream neighbor) & fix originator logger & remove dead code
parent 66b92c8d
......@@ -44,6 +44,7 @@ class InterfaceIGMP(Interface):
# bind to interface
rcv_s.bind((interface_name, 0x0800))
super().__init__(interface_name=interface_name, recv_socket=rcv_s, send_socket=snd_s, vif_index=vif_index)
self.interface_enabled = True
from igmp.RouterState import RouterState
self.interface_state = RouterState(self)
super()._enable()
......
......@@ -145,6 +145,9 @@ class InterfacePim(Interface):
self._had_neighbors = has_neighbors
Main.kernel.interface_change_number_of_neighbors()
def new_or_reset_neighbor(self, neighbor_ip):
Main.kernel.new_or_reset_neighbor(self.vif_index, neighbor_ip)
'''
def add_neighbor(self, ip, random_number, hello_hold_time):
with self.neighbors_lock.genWlock():
......@@ -187,18 +190,21 @@ class InterfacePim(Interface):
'''
def change_interface(self):
# check if ip change was already applied to interface
old_ip_address = self.ip_interface
new_ip_interface = netifaces.ifaddresses(self.interface_name)[netifaces.AF_INET][0]['addr']
if old_ip_address == new_ip_interface:
return
self._send_socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(new_ip_interface))
self._recv_socket.setsockopt(socket.IPPROTO_IP, socket.IP_DROP_MEMBERSHIP,
socket.inet_aton(Interface.MCAST_GRP) + socket.inet_aton(old_ip_address))
new_ip_interface = netifaces.ifaddresses(self.interface_name)[netifaces.AF_INET][0]['addr']
self._recv_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(Interface.MCAST_GRP) + socket.inet_aton(new_ip_interface))
self._send_socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(new_ip_interface))
self.ip_interface = new_ip_interface
import Main
Main.kernel.vif_dic[new_ip_interface] = Main.kernel.vif_dic.pop(old_ip_address)
'''
###########################################
......@@ -220,11 +226,14 @@ class InterfacePim(Interface):
with self.neighbors_lock.genWlock():
if ip not in self.neighbors:
if hello_hold_time == 0:
return
print("ADD NEIGHBOR")
from Neighbor import Neighbor
self.neighbors[ip] = Neighbor(self, ip, generation_id, hello_hold_time, state_refresh_capable)
self.force_send_hello()
self.check_number_of_neighbors()
self.new_or_reset_neighbor(ip)
return
else:
neighbor = self.neighbors[ip]
......
......@@ -337,7 +337,7 @@ class Kernel:
if ip_src in self.routing and ip_dst in self.routing[ip_src]:
return self.routing[ip_src][ip_dst]
elif create_if_not_existent:
kernel_entry = KernelEntry(ip_src, ip_dst, 0)
kernel_entry = KernelEntry(ip_src, ip_dst)
if ip_src not in self.routing:
self.routing[ip_src] = {}
......@@ -357,9 +357,38 @@ class Kernel:
self.routing[source_ip][group_ip].network_update()
# notify about changes at the interface (IP)
'''
def notify_interface_change(self, interface_name):
with self.interface_lock:
# check if interface was already added
if interface_name not in self.vif_name_to_index_dic:
return
print("trying to change ip")
pim_interface = self.pim_interface.get(interface_name)
if pim_interface:
old_ip = pim_interface.get_ip()
pim_interface.change_interface()
new_ip = pim_interface.get_ip()
if old_ip != new_ip:
self.vif_dic[new_ip] = self.vif_dic.pop(old_ip)
igmp_interface = self.igmp_interface.get(interface_name)
if igmp_interface:
igmp_interface.change_interface()
'''
# When interface changes number of neighbors verify if olist changes and prune/forward respectively
def interface_change_number_of_neighbors(self):
with self.rwlock.genWlock():
with self.rwlock.genRlock():
for groups_dict in self.routing.values():
for entry in groups_dict.values():
entry.change_at_number_of_neighbors()
# When new neighbor connects try to resend last state refresh msg (if AssertWinner)
def new_or_reset_neighbor(self, vif_index, neighbor_ip):
with self.rwlock.genRlock():
for groups_dict in self.routing.values():
for entry in groups_dict.values():
entry.new_or_reset_neighbor(vif_index, neighbor_ip)
import netifaces
import time
from prettytable import PrettyTable
import sys
import logging, logging.handlers
from TestLogger import RootFilter
#from InterfacePIM import InterfacePim
#from InterfaceIGMP import InterfaceIGMP
from Kernel import Kernel
#from threading import Lock
import UnicastRouting
interfaces = {} # interfaces with multicast routing enabled
......@@ -160,8 +160,6 @@ def stop():
def test(router_name, server_logger_ip):
global logger
import logging.handlers
from TestLogger import RootFilter
socketHandler = logging.handlers.SocketHandler(server_logger_ip,
logging.handlers.DEFAULT_TCP_LOGGING_PORT)
# don't bother with a formatter, since a socket handler sends the event as
......@@ -173,8 +171,6 @@ def test(router_name, server_logger_ip):
def main():
# logging
global logger
import sys
import logging, logging.handlers
logger = logging.getLogger('pim')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler(sys.stdout))
......
......@@ -45,7 +45,7 @@ class Neighbor:
# neighbor restarted
if self.generation_id != generation_id:
self.generation_id = generation_id
self.contact_interface.send_hello()
self.contact_interface.force_send_hello()
self.reset()
"""
......@@ -74,7 +74,7 @@ class Neighbor:
def reset(self):
return
self.contact_interface.new_or_reset_neighbor(self.ip)
def receive_hello(self, generation_id, hello_hold_time, state_refresh_capable):
......
......@@ -26,8 +26,8 @@ class PacketPimHelloOptions(metaclass=ABCMeta):
def parse_bytes(data: bytes, type:int = None, length:int = None):
(type, length) = struct.unpack(PacketPimHelloOptions.PIM_HDR_OPTS,
data[:PacketPimHelloOptions.PIM_HDR_OPTS_LEN])
print("TYPE:", type)
print("LENGTH:", length)
#print("TYPE:", type)
#print("LENGTH:", length)
data = data[PacketPimHelloOptions.PIM_HDR_OPTS_LEN:]
#return PIM_MSG_TYPES[type](data)
return PIM_MSG_TYPES.get(type, PacketPimHelloUnknown).parse_bytes(data, type, length)
......@@ -114,7 +114,7 @@ class PacketPimHelloHoldtime(PacketPimHelloOptions):
raise Exception
(holdtime, ) = struct.unpack(PacketPimHelloHoldtime.PIM_HDR_OPT,
data[:PacketPimHelloHoldtime.PIM_HDR_OPT_LEN])
print("HOLDTIME:", holdtime)
#print("HOLDTIME:", holdtime)
return PacketPimHelloHoldtime(holdtime=holdtime)
......@@ -142,7 +142,7 @@ class PacketPimHelloGenerationID(PacketPimHelloOptions):
raise Exception
(generation_id, ) = struct.unpack(PacketPimHelloGenerationID.PIM_HDR_OPT,
data[:PacketPimHelloGenerationID.PIM_HDR_OPT_LEN])
print("GenerationID:", generation_id)
#print("GenerationID:", generation_id)
return PacketPimHelloGenerationID(generation_id=generation_id)
......@@ -158,7 +158,7 @@ class PacketPimHelloUnknown(PacketPimHelloOptions):
'''
def __init__(self, type, length):
super().__init__(type=type, length=length)
print("PIM Hello Option Unknown... TYPE=", type, "LENGTH=", length)
#print("PIM Hello Option Unknown... TYPE=", type, "LENGTH=", length)
def bytes(self) -> bytes:
raise Exception
......
......@@ -64,7 +64,7 @@ class PacketPimStateRefresh:
msg = multicast_group_adress + source_address + originator_adress + \
struct.pack(self.PIM_HDR_STATE_REFRESH_WITHOUT_ADDRESSES, 0x7FFFFFFF & self.metric_preference,
self.metric, self.mask_len, self.ttl, prune_and_assert_flags, self. interval)
self.metric, self.mask_len, self.ttl, prune_and_assert_flags, self.interval)
return msg
......
......@@ -102,16 +102,17 @@ class UnicastRouting(object):
elif action == "RTM_NEWADDR" or action == "RTM_DELADDR":
# TODO ALTERACOES NA INTERFACE
'''
print(action)
print(msg)
interface_name = None
attrs = msg["attrs"]
for (key, value) in attrs:
print((key, value))
if key == "IFA_LABEL":
interface_name = value
break
pim_interface = Main.kernel.pim_interface.get(interface_name)
pim_interface.change_interface()
igmp_interface = Main.kernel.igmp_interface.get(interface_name)
Main.kernel.notify_interface_change(interface_name)
'''
pass
......
......@@ -12,7 +12,7 @@ class KernelEntry:
TREE_TIMEOUT = 180
KERNEL_LOGGER = logging.getLogger('pim.KernelEntry')
def __init__(self, source_ip: str, group_ip: str, inbound_interface_index: int):
def __init__(self, source_ip: str, group_ip: str):
self.kernel_entry_logger = logging.LoggerAdapter(KernelEntry.KERNEL_LOGGER, {'tree': '(' + source_ip + ',' + group_ip + ')'})
self.kernel_entry_logger.debug('Create KernelEntry')
......@@ -55,7 +55,7 @@ class KernelEntry:
for i in Main.kernel.vif_index_to_name_dic.keys():
try:
if i == self.inbound_interface_index:
self.interface_state[i] = TreeInterfaceUpstream(self, i, False)
self.interface_state[i] = TreeInterfaceUpstream(self, i)
else:
self.interface_state[i] = TreeInterfaceDownstream(self, i)
except:
......@@ -199,7 +199,7 @@ class KernelEntry:
# change type of interfaces
new_downstream_interface = TreeInterfaceDownstream(self, self.inbound_interface_index)
self.interface_state[self.inbound_interface_index] = new_downstream_interface
new_upstream_interface = TreeInterfaceUpstream(self, new_inbound_interface_index, False)
new_upstream_interface = TreeInterfaceUpstream(self, new_inbound_interface_index)
self.interface_state[new_inbound_interface_index] = new_upstream_interface
self.inbound_interface_index = new_inbound_interface_index
......@@ -223,6 +223,10 @@ class KernelEntry:
self.change()
self.evaluate_olist_change()
def new_or_reset_neighbor(self, if_index, neighbor_ip):
# todo maybe lock de interfaces
self.interface_state[if_index].new_or_reset_neighbor(neighbor_ip)
def is_olist_null(self):
for interface in self.interface_state.values():
if interface.is_forwarding():
......@@ -248,7 +252,6 @@ class KernelEntry:
return self.group_ip
def change(self):
# todo: changes on unicast routing or multicast routing...
with self._multicast_change:
Main.kernel.set_multicast_route(self)
......
......@@ -52,6 +52,8 @@ class Originator(OriginatorStateABC):
#print('Source no longer directly connected, O to NO')
tree.originator_logger.debug('Source no longer directly connected, O -> NO')
def __str__(self):
return 'O'
class NotOriginator(OriginatorStateABC):
@staticmethod
......@@ -79,6 +81,9 @@ class NotOriginator(OriginatorStateABC):
def SourceNotConnected(tree):
return
def __str__(self):
return 'NO'
class OriginatorState():
NotOriginator = NotOriginator()
......
......@@ -27,6 +27,9 @@ class TreeInterfaceDownstream(TreeInterface):
self.logger.debug('Created DownstreamInterface')
self.join_prune_logger.debug(str(self._prune_state))
# Last state refresh message sent (resend in case of new neighbors)
self._last_state_refresh_message = None
##########################################
# Set state
##########################################
......@@ -116,6 +119,10 @@ class TreeInterfaceDownstream(TreeInterface):
# Send messages
######################################
def send_state_refresh(self, state_refresh_msg_received):
if state_refresh_msg_received is None:
return
self._last_state_refresh_message = state_refresh_msg_received
if self.lost_assert() or not self.get_interface().is_state_refresh_enabled():
return
......@@ -167,9 +174,10 @@ class TreeInterfaceDownstream(TreeInterface):
# self._assert_winner_metric.is_better_than(AssertMetric.spt_assert_metric(self))
# Override
def nbr_connected(self):
# TODO resend last state refresh messages
return
# When new neighbor connects, send last state refresh msg
def new_or_reset_neighbor(self, neighbor_ip):
self.send_state_refresh(self._last_state_refresh_message)
# Override
def delete(self, change_type_interface=False):
......
......@@ -22,7 +22,7 @@ import Main
class TreeInterfaceUpstream(TreeInterface):
LOGGER = logging.getLogger('pim.KernelEntry.UpstreamInterface')
def __init__(self, kernel_entry, interface_id, is_originater: bool):
def __init__(self, kernel_entry, interface_id):
extra_dict_logger = kernel_entry.kernel_entry_logger.extra.copy()
extra_dict_logger['vif'] = interface_id
extra_dict_logger['interfacename'] = Main.kernel.vif_index_to_name_dic[interface_id]
......@@ -42,7 +42,8 @@ class TreeInterfaceUpstream(TreeInterface):
self._state_refresh_timer = None
self._source_active_timer = None
self._prune_now_counter = 0
self.originator_logger = logging.LoggerAdapter(TreeInterfaceUpstream.LOGGER, extra_dict_logger)
self.originator_logger = logging.LoggerAdapter(TreeInterfaceUpstream.LOGGER.getChild('Originator'), extra_dict_logger)
self.originator_logger.debug(str(self._originator_state))
if self.is_S_directly_conn():
self._graft_prune_state.sourceIsNowDirectConnect(self)
......@@ -89,6 +90,7 @@ class TreeInterfaceUpstream(TreeInterface):
def set_originator_state(self, new_state: OriginatorStateABC):
if new_state != self._originator_state:
self._originator_state = new_state
self.originator_logger.debug(str(new_state))
##########################################
# Check timers
......@@ -250,6 +252,12 @@ class TreeInterfaceUpstream(TreeInterface):
def change_on_unicast_routing(self, interface_change=False):
self.change_rpf(self.is_olist_null(), interface_change)
'''
if self.is_S_directly_conn():
self._graft_prune_state.sourceIsNowDirectConnect(self)
else:
self._originator_state.SourceNotConnected(self)
'''
def change_rpf(self, olist_is_null, interface_change=False):
current_rpf = self.get_neighbor_RPF()
......@@ -266,6 +274,11 @@ class TreeInterfaceUpstream(TreeInterface):
def is_forwarding(self):
return False
# If new/reset neighbor is RPF neighbor => clear prune limit timer
def new_or_reset_neighbor(self, neighbor_ip):
if neighbor_ip == self.get_neighbor_RPF():
self.clear_prune_limit_timer()
#Override
def delete(self, change_type_interface=False):
self.socket_is_enabled = False
......
......@@ -5,7 +5,7 @@ Created on Jul 16, 2015
'''
from abc import ABCMeta, abstractmethod
import Main
from threading import Lock, RLock
from threading import RLock
import traceback
from .downstream_prune import DownstreamState
......@@ -263,16 +263,12 @@ class TreeInterface(metaclass=ABCMeta):
def is_forwarding(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
@abstractmethod
def new_or_reset_neighbor(self, neighbor_ip):
raise NotImplementedError()
@abstractmethod
def delete(self, change_type_interface=False):
......
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