Hi all
Because I did not receive any reply to my bug description
of TCP retries and the problem is still present since
2.3.18 when I first noticed it I am making it more descriptive:
(It is actually in whole 2.3 and 2.2 series)
After setting number of retries for tcp_syn_retries or tcp_retries you
get
one more retry than specified. Furthermore user application receives
error
exactly at the time last retry takes place:
with echo 3>/proc/sys/net/ipv4/tcp_syn_retries
and application that tries to connect to 172.16.100.20 port 9
you get:
14:44:11.527433 172.16.161.23.1032 > 172.16.100.20.9: S
925580338:925580338(0)
14:44:14.527433 172.16.161.23.1032 > 172.16.100.20.9: S
925580338:925580338(0)
14:44:20.527433 172.16.161.23.1032 > 172.16.100.20.9: S
925580338:925580338(0)
14:44:32.527433 172.16.161.23.1032 > 172.16.100.20.9: S
925580338:925580338(0)
14:44:56.527433 172.16.161.23.1032 > 172.16.100.20.9: S
925580338:925580338(0)
The application reports that connect() returned with error at 14:44:56
which is
apparently the time of last (useless) retry.
The same retry behavior have normal tcp segments also.
After applying included patch you get right behavior (3 retries):
14:53:53.703863 172.16.161.23.1026 > 172.16.100.20.9: S
1567489151:1567489151(0)
14:53:56.713863 172.16.161.23.1026 > 172.16.100.20.9: S
1567489151:1567489151(0)
14:54:02.713863 172.16.161.23.1026 > 172.16.100.20.9: S
1567489151:1567489151(0)
14:54:14.713863 172.16.161.23.1026 > 172.16.100.20.9: S
1567489151:1567489151(0)
and application reports that connect() returned with error at 14:54:38
which is the time
when the next retry would take place.
This small patch moves only retransmition checks in
tcp_retransmit_timer function before retransmitions
take place and solves the problem.
regards
Pavel
--- linux-2.3.36/net/ipv4/tcp_timer.c.bak Thu Jan 6 14:41:58 2000
+++ linux-2.3.36/net/ipv4/tcp_timer.c Thu Jan 6 14:42:10 2000
@@ -152,14 +152,14 @@
}
/* A write timeout has occurred. Process the after effects. */
-static void tcp_write_timeout(struct sock *sk)
+static int tcp_write_timeout(struct sock *sk)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
/* Look for a 'soft' timeout. */
if ((sk->state == TCP_ESTABLISHED &&
tp->retransmits && (tp->retransmits % TCP_QUICK_TRIES) == 0) ||
- (sk->state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
+ (sk->state != TCP_ESTABLISHED && tp->retransmits >= sysctl_tcp_retries1)) {
/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
hole detection. :-(
@@ -185,14 +185,17 @@
/* Have we tried to SYN too many times (repent repent 8)) */
if (sk->state == TCP_SYN_SENT &&
- ((!tp->syn_retries && tp->retransmits > sysctl_tcp_syn_retries) ||
- (tp->syn_retries && tp->retransmits > tp->syn_retries))) {
+ ((!tp->syn_retries && tp->retransmits >= sysctl_tcp_syn_retries) ||
+ (tp->syn_retries && tp->retransmits >= tp->syn_retries))) {
tcp_write_err(sk, 1);
+ return 1;
/* Don't FIN, we got nothing back */
- } else if (tp->retransmits > sysctl_tcp_retries2) {
+ } else if (tp->retransmits >= sysctl_tcp_retries2) {
/* Has it gone just too far? */
tcp_write_err(sk, 0);
+ return 1;
}
+ return 0;
}
void tcp_delack_timer(unsigned long data)
@@ -391,6 +394,9 @@
/* Clear delay ack timer. */
tcp_clear_xmit_timer(sk, TIME_DACK);
+
+ if (tcp_write_timeout(sk))
+ goto out_unlock;
/* RFC 2018, clear all 'sacked' flags in retransmission queue,
* the sender may have dropped out of order frames and we must
@@ -451,7 +457,6 @@
tp->rto = min(tp->rto << 1, 120*HZ);
tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
- tcp_write_timeout(sk);
out_unlock:
bh_unlock_sock(sk);
-
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/
This archive was generated by hypermail 2b29 : Fri Jan 07 2000 - 21:00:06 EST