Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc6415bc authored by David S. Miller's avatar David S. Miller
Browse files

[TCP]: Fix quick-ack decrementing with TSO.



On each packet output, we call tcp_dec_quickack_mode()
if the ACK flag is set.  It drops tp->ack.quick until
it hits zero, at which time we deflate the ATO value.

When doing TSO, we are emitting multiple packets with
ACK set, so we should decrement tp->ack.quick that many
segments.

Note that, unlike this case, tcp_enter_cwr() should not
take the tcp_skb_pcount(skb) into consideration.  That
function, one time, readjusts tp->snd_cwnd and moves
into TCP_CA_CWR state.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c65f7f00
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -721,11 +721,16 @@ static inline int tcp_ack_scheduled(struct tcp_sock *tp)
	return tp->ack.pending&TCP_ACK_SCHED;
}

static __inline__ void tcp_dec_quickack_mode(struct tcp_sock *tp)
static __inline__ void tcp_dec_quickack_mode(struct tcp_sock *tp, unsigned int pkts)
{
	if (tp->ack.quick && --tp->ack.quick == 0) {
	if (tp->ack.quick) {
		if (pkts >= tp->ack.quick) {
			tp->ack.quick = 0;

			/* Leaving quickack mode we deflate ATO. */
			tp->ack.ato = TCP_ATO_MIN;
		} else
			tp->ack.quick -= pkts;
	}
}

+3 −3
Original line number Diff line number Diff line
@@ -140,11 +140,11 @@ static inline void tcp_event_data_sent(struct tcp_sock *tp,
		tp->ack.pingpong = 1;
}

static __inline__ void tcp_event_ack_sent(struct sock *sk)
static __inline__ void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
	struct tcp_sock *tp = tcp_sk(sk);

	tcp_dec_quickack_mode(tp);
	tcp_dec_quickack_mode(tp, pkts);
	tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
}

@@ -355,7 +355,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
		tp->af_specific->send_check(sk, th, skb->len, skb);

		if (tcb->flags & TCPCB_FLAG_ACK)
			tcp_event_ack_sent(sk);
			tcp_event_ack_sent(sk, tcp_skb_pcount(skb));

		if (skb->len != tcp_header_size)
			tcp_event_data_sent(tp, skb, sk);