We probably need this ugly timeout also in the startup of the
connection... Ugly but I can't think a smarter way to guess if the
sender-userspace will kick out new data shortly. And to get this
ack-merging feature from the TCP we should not use a fixed HZ/50 timeout
but use the normal ato timeout to get the improvement over all kind of
underlying hardware.
Here a patch against 2.2.2. I did not tried the code yet. In the
TCP_NODELAY case we probably want to do raw things (without caring about
network load).
Index: tcp_input.c
===================================================================
RCS file: /var/cvs/linux/net/ipv4/tcp_input.c,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 tcp_input.c
--- tcp_input.c 1999/02/23 16:48:26 1.1.1.6
+++ linux/net/ipv4/tcp_input.c 1999/03/02 01:50:05
@@ -55,6 +55,8 @@
* work without delayed acks.
* Andi Kleen: Process packets with PSH set in the
* fast path.
+ * Andrea Arcangeli: Always try to delay the ack in the hope
+ * to get the ack merged with data.
*/
#include <linux/config.h>
@@ -99,12 +101,13 @@
if(tp->ato == 0) {
tp->lrcvtime = jiffies;
- /* Help sender leave slow start quickly,
- * and also makes sure we do not take this
- * branch ever again for this connection.
+ /*
+ * Makes sure we do not take this branch ever again for this
+ * connection and delay the first ack of the minimum timeout
+ * to have a chance to get the first ack merged in a data
+ * segment. -arca
*/
tp->ato = 1;
- tcp_enter_quickack_mode(tp);
} else {
int m = jiffies - tp->lrcvtime;
@@ -125,20 +128,16 @@
/*
* Remember to send an ACK later.
*/
-static __inline__ void tcp_remember_ack(struct tcp_opt *tp, struct tcphdr *th,
- struct sk_buff *skb)
+static __inline__ void tcp_remember_ack(struct sock *sk, struct tcp_opt *tp,
+ struct tcphdr *th, struct sk_buff *skb)
{
tp->delayed_acks++;
/* Tiny-grams with PSH set artifically deflate our
* ato measurement, but with a lower bound.
*/
- if(th->psh && (skb->len < (tp->mss_cache >> 1))) {
- /* Preserve the quickack state. */
- if((tp->ato & 0x7fffffff) > HZ/50)
- tp->ato = ((tp->ato & 0x80000000) |
- (HZ/50));
- }
+ if(sk->nonagle == 1 && th->psh && (skb->len < (tp->mss_cache >> 1)))
+ tcp_enter_quickack_mode(tp);
}
/* Called to compute a smoothed rtt estimate. The data fed to this
@@ -241,7 +240,7 @@
extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
{
/* ts_recent must be younger than 24 days */
- return (((jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
+ return (((s32)(jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
(((s32)(tp->rcv_tsval-tp->ts_recent) < 0) &&
/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
(len != (th->doff * 4))));
@@ -1372,7 +1371,7 @@
if(skb->h.th->fin) {
tcp_fin(skb, sk, skb->h.th);
} else {
- tcp_remember_ack(tp, skb->h.th, skb);
+ tcp_remember_ack(sk, tp, skb->h.th, skb);
}
/* This may have eaten into a SACK block. */
if(tp->sack_ok && tp->num_sacks)
@@ -1727,7 +1726,7 @@
* if we are really having our buffer space abused we stop accepting
* new receive data.
*/
- if(atomic_read(&sk->rmem_alloc) < (sk->rcvbuf << 1))
+ if(atomic_read(&sk->rmem_alloc) <= sk->rcvbuf)
return 0;
/* Massive buffer overcommit. */
@@ -1839,7 +1838,7 @@
sk->data_ready(sk, 0);
tcp_delack_estimator(tp);
- tcp_remember_ack(tp, th, skb);
+ tcp_remember_ack(sk, tp, th, skb);
__tcp_ack_snd_check(sk);
return 0;
Comments?
Andrea Arcangeli
PS. Time to sleep for me, I am going to have big sleep leakage tomorrow...
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/