tcp: refactor CA_Loss state processing
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / tcp_input.c
index 231c79fe91f32251ae2bc9fc633648fb224b4dcd..8d821e45b9178ed85287e2835eedb43507e72ed5 100644 (file)
@@ -2664,6 +2664,30 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack)
        tcp_set_ca_state(sk, TCP_CA_Recovery);
 }
 
+/* Process an ACK in CA_Loss state. Move to CA_Open if lost data are
+ * recovered or spurious. Otherwise retransmits more on partial ACKs.
+ */
+static void tcp_process_loss(struct sock *sk, int flag)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       if (!before(tp->snd_una, tp->high_seq)) {
+               icsk->icsk_retransmits = 0;
+               tcp_try_undo_recovery(sk);
+               return;
+       }
+
+       if (flag & FLAG_DATA_ACKED)
+               icsk->icsk_retransmits = 0;
+       if (tcp_is_reno(tp) && flag & FLAG_SND_UNA_ADVANCED)
+               tcp_reset_reno_sack(tp);
+       if (tcp_try_undo_loss(sk))
+               return;
+       tcp_moderate_cwnd(tp);
+       tcp_xmit_retransmit_queue(sk);
+}
+
 /* Process an event, which can update packets-in-flight not trivially.
  * Main goal of this function is to calculate new estimate for left_out,
  * taking into account both packets sitting in receiver's buffer and
@@ -2710,12 +2734,6 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                tp->retrans_stamp = 0;
        } else if (!before(tp->snd_una, tp->high_seq)) {
                switch (icsk->icsk_ca_state) {
-               case TCP_CA_Loss:
-                       icsk->icsk_retransmits = 0;
-                       if (tcp_try_undo_recovery(sk))
-                               return;
-                       break;
-
                case TCP_CA_CWR:
                        /* CWR is to be held something *above* high_seq
                         * is ACKed for CWR bit to reach receiver. */
@@ -2746,18 +2764,10 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
                break;
        case TCP_CA_Loss:
-               if (flag & FLAG_DATA_ACKED)
-                       icsk->icsk_retransmits = 0;
-               if (tcp_is_reno(tp) && flag & FLAG_SND_UNA_ADVANCED)
-                       tcp_reset_reno_sack(tp);
-               if (!tcp_try_undo_loss(sk)) {
-                       tcp_moderate_cwnd(tp);
-                       tcp_xmit_retransmit_queue(sk);
-                       return;
-               }
+               tcp_process_loss(sk, flag);
                if (icsk->icsk_ca_state != TCP_CA_Open)
                        return;
-               /* Loss is undone; fall through to processing in Open state. */
+               /* Fall through to processing in Open state. */
        default:
                if (tcp_is_reno(tp)) {
                        if (flag & FLAG_SND_UNA_ADVANCED)