aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tcp.h1
-rw-r--r--net/ipv4/tcp_input.c21
2 files changed, 16 insertions, 6 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index b386361ba3e8..d909feeeaea2 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -256,6 +256,7 @@ struct tcp_sock {
256 u32 prr_delivered; /* Number of newly delivered packets to 256 u32 prr_delivered; /* Number of newly delivered packets to
257 * receiver in Recovery. */ 257 * receiver in Recovery. */
258 u32 prr_out; /* Total number of pkts sent during Recovery. */ 258 u32 prr_out; /* Total number of pkts sent during Recovery. */
259 u32 delivered; /* Total data packets delivered incl. rexmits */
259 260
260 u32 rcv_wnd; /* Current receiver window */ 261 u32 rcv_wnd; /* Current receiver window */
261 u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ 262 u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index dc810df53e90..2d690b3f0a7b 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1214,6 +1214,7 @@ static u8 tcp_sacktag_one(struct sock *sk,
1214 sacked |= TCPCB_SACKED_ACKED; 1214 sacked |= TCPCB_SACKED_ACKED;
1215 state->flag |= FLAG_DATA_SACKED; 1215 state->flag |= FLAG_DATA_SACKED;
1216 tp->sacked_out += pcount; 1216 tp->sacked_out += pcount;
1217 tp->delivered += pcount; /* Out-of-order packets delivered */
1217 1218
1218 fack_count += pcount; 1219 fack_count += pcount;
1219 1220
@@ -1825,8 +1826,12 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend)
1825static void tcp_add_reno_sack(struct sock *sk) 1826static void tcp_add_reno_sack(struct sock *sk)
1826{ 1827{
1827 struct tcp_sock *tp = tcp_sk(sk); 1828 struct tcp_sock *tp = tcp_sk(sk);
1829 u32 prior_sacked = tp->sacked_out;
1830
1828 tp->sacked_out++; 1831 tp->sacked_out++;
1829 tcp_check_reno_reordering(sk, 0); 1832 tcp_check_reno_reordering(sk, 0);
1833 if (tp->sacked_out > prior_sacked)
1834 tp->delivered++; /* Some out-of-order packet is delivered */
1830 tcp_verify_left_out(tp); 1835 tcp_verify_left_out(tp);
1831} 1836}
1832 1837
@@ -1838,6 +1843,7 @@ static void tcp_remove_reno_sacks(struct sock *sk, int acked)
1838 1843
1839 if (acked > 0) { 1844 if (acked > 0) {
1840 /* One ACK acked hole. The rest eat duplicate ACKs. */ 1845 /* One ACK acked hole. The rest eat duplicate ACKs. */
1846 tp->delivered += max_t(int, acked - tp->sacked_out, 1);
1841 if (acked - 1 >= tp->sacked_out) 1847 if (acked - 1 >= tp->sacked_out)
1842 tp->sacked_out = 0; 1848 tp->sacked_out = 0;
1843 else 1849 else
@@ -3156,10 +3162,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3156 flag |= FLAG_ORIG_SACK_ACKED; 3162 flag |= FLAG_ORIG_SACK_ACKED;
3157 } 3163 }
3158 3164
3159 if (sacked & TCPCB_SACKED_ACKED) 3165 if (sacked & TCPCB_SACKED_ACKED) {
3160 tp->sacked_out -= acked_pcount; 3166 tp->sacked_out -= acked_pcount;
3161 else if (tcp_is_sack(tp) && !tcp_skb_spurious_retrans(tp, skb)) 3167 } else if (tcp_is_sack(tp)) {
3162 tcp_rack_advance(tp, &skb->skb_mstamp, sacked); 3168 tp->delivered += acked_pcount;
3169 if (!tcp_skb_spurious_retrans(tp, skb))
3170 tcp_rack_advance(tp, &skb->skb_mstamp, sacked);
3171 }
3163 if (sacked & TCPCB_LOST) 3172 if (sacked & TCPCB_LOST)
3164 tp->lost_out -= acked_pcount; 3173 tp->lost_out -= acked_pcount;
3165 3174
@@ -3541,9 +3550,9 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3541 bool is_dupack = false; 3550 bool is_dupack = false;
3542 u32 prior_fackets; 3551 u32 prior_fackets;
3543 int prior_packets = tp->packets_out; 3552 int prior_packets = tp->packets_out;
3544 const int prior_unsacked = tp->packets_out - tp->sacked_out; 3553 u32 prior_delivered = tp->delivered;
3545 int acked = 0; /* Number of packets newly acked */ 3554 int acked = 0; /* Number of packets newly acked */
3546 int acked_sacked; /* Number of packets newly acked or sacked */ 3555 u32 acked_sacked; /* Number of packets newly acked or sacked */
3547 int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */ 3556 int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */
3548 3557
3549 sack_state.first_sackt.v64 = 0; 3558 sack_state.first_sackt.v64 = 0;
@@ -3645,7 +3654,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3645 if (tp->tlp_high_seq) 3654 if (tp->tlp_high_seq)
3646 tcp_process_tlp_ack(sk, ack, flag); 3655 tcp_process_tlp_ack(sk, ack, flag);
3647 3656
3648 acked_sacked = prior_unsacked - (tp->packets_out - tp->sacked_out); 3657 acked_sacked = tp->delivered - prior_delivered;
3649 /* Advance cwnd if state allows */ 3658 /* Advance cwnd if state allows */
3650 if (tcp_in_cwnd_reduction(sk)) { 3659 if (tcp_in_cwnd_reduction(sk)) {
3651 /* Reduce cwnd if state mandates */ 3660 /* Reduce cwnd if state mandates */