def on_reception(self, t, received_packet): assert received_packet.receiver == self.host if self.debug: print("t={}: {} received packet {}".format(round(t, 6), self, received_packet)) ### Per-flow receive rate ### self.em.log_it('FLOW|{}'.format(self.i), 'T|{}|RCVE|{}'.format(t, received_packet.size)) # # OPERATIONS AGNOSTIC TO WHETHER WE'RE ESTABLISHED # if received_packet.ack_flag: # Got an ACK # Update window size and send_first_unacked. # Retransmit if needed if received_packet.ack_number < self.send_first_unacked: # TODO is this possible? assert False elif received_packet.ack_number == self.send_first_unacked: if received_packet.size == CONTROL_PACKET_SIZE: # Only non-data packets can be dupacks retransmit, self.window_size = self.cc.dupack(t) self.em.log_it( 'FLOW|{}'.format(self.i), 'T|{}|WINDOW|{}'.format(t, self.window_size)) self.em.log_it('FLOW|{}'.format(self.i), 'T|{}|DUPACK|1'.format(t)) if retransmit: old_next = self.send_next old_window_size = self.window_size # Retransmit the lost packet (which is the first unacked packet) # Subtle: invalidate its old ack timeout self.send_next = self.send_first_unacked self.window_size = 1 self.em.log_it( 'FLOW|{}'.format(self.i), 'T|{}|WINDOW|{}'.format(t, self.window_size)) self.ack_timeout_events[ self.send_first_unacked].invalidate() self.act(t) # Restore previous state self.send_next = old_next self.window_size = old_window_size self.em.log_it( 'FLOW|{}'.format(self.i), 'T|{}|WINDOW|{}'.format(t, self.window_size)) self.act(t) else: self.em.log_it( 'FLOW|{}'.format(self.i), 'T|{}|THROUGHPUT|{}'.format( t, (received_packet.ack_number - self.send_first_unacked) * DATA_PACKET_SIZE)) self.send_first_unacked = received_packet.ack_number self.window_size = self.cc.posack(t) self.em.log_it('FLOW|{}'.format(self.i), 'T|{}|WINDOW|{}'.format(t, self.window_size)) self.em.log_it('FLOW|{}'.format(self.i), 'T|{}|POSACK|1'.format(t)) if self.send_first_unacked > self.last_seq_number: # All packets are acked, so this flow is done self.em.flowend_done(self) self.clear_redundant_timeouts(received_packet.ack_number) # clean if self.rtt_sample_seq is not None and \ received_packet.ack_number > self.rtt_sample_seq: # NB: The only case that self.rtt_sample_seq is None is # when we get an ACK without ever having sent our own packet. # That's when we're the destination getting a SYN+ACK. self.on_rtt_sample(received_packet, t - self.rtt_sample_send_time, t) self.rtt_sample_seq = None self.rtt_sample_send_time = None # # OPERATIONS DEPENDING ON WHETHER WE'RE ESTABLISHED # if not self.is_established(): # We're always sending a Syn received_packet. response_packet = Packet(i=self.flow.get_packet_id(), flow=self.flow, sender=self.host, receiver=self.other_host, syn_flag=True, ack_flag=False, fin_flag=False, seq_number=self.send_iss, ack_number=None, size=CONTROL_PACKET_SIZE) # But we also acknowledge the packet we've received if it's Syn. # We don't acknowledge data packets. if received_packet.syn_flag: # Update state self.receive_iss = received_packet.seq_number # syn seq# self.receive_next = self.receive_iss + 1 self.send_next = self.send_iss # Reset 'next packet' to ISS # Modify response packet to change it to SynAck. response_packet.ack_flag = True response_packet.ack_number = self.receive_next self.send_acknowledgeable_packet(t, response_packet) # Can't act, since we're not established. else: # We're established. A response is required if Syn or data. if received_packet.syn_flag or received_packet.size >= 513: if received_packet.syn_flag: # Set initial sequence number self.receive_iss = received_packet.seq_number self.receive_next = self.receive_iss # Update receive_next self.received_seqs.add(received_packet.seq_number) while self.receive_next in self.received_seqs: self.receive_next += 1 response_packet = \ Packet(i=self.flow.get_packet_id(), flow=self.flow, sender=self.host, receiver=self.other_host, syn_flag=False, ack_flag=True, fin_flag=False, seq_number=self.send_next, ack_number=self.receive_next, size=CONTROL_PACKET_SIZE) # Do NOT schedule a timeout, just send the packet. self.send(t, response_packet) if self.debug: print("t={}: {} sends packet: {}".format( round(t, 6), self, response_packet)) self.act(t) # May want to send data here.