def write_host_data(host): ''' Description: This function writes the data to the two host output files. Arguments: host (Host) Return Values: None. Global Variables: None. Limitations: None. Known Bugs: None. Revision History: 2015/11/29: Created and filled in. ''' host_name = host.host_name # --- WRITE TO DATA FILES --- # Compute the packet receive rate for this host (in Mbps) data_pkts_rec_Mb = cv.bytes_to_Mb(host.pkts_received * ct.PACKET_DATA_SIZE) pkts_received_rate = data_pkts_rec_Mb / ct.DELTA_SECS # Compute the ack packet receive rate for this host (in Mbps) ack_pkts_rec_Mb = cv.bytes_to_Mb(host.ack_received * ct.PACKET_ACK_SIZE) ack_received_rate = host.ack_received / ct.DELTA_SECS # Get the string to write out to the host recs file host_receive_row = str(host_name) + "," + str(pkts_received_rate) + "," + \ str(ack_received_rate) + "\n" host_receives.write(host_receive_row) # Compute the packet send rate for this host (in Mbps/sec) data_pkts_sent_Mb = cv.bytes_to_Mb(host.pkts_sent * ct.PACKET_DATA_SIZE) pkts_send_rate = data_pkts_sent_Mb / ct.DELTA_SECS # Compute the ack packet send rate for this host (in Mbps/sec) ack_pkts_sent_Mb = cv.bytes_to_Mb(host.ack_sent * ct.PACKET_ACK_SIZE) ack_send_rate = ack_pkts_sent_Mb / ct.DELTA_SECS # Get the string to write out to the host_sends file host_send_row = str(host_name) + "," + str(pkts_send_rate) + "," + \ str(ack_send_rate) + "\n" host_sends.write(host_send_row) # Reset the pkts_received, ack_received, pkts_sent, and ack_sent attributes # for this host so that the next interval measures a new rate host.pkts_received = 0 host.ack_received = 0 host.pkts_sent = 0 host.ack_sent = 0
def handoff_packet(self, list_sender): ''' Description: This changes all the appropriate variables so the Link reflects that it no longer has the Packet on it. It then allows the endpoint to receive the Packet. Arguments: list_sender ([sender_index]) - A list containing the index of the sender in the shared arrays. Shared Variables: data_on_link (WRITE) - Decremented to show data has been taken off Link. packets_on_link (WRITE) - Packet popped off of Link. ep_names (READ) - Used to get the name of the endpoint. Global Variables: sim.packets (READ) - Used to get the size of data being taken off of the Link. sim.endpoints (READ) - Used to obtain endpoint object. Limitations: None. Known Bugs: None. Revision History: 2015/11/16: Created ''' # Unpack the argument list, which has the sender in it. [sender_index] = list_sender # Take the packet off of the link by removing it from the queue. [time, flow_name, packet_ID] = \ heapq.heappop(self.packets_on_link[sender_index]) packet_size = sim.packets[(flow_name, packet_ID)].size # in bytes self.data_on_link -= cv.bytes_to_Mb(packet_size) # Use the sender index to figure out the receiver index. rcv_index = (sender_index + 1) % 2 # Now "hand off" the packet to the host/router. ep = sim.endpoints[self.ep_names[rcv_index]] ep.receive_packet([flow_name, packet_ID])
def put_packet_on_link(self, arg_list): ''' Description: This puts a Packet on the Link. It then enqueues some Event. One will check after transmission time if there is another Packet that can go in the same direction. One will check wait for transmission time then reset the in_transmission flag. One waits for the Packet to reach the other end to see if there is a Packet waiting to go the opposite direction, and the last is for the other end to receive the Packet. Arguments: arg_list ([]) - Unused. Return Values: None. Shared Variables: buffers (READ/WRITE) - Read to see if there is anything to put on the Link, written if something is taken off of the buffer to put on the link. packets_on_link (READ/WRITE) - Read to see direction of travel and written to put Packet on the Link. in_transmission (WRITE) - Written to True when a packet is being transmitted. data_on_link (WRITE) - The amount of data on the Link is updated. Global Variables: None. Limitations: None. Known Bugs: None. Revision History: 2015/10/22: Created function handle and docstring 2015/10/29: Filled function in. 2015/11/03: Changed the link buffers to use the python queue data structure and only store the flow_name and packet_name 2015/11/16: Now checks for next packet to put on Link and creates Event for it. ''' # If there is a packet in transmission, we cannot put anything on the # link. if self.in_transmission: return # If there are no packets in either buffer, then we have no business # here. if len(self.buffers[0]) == 0 and len(self.buffers[1]) == 0: return # Get which buffer to pop a packet from next (0 or 1) data_src, next_pop = self.get_next_buffer_pop() # Now that we know the source of the next packet, we know if it goes on # right away. If the next packet will go in the same direction of # travel as the other packets, put it on the link. Otherwise, we # must wait until the link is clear to send it the opposite # direction. if (next_pop == data_src and not self.in_transmission) or \ data_src == -1: # We are sending a packet, so set the in_transmission flag. self.in_transmission = True # The next packet will go in the same direction as data on the # link. Pop the packet from the link buffer [time, flow_name, packet_ID] = heapq.heappop( self.buffers[next_pop]) # Put it on the link and use the current time so we can heapify # more easily. Subtract from the buffer load to reflect that the # packet is no longer on the buffer heapq.heappush(self.packets_on_link[next_pop], (sim.network_now(), flow_name, packet_ID)) packet_size = sim.packets[(flow_name, packet_ID)].size # in bytes self.buffer_load[next_pop] -= cv.bytes_to_KB(packet_size) self.data_on_link += cv.bytes_to_Mb(packet_size) # Calculate the transmission time as the size of the packet # divided by the link capacity (aka rate). packet_size = sim.packets[(flow_name, packet_ID)].size transmission_time = (cv.bytes_to_Mb(packet_size) / self.rate) transmission_time /= 1000 # To get it in ms # Create an event after this packet's transmission to reset the # in_transmission flag. Subtract a small amount of time to # assure it happens before the next call of this function. reset_time = sim.network_now() + transmission_time - ct.TIME_BIT reset_event = e.Event(self.link_name, 'reset_in_transmission', []) sim.enqueue_event(reset_time, reset_event) # Create an event to check if we should send another packet after # transmission. pkt1_time = sim.network_now() + transmission_time pkt1_event = e.Event(self.link_name, 'put_packet_on_link', []) sim.enqueue_event(pkt1_time, pkt1_event) # Enqueue the event for the opposite end to receive the packet. # This occurs at the same time as the transmission plus delay # event. rcv_time = pkt1_time + self.delay rcv_event = e.Event(self.link_name, 'handoff_packet', [next_pop]) sim.enqueue_event(rcv_time, rcv_event) # If we are not sending another packet after transmission, we need # to also have an event that checks after propagation. Because # we do not know yet, we must make the event no matter what. pkt2_time = rcv_time pkt2_event = e.Event(self.link_name, 'put_packet_on_link', []) sim.enqueue_event(pkt2_time, pkt2_event)