def receive(self, pkt, time): # Pass ACKs to flows to handle congestion control and dropped packets if (isinstance(pkt, packet.Ack)): pkt.flow.receiveAck(pkt, time) else: # Only send ACKs for packets we have not yet recieved # (next_pkt = pkt.number) or packets out of order # (next_pkt < pkt.number). # If first packet from flow, then set expected_pkt to 0. if self.expected_pkt.setdefault(pkt.flow.id, 0) <= pkt.number: # If the packet is the one we're expecting, # increment its value in next_packet. if self.expected_pkt[pkt.flow.id] == pkt.number: self.expected_pkt[pkt.flow.id] += 1 while self.expected_pkt[pkt.flow.id] in \ self.received_pkts.setdefault(pkt.flow.id, []): self.received_pkts[pkt.flow.id].remove( self.expected_pkt[pkt.flow.id]) self.expected_pkt[pkt.flow.id] += 1 else: self.received_pkts.setdefault(pkt.flow.id, []).append(pkt.number) ack = packet.makeAck(pkt.flow, self.expected_pkt[pkt.flow.id]) enqueue(event.SendPacket(time, ack, self.link, self)) pkt.flow.received_packets += 1
def handleTimeout(self, pkt, curr_time): # If unacknowledged, resend the packet + its timeout event if pkt.number in self.unacknowledged: self.window_size = 1 enqueue(event.SendPacket(curr_time, pkt, self.source.link, \ self.source)) enqueue(event.PacketTimeout(curr_time + self.timeout, pkt)) self.unacknowledged[pkt.number] = curr_time
def receive(self, pkt, time): # Record ACKed routing packet if (isinstance(pkt, packet.RtAck)): self.sent_rtpkts[pkt.rtpkt] = Router.PKT_ACKED # Handle received routing packet (update BF) elif (isinstance(pkt, packet.RoutingPkt)): if self.bf_updated.get(pkt.sender.id, False) == False: ack_link = self.rneighbours[pkt.sender.id] rt_ack = packet.RtAck(pkt) enqueue(event.SendPacket(time, rt_ack, ack_link, self)) if pkt.bf_round == self.bf_round: self.update_bf(pkt.sender.id, pkt.distvec, ack_link, time) # Forward packet on according to routing table else: next_link = link.Link.l_map[self.routing_table[pkt.recipient.id]] enqueue(event.SendPacket(time, pkt, next_link, self))
def broadcast_distvec(self, time): for rtr_id in self.rneighbours: link = self.rneighbours[rtr_id] dest = link.get_receiver(self) rtPkt = packet.RoutingPkt(self, dest, self.bf_distvec, \ self.bf_round) enqueue(event.SendPacket(time, rtPkt, link, self)) self.sent_rtpkts[rtPkt] = Router.PKT_SENT enqueue( event.RtPktTimeout(time + Router.RTPKT_TIMEOUT, self, rtPkt))
def makePacket(self, payload, number, start_time): # Makes a new packet and then enqueues SendPacket and PacketTimeout # events. pkt = packet.DataPkt(self.source, self.destination, payload, number, self) # We send the packet (put the event in the pqueue at the flow's start # time. enqueue( event.SendPacket(start_time, pkt, self.source.link, self.source)) enqueue(event.PacketTimeout(start_time + self.timeout, pkt))
def handle_timeout(self, curr_time, rtpkt): ''' Handle timeout for a routing packet ''' status = self.sent_rtpkts.get(rtpkt, None) # If it's been sent but not acknowledged, resend. if status == Router.PKT_SENT: send_link = self.rneighbours[rtpkt.recipient.id] enqueue(event.SendPacket(curr_time, rtpkt, send_link, self)) # If it's been acknowledged, remove it from the sent list. elif status == Router.PKT_ACKED: del self.sent_rtpkts[rtpkt]