def handle_routing_packet(self, packet, dynamic): """ Updates the cost and routing tables using the given routing packet :param packet: Routing packet to update tables for :type packet: RoutingPacket :param dynamic: Whether we're handling a dynamic or static packet :type dynamic: bool :return: Nothing :rtype: None """ # No routing table yet. Begin creation, then handle this packet if not self._get_intermediate_routing_table(dynamic): self.create_routing_table(dynamic) did_update = False cost_table = packet.costTable src_id = packet.src.id # Get the appropriate routing table routing_table = self._get_intermediate_routing_table(dynamic) # Update costs by adding the cost to travel to the source node src_cost = routing_table[src_id].cost for identifier in cost_table.keys(): cost_table[identifier] = cost_table[identifier] + src_cost src_link = routing_table[src_id].link # Update our routing table based on the received table for identifier, cost in cost_table.items(): # New entry to tables or smaller cost if identifier not in routing_table or \ cost < routing_table[identifier].cost: did_update = True routing_table[identifier] = LinkCostTuple(src_link, cost) # Store and broadcast the updated table if an update occurred if did_update: self.sameDataCounter = 0 self.store_routing_table(dynamic, routing_table) new_cost_table = self.cost_table_from_routing_table(dynamic) self.broadcast_table(new_cost_table, dynamic) else: self.sameDataCounter += 1 # Log the same data receipt Logger.debug(Network.get_time(), "%s received no new routing table " "data." % self) # Log finalized routing table Logger.trace( Network.get_time(), "%s final %s routing table:" % (self, "dynamic" if dynamic else "static")) if dynamic: self.handle_same_dynamic_routing_table()
def handle_routing_packet(self, packet, dynamic): """ Updates the cost and routing tables using the given routing packet :param packet: Routing packet to update tables for :type packet: RoutingPacket :param dynamic: Whether we're handling a dynamic or static packet :type dynamic: bool :return: Nothing :rtype: None """ # No routing table yet. Begin creation, then handle this packet if not self._get_intermediate_routing_table(dynamic): self.create_routing_table(dynamic) did_update = False cost_table = packet.costTable src_id = packet.src.id # Get the appropriate routing table routing_table = self._get_intermediate_routing_table(dynamic) # Update costs by adding the cost to travel to the source node src_cost = routing_table[src_id].cost for identifier in cost_table.keys(): cost_table[identifier] = cost_table[identifier] + src_cost src_link = routing_table[src_id].link # Update our routing table based on the received table for identifier, cost in cost_table.items(): # New entry to tables or smaller cost if identifier not in routing_table or \ cost < routing_table[identifier].cost: did_update = True routing_table[identifier] = LinkCostTuple(src_link, cost) # Store and broadcast the updated table if an update occurred if did_update: self.sameDataCounter = 0 self.store_routing_table(dynamic, routing_table) new_cost_table = self.cost_table_from_routing_table(dynamic) self.broadcast_table(new_cost_table, dynamic) else: self.sameDataCounter += 1 # Log the same data receipt Logger.debug(Network.get_time(), "%s received no new routing table " "data." % self) # Log finalized routing table Logger.trace(Network.get_time(), "%s final %s routing table:" % (self, "dynamic" if dynamic else "static")) if dynamic: self.handle_same_dynamic_routing_table()
def update_dynamic_routing_table(self, routing_table): """ Replace the old dynamicRoutingTable with the given new one :param routing_table: Routing table to update the old one with :type routing_table: dict[str, LinkCostTuple] :return: Nothing :rtype: None """ Logger.trace(Network.get_time(), "%s:" % self) Logger.trace(Network.get_time(), "Replacing old dynamic routing table:") self.print_routing_table(self.dynamicRoutingTable) Logger.trace(Network.get_time(), "With new dynamic routing table:") self.print_routing_table(self.newDynamicRoutingTable) self.dynamicRoutingTable = routing_table
def create_routing_table(self, dynamic=None): """ Begins creation of a routing table by broadcasting adjacent link costs :param dynamic: Whether to create a dynamic or static routing table :type dynamic: bool :return: Nothing :rtype: None """ if not dynamic: dynamic = self.dynamicEnabled # Only add the dynamic routing table update timer once if dynamic and not self.dynamicRoutingTableTimerAdded: self.add_timer(UpdateDynamicRoutingTableEvent(None, self), Network.get_time(), DYNAMIC_UPDATE_INTERVAL) self.dynamicRoutingTableTimerAdded = True # Reset the dynamic routing table same data counter self.sameDataCounter = 0 # Initialize cost of reaching oneself as 0 routing_table = {self.id: LinkCostTuple(None, 0)} # Create cost table to broadcast with costs of this router's neighbors # { node_id : cost } cost_table = {} for link in self.links: # Get the dynamic or static cost of the link cost = link.dynamic_cost() if dynamic else link.static_cost() other_node_id = link.other_node(self).id cost_table[other_node_id] = cost routing_table[other_node_id] = LinkCostTuple(link, cost) self.store_routing_table(dynamic, routing_table) self.broadcast_table(cost_table, dynamic)
def update_dynamic_routing_table(self, routing_table): """ Replace the old dynamicRoutingTable with the given new one :param routing_table: Routing table to update the old one with :type routing_table: dict[str, LinkCostTuple] :return: Nothing :rtype: None """ Logger.trace(Network.get_time(), "%s:" % self) Logger.trace(Network.get_time(), "Replacing old dynamic routing table:") self.print_routing_table(self.dynamicRoutingTable) Logger.trace(Network.get_time(), "With new dynamic routing table:") self.print_routing_table(self.newDynamicRoutingTable) self.dynamicRoutingTable = routing_table
def create_routing_table(self, dynamic=None): """ Begins creation of a routing table by broadcasting adjacent link costs :param dynamic: Whether to create a dynamic or static routing table :type dynamic: bool :return: Nothing :rtype: None """ if not dynamic: dynamic = self.dynamicEnabled # Only add the dynamic routing table update timer once if dynamic and not self.dynamicRoutingTableTimerAdded: self.add_timer(UpdateDynamicRoutingTableEvent(None, self), Network.get_time(), DYNAMIC_UPDATE_INTERVAL) self.dynamicRoutingTableTimerAdded = True # Reset the dynamic routing table same data counter self.sameDataCounter = 0 # Initialize cost of reaching oneself as 0 routing_table = {self.id: LinkCostTuple(None, 0)} # Create cost table to broadcast with costs of this router's neighbors # { node_id : cost } cost_table = {} for link in self.links: # Get the dynamic or static cost of the link cost = link.dynamic_cost() if dynamic else link.static_cost() other_node_id = link.other_node(self).id cost_table[other_node_id] = cost routing_table[other_node_id] = LinkCostTuple(link, cost) self.store_routing_table(dynamic, routing_table) self.broadcast_table(cost_table, dynamic)
def handle_same_dynamic_routing_table(self): """ Handle the receipt of a routing table that provided no updates. If we have seen the same data SAME_DATA_THRESHOLD times, dispatch an event to update the dynamic routing table in the future, and replace the old dynamic routing table with the new one. Otherwise re-broadcast the routing table. """ if self.sameDataCounter >= self.SAME_DATA_THRESHOLD: self.update_dynamic_routing_table(self.newDynamicRoutingTable) # Reset the dynamic cost for the links, we're done updating map(lambda l: l.reset_dynamic_cost(Network.get_time()), self.links) else: new_cost_table = self.cost_table_from_routing_table(dynamic=True) self.broadcast_table(new_cost_table, dynamic=True)
def broadcast_table(self, cost_table, dynamic): """ Broadcasts given table to all nodes this router is connected to. :param cost_table: Cost table to broadcast :type cost_table: dict[str, float] :param dynamic: Whether we're broadcasting dynamic/static routing table :type dynamic: bool :return: Nothing :rtype: None """ packet_type = DynamicRoutingPacket if dynamic else StaticRoutingPacket for link in self.links: packet = packet_type(deepcopy(cost_table), self, link.other_node(self)) self.send(packet, link, Network.get_time())
def handle_same_dynamic_routing_table(self): """ Handle the receipt of a routing table that provided no updates. If we have seen the same data SAME_DATA_THRESHOLD times, dispatch an event to update the dynamic routing table in the future, and replace the old dynamic routing table with the new one. Otherwise re-broadcast the routing table. """ if self.sameDataCounter >= self.SAME_DATA_THRESHOLD: self.update_dynamic_routing_table(self.newDynamicRoutingTable) # Reset the dynamic cost for the links, we're done updating map(lambda l: l.reset_dynamic_cost(Network.get_time()), self.links) else: new_cost_table = self.cost_table_from_routing_table(dynamic=True) self.broadcast_table(new_cost_table, dynamic=True)
def broadcast_table(self, cost_table, dynamic): """ Broadcasts given table to all nodes this router is connected to. :param cost_table: Cost table to broadcast :type cost_table: dict[str, float] :param dynamic: Whether we're broadcasting dynamic/static routing table :type dynamic: bool :return: Nothing :rtype: None """ packet_type = DynamicRoutingPacket if dynamic else StaticRoutingPacket for link in self.links: packet = packet_type(deepcopy(cost_table), self, link.other_node(self)) self.send(packet, link, Network.get_time())
def print_routing_table(routing_table): if not routing_table: Logger.trace(Network.get_time(), "None") return for i, j in routing_table.items(): Logger.trace(Network.get_time(), "\t%s: %s" % (i, j))
def print_routing_table(routing_table): if not routing_table: Logger.trace(Network.get_time(), "None") return for i, j in routing_table.items(): Logger.trace(Network.get_time(), "\t%s: %s" % (i, j))