|
@@ -704,30 +704,45 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
|
704
|
704
|
size_t len;
|
705
|
705
|
unsigned int acked_flags;
|
706
|
706
|
|
707
|
|
- /* Ignore duplicate or out-of-range ACK */
|
708
|
|
- if ( ack_len > tcp->snd_sent ) {
|
709
|
|
- DBGC ( tcp, "TCP %p received ACK for [%08x,%08zx), "
|
710
|
|
- "sent only [%08x,%08x)\n", tcp, tcp->snd_seq,
|
711
|
|
- ( tcp->snd_seq + ack_len ), tcp->snd_seq,
|
712
|
|
- ( tcp->snd_seq + tcp->snd_sent ) );
|
713
|
|
- return -EINVAL;
|
714
|
|
- }
|
715
|
|
-
|
716
|
|
- /* Acknowledge any flags being sent */
|
|
707
|
+ /* Determine acknowledged flags and data length */
|
717
|
708
|
len = ack_len;
|
718
|
709
|
acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
|
719
|
710
|
( TCP_SYN | TCP_FIN ) );
|
720
|
711
|
if ( acked_flags )
|
721
|
712
|
len--;
|
722
|
713
|
|
|
714
|
+ /* Stop retransmission timer if necessary */
|
|
715
|
+ if ( ack_len == 0 ) {
|
|
716
|
+ /* Duplicate ACK (or just a packet that isn't
|
|
717
|
+ * intending to ACK any new data). If the
|
|
718
|
+ * retransmission timer is running, leave it running
|
|
719
|
+ * so that we don't immediately retransmit and cause a
|
|
720
|
+ * sorceror's apprentice syndrome.
|
|
721
|
+ */
|
|
722
|
+ } else if ( ack_len <= tcp->snd_sent ) {
|
|
723
|
+ /* ACK of new data. Stop the retransmission timer. */
|
|
724
|
+ stop_timer ( &tcp->timer );
|
|
725
|
+ } else {
|
|
726
|
+ /* Out-of-range (or old duplicate) ACK. Leave the
|
|
727
|
+ * timer running, as for the ack_len==0 case, to
|
|
728
|
+ * handle old duplicate ACKs.
|
|
729
|
+ */
|
|
730
|
+ DBGC ( tcp, "TCP %p received ACK for [%08x,%08zx), "
|
|
731
|
+ "sent only [%08x,%08x)\n", tcp, tcp->snd_seq,
|
|
732
|
+ ( tcp->snd_seq + ack_len ), tcp->snd_seq,
|
|
733
|
+ ( tcp->snd_seq + tcp->snd_sent ) );
|
|
734
|
+ /* Send RST if an out-of-range ACK is received on a
|
|
735
|
+ * not-yet-established connection.
|
|
736
|
+ */
|
|
737
|
+ if ( ! TCP_HAS_BEEN_ESTABLISHED ( tcp->tcp_state ) )
|
|
738
|
+ return -EINVAL;
|
|
739
|
+ }
|
|
740
|
+
|
723
|
741
|
/* Update SEQ and sent counters, and window size */
|
724
|
742
|
tcp->snd_seq = ack;
|
725
|
743
|
tcp->snd_sent = 0;
|
726
|
744
|
tcp->snd_win = win;
|
727
|
745
|
|
728
|
|
- /* Stop the retransmission timer */
|
729
|
|
- stop_timer ( &tcp->timer );
|
730
|
|
-
|
731
|
746
|
/* Remove any acknowledged data from transmit queue */
|
732
|
747
|
tcp_process_queue ( tcp, len, NULL, 1 );
|
733
|
748
|
|