Source code for NetworkSim.architecture.base.ring

__all__ = ["Ring"]
__author__ = ["Hongyi Yang"]

import numpy as np


[docs]class Ring: """ Ring class to store packets on both control and data rings. Packets can be added or removed from the ring. Time of addition of the packet is recorded to track packet location. Parameters ---------- model : Model The network model used. Default is ``Model()``. time_unit : str The time unit used for the simulation, chosen from the following: - 'ns' - 's' Default is ``'ns'`` Attributes ---------- ring_id : int The ID of the ring. Default is ``None``. nodes_location : array Array of locations of the nodes on the ring, in meters. packets : list List of packets present on the ring, containing: - `raw_packet` : str The raw packet string. - `generation_timestamp` : float Time when the packet was generated and stored into the RAM. - `transmission_timestamp` : float Time when the packet was added onto the ring. - `packet_entry_point` : float The location (in meters) where the packet was added. - `entry_node_id` : int The ID of the node where the packet was added. - `destination_node_id` : int The ID of the destination of the packet. packet_record : list A list containing the information on all packet transmission on the ring, including the columns: - `Generation Timestamp` : float The timestamp when the packet is generated and stored in the RAM. - `Transmission Timestamp` : float The timestamp when the packet is added onto the ring by the transmitter. - `Reception Timestamp` : float The timestamp when the packet is received by the receiver. - `Raw Packet` : str The raw packet content. - `Source Node` : int The ID of the source node. - `Destination Node` : int The ID of the destination node. - `Status` : str The status of the packet, can be ``added`` or ``removed``. - Total Packet Count : int The total number of packets on the ring at the time of the operation. """ def __init__( self, model, ring_id=None, time_unit='ns', reversed=False ): self.model = model self.ring_id = ring_id self.nodes_location = self.get_nodes_location() self.packets = [] self.packet_count = 0 self.packet_record = [] self.time_unit = time_unit self.reversed = reversed
[docs] def get_nodes_location(self): """ Get locations of all nodes in the ring. Returns ------- locations : numpy array An array of node locations. """ locations = np.linspace(start=0, stop=self.model.network.length, num=self.model.network.num_nodes + 1) return locations[:-1]
[docs] def add_packet(self, node_id, destination_id, packet, generation_timestamp, transmission_timestamp): """ Packet addition to the ring. The packet added will be in the format `[raw_packet, timestamp, node_id]`. Parameters ---------- node_id : int The ID of the node at which the packet is added. destination_id : int The ID of the destination node of the packet. packet : str The packet string added onto the ring. generation_timestamp : float The timestamp when the packet is generated. transmission_timestamp : float The timestamp when the packet is added. """ # Check input types if not isinstance(node_id, int): raise ValueError('Input node_id must be an integer.') # Add packet to the ring self.packets.append([ packet, generation_timestamp, transmission_timestamp, self.nodes_location[node_id], node_id, destination_id ]) self.packet_count += 1 self.packet_record.append([ generation_timestamp, transmission_timestamp, None, packet, node_id, destination_id, 'added', self.packet_count ])
[docs] def remove_packet(self, node_id, packet, reception_timestamp): """ Packet removal from the ring. Parameters ---------- node_id : int The ID of the node where the packet is removed. packet : packet The packet to be removed from the ring, containing: - `raw_packet` - `generation_timestamp` - `transmission_timestamp` - `packet_entry_point` - `entry_node_id` - `destination_node_id` reception_timestamp : float The timestamp at which the packet is removed. """ self.packets.remove(packet) self.packet_count -= 1 self.packet_record.append([ packet[1], packet[2], reception_timestamp, packet[0], packet[4], node_id, 'removed', self.packet_count ])
[docs] def check_packet(self, current_time, node_id): """ Packet existence check. Parameters ---------- current_time : float Current time when the packet is checked. node_id : int Id of the node at which the check is performed. Returns ------- existence : bool The existence of the packet. ``True`` when a packet exists. packet : packet The packet information, containing: - `raw_packet` - `generation_timestamp` - `transmission_timestamp` - `packet_entry_point` - `entry_node_id` - `destination_node_id` """ # Check input if not isinstance(node_id, int): raise ValueError('Input node_id must be an integer.') # Check presence of packet based on current time for packet in self.packets: # Compare current location of packet with node location with time in ns if self.time_unit == 'ns': _new_location = packet[3] + (current_time - packet[2]) * self.model.constants.get('speed') * 1e-9 elif self.time_unit == 's': _new_location = packet[3] + (current_time - packet[2]) * self.model.constants.get('speed') else: raise NotImplementedError('Unknown time unit of the simulation.') new_location_on_ring = _new_location % self.model.network.length # Calculate location on reversed ring if self.reversed: new_location_on_ring = packet[3] - (new_location_on_ring - packet[3]) if new_location_on_ring < 0: new_location_on_ring += self.model.network.length elif new_location_on_ring > self.model.network.length: new_location_on_ring -= self.model.network.length # Update location when near end of the ring and causing no detection error if np.isclose(new_location_on_ring, self.model.network.length, atol=1e-2): new_location_on_ring = 0 if np.isclose(new_location_on_ring, self.nodes_location[node_id], atol=1e-2): return True, packet # No packet present return False, None