Try this patch, already sent to Linus:
diff -u --recursive --new-file --exclude=CVS --exclude=.cvsignore
vanilla/linux/include/net/tcp.h linux/include/net/tcp.h
--- vanilla/linux/include/net/tcp.h Mon Jan 24 18:15:40 2000
+++ linux/include/net/tcp.h Mon Jan 24 19:09:24 2000
@@ -975,7 +975,7 @@
{
__u32 cwnd;
- if (!tp->srtt || tp->srtt > (HZ/50) || tp->mss_cache > 1460)
+ if (!tp->srtt || tp->srtt > ((HZ/50)<<3) || tp->mss_cache > 1460)
cwnd = 2;
else if (tp->mss_cache > 1095)
cwnd = 3;
diff -u --recursive --new-file --exclude=CVS --exclude=.cvsignore
vanilla/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- vanilla/linux/net/ipv4/tcp.c Mon Jan 24 18:15:41 2000
+++ linux/net/ipv4/tcp.c Mon Jan 24 10:40:32 2000
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.158 2000/01/21 23:45:57 davem Exp $
+ * Version: $Id: tcp.c,v 1.160 2000/01/24 18:40:32 davem Exp $
*
* Authors: Ross Biro, <[EMAIL PROTECTED]>
* Fred N. van Kempen, <[EMAIL PROTECTED]>
@@ -1027,7 +1027,6 @@
TCP_CHECK_TIMER(sk);
out_unlock:
release_sock(sk);
- tcp_push_pending_frames(sk, tp);
return err;
}
@@ -1347,6 +1346,35 @@
BUG_TRAP(tp->copied_seq == tp->rcv_nxt);
+ /* Ugly... If prequeue is not empty, we have to
+ * process it before releasing socket, otherwise
+ * order will be broken at second iteration.
+ * More elegant solution is required!!!
+ *
+ * Look: we have the following (pseudo)queues:
+ *
+ * 1. packets in flight
+ * 2. backlog
+ * 3. prequeue
+ * 4. receive_queue
+ *
+ * Each queue can be processed only if the next ones
+ * are empty. At this point we have empty receive_queue.
+ * But prequeue _can_ be not empty after second iteration,
+ * when we jumped to start of loop because backlog
+ * processing added something to receive_queue.
+ * We cannot release_sock(), because backlog contains
+ * packets arrived _after_ prequeued ones.
+ *
+ * Shortly, algorithm is clear --- to process all
+ * the queues in order. We could make it more directly,
+ * requeueing packets from backlog to prequeue, if
+ * is not empty. It is more elegant, but eats cycles,
+ * unfortunately.
+ */
+ if (skb_queue_len(&tp->ucopy.prequeue))
+ goto do_prequeue;
+
/* __ Set realtime policy in scheduler __ */
}
@@ -1371,6 +1399,7 @@
if (tp->rcv_nxt == tp->copied_seq &&
skb_queue_len(&tp->ucopy.prequeue)) {
+do_prequeue:
tcp_prequeue_process(sk);
if ((chunk = len - tp->ucopy.len) != 0) {
diff -u --recursive --new-file --exclude=CVS --exclude=.cvsignore
vanilla/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- vanilla/linux/net/ipv4/tcp_input.c Mon Jan 24 18:15:41 2000
+++ linux/net/ipv4/tcp_input.c Mon Jan 24 10:40:33 2000
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.182 2000/01/21 23:45:59 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.183 2000/01/24 18:40:33 davem Exp $
*
* Authors: Ross Biro, <[EMAIL PROTECTED]>
* Fred N. van Kempen, <[EMAIL PROTECTED]>
@@ -1323,7 +1323,11 @@
if (th->doff > (sizeof(struct tcphdr)>>2) && tw->ts_recent_stamp) {
tcp_parse_options(NULL, th, &tp, 0);
- paws_reject = tp.saw_tstamp && tcp_paws_check(&tp, th->rst);
+ if (tp.saw_tstamp) {
+ tp.ts_recent = tw->ts_recent;
+ tp.ts_recent_stamp = tw->ts_recent_stamp;
+ paws_reject = tcp_paws_check(&tp, th->rst);
+ }
}
if (tw->substate == TCP_FIN_WAIT2) {
@@ -2832,7 +2836,15 @@
if (th->doff > (sizeof(struct tcphdr)>>2)) {
tcp_parse_options(NULL, th, &ttp, 0);
- paws_reject = ttp.saw_tstamp && tcp_paws_check(&ttp, th->rst);
+ if (ttp.saw_tstamp) {
+ ttp.ts_recent = req->ts_recent;
+ /* We do not store true stamp, but it is not required,
+ * it can be estimated (approximately)
+ * from another data.
+ */
+ ttp.ts_recent_stamp = xtime.tv_sec -
+((TCP_TIMEOUT_INIT/HZ)<<req->retrans);
+ paws_reject = tcp_paws_check(&ttp, th->rst);
+ }
}
/* Check for pure retransmited SYN. */
@@ -3019,12 +3031,26 @@
* checked in SYN-SENT unlike another states, hence
* echoed tstamp must be checked too.
*/
- if (tp->saw_tstamp &&
- ((__s32)(tp->rcv_tsecr - tcp_time_stamp) > 0 ||
- (__s32)(tp->rcv_tsecr - tp->syn_stamp) < 0)) {
- NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: synsent
reject.\n"));
- NET_INC_STATS_BH(PAWSActiveRejected);
- return 1;
+ if (tp->saw_tstamp) {
+ if (tp->rcv_tsecr == 0) {
+ /* Workaround for bug in linux-2.1 and early
+ * 2.2 kernels. Let's pretend that we did not
+ * see such timestamp to avoid bogus rtt value,
+ * calculated by tcp_ack().
+ */
+ tp->saw_tstamp = 0;
+
+ /* But do not forget to store peer's timestamp! */
+ if (th->syn) {
+ tp->ts_recent = tp->rcv_tsval;
+ tp->ts_recent_stamp = xtime.tv_sec;
+ }
+ } else if ((__s32)(tp->rcv_tsecr - tcp_time_stamp) > 0 ||
+ (__s32)(tp->rcv_tsecr - tp->syn_stamp) < 0) {
+ NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP:
+synsent reject.\n"));
+ NET_INC_STATS_BH(PAWSActiveRejected);
+ return 1;
+ }
}
/* Now ACK is acceptable.
@@ -3449,6 +3475,14 @@
tmo = tcp_fin_time(tp);
if (tmo > TCP_TIMEWAIT_LEN) {
tcp_reset_keepalive_timer(sk, tmo -
TCP_TIMEWAIT_LEN);
+ } else if (th->fin || sk->lock.users) {
+ /* Bad case. We could lose such FIN
+otherwise.
+ * It is not a big problem, but it
+looks confusing
+ * and not so rare event. We still can
+lose it now,
+ * if it spins in bh_lock_sock(), but
+it is really
+ * marginal case.
+ */
+ tcp_reset_keepalive_timer(sk, tmo);
} else {
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto discard;
diff -u --recursive --new-file --exclude=CVS --exclude=.cvsignore
vanilla/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- vanilla/linux/net/packet/af_packet.c Mon Jan 24 18:15:41 2000
+++ linux/net/packet/af_packet.c Mon Jan 24 15:35:59 2000
@@ -5,7 +5,7 @@
*
* PACKET - implements raw packet sockets.
*
- * Version: $Id: af_packet.c,v 1.27 2000/01/18 08:24:27 davem Exp $
+ * Version: $Id: af_packet.c,v 1.28 2000/01/24 23:35:59 davem Exp $
*
* Authors: Ross Biro, <[EMAIL PROTECTED]>
* Fred N. van Kempen, <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [EMAIL PROTECTED]