From: Rick Jones <hidden> Date: 2007-08-31 00:09:22
Enable configuration of the minimum TCP Retransmission Timeout via
a new sysctl "tcp_rto_min" to help those who's networks (eg cellular)
have quite variable RTTs avoid spurrious RTOs.
Signed-off-by: Rick Jones <redacted>
Signed-off-by: Lamont Jones <redacted>
---
diff -r 06d7322848a3 Documentation/networking/ip-sysctl.txt
--- a/Documentation/networking/ip-sysctl.txt Mon Aug 27 18:32:35 2007 -0700+++ b/Documentation/networking/ip-sysctl.txt Thu Aug 30 17:06:16 2007 -0700
@@ -339,6 +339,13 @@ tcp_rmem - vector of 3 INTEGERs: min, de selected receiver buffers for TCP socket. This value does not override net.core.rmem_max, "static" selection via SO_RCVBUF does not use this. Default: 87380*2 bytes.++tcp_rto_min - INTEGER+ The minimum value for the TCP Retransmission Timeout, expressed+ in milliseconds for the convenience of the user.+ This is bounded at the low-end by TCP_RTO_MIN and by TCP_RTO_MAX at+ the high-end. + Default: 200. tcp_sack - BOOLEAN Enable select acknowledgments (SACKS).
diff -r 06d7322848a3 include/net/tcp.h
--- a/include/net/tcp.h Mon Aug 27 18:32:35 2007 -0700+++ b/include/net/tcp.h Thu Aug 30 17:06:16 2007 -0700
@@ -232,6 +232,7 @@ extern int sysctl_tcp_workaround_signed_externintsysctl_tcp_workaround_signed_windows;externintsysctl_tcp_slow_start_after_idle;externintsysctl_tcp_max_ssthresh;+externunsignedintsysctl_tcp_rto_min;externatomic_ttcp_memory_allocated;externatomic_ttcp_sockets_allocated;
diff -r 06d7322848a3 net/ipv4/sysctl_net_ipv4.c
--- a/net/ipv4/sysctl_net_ipv4.c Mon Aug 27 18:32:35 2007 -0700+++ b/net/ipv4/sysctl_net_ipv4.c Thu Aug 30 17:06:16 2007 -0700
@@ -186,6 +186,32 @@ static int strategy_allowed_congestion_c}+/* if there is ever a proc_dointvec_ms_jiffies_minmax we can get rid+ofthisroutine*/++staticintproc_tcp_rto_min(ctl_table*ctl,intwrite,structfile*filp,+void__user*buffer,size_t*lenp,loff_t*ppos)+{+u32*valp=ctl->data;+u32oldval=*valp;+intret;++ret=proc_dointvec_ms_jiffies(ctl,write,filp,buffer,lenp,ppos);+if(ret)+returnret;++/* some bounds checking would be in order */+if(write&&*valp!=oldval){+if(*valp<TCP_RTO_MIN||*valp>TCP_RTO_MAX){+*valp=oldval;+return-EINVAL;+}+}++return0;+}++ctl_tableipv4_table[]={{.ctl_name=NET_IPV4_TCP_TIMESTAMPS,
--- a/net/ipv4/tcp_input.c Mon Aug 27 18:32:35 2007 -0700+++ b/net/ipv4/tcp_input.c Thu Aug 30 17:06:16 2007 -0700
@@ -91,6 +91,8 @@ int sysctl_tcp_nometrics_save __read_mosintsysctl_tcp_moderate_rcvbuf__read_mostly=1;intsysctl_tcp_abc__read_mostly;++unsignedintsysctl_tcp_rto_min__read_mostly=TCP_RTO_MIN;#define FLAG_DATA 0x01 /* Incoming frame contained data. */#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
@@ -616,13 +618,13 @@ static void tcp_rtt_estimator(struct socif(tp->mdev_max<tp->rttvar)tp->rttvar-=(tp->rttvar-tp->mdev_max)>>2;tp->rtt_seq=tp->snd_nxt;-tp->mdev_max=TCP_RTO_MIN;+tp->mdev_max=sysctl_tcp_rto_min;}}else{/* no previous measure. */tp->srtt=m<<3;/* take the measured time to be rtt */tp->mdev=m<<1;/* make sure rto = 3*rtt */-tp->mdev_max=tp->rttvar=max(tp->mdev,TCP_RTO_MIN);+tp->mdev_max=tp->rttvar=max(tp->mdev,sysctl_tcp_rto_min);tp->rtt_seq=tp->snd_nxt;}}
From: David Miller <davem@davemloft.net> Date: 2007-08-31 00:39:13
From: Rick Jones <redacted>
Date: Thu, 30 Aug 2007 17:09:04 -0700 (PDT)
Enable configuration of the minimum TCP Retransmission Timeout via
a new sysctl "tcp_rto_min" to help those who's networks (eg cellular)
have quite variable RTTs avoid spurrious RTOs.
Signed-off-by: Rick Jones <redacted>
Signed-off-by: Lamont Jones <redacted>
Thanks for doing this work Rick.
But as John Heffner and I both mentioned, it's pretty clear we should
do this as a routing metric. Both for handling realistic scenerios
where the sysctl doesn't work, and to help prevent misuse (example:
someone decides that it would be _totally_ _awesome_ for "Carrier
Grade Linux" to set this to 3 seconds by default in /etc/sysctl.conf
and crap like that).
From: Rick Jones <hidden> Date: 2007-08-31 01:07:31
David Miller wrote:
From: Rick Jones <redacted>
Date: Thu, 30 Aug 2007 17:09:04 -0700 (PDT)
quoted
Enable configuration of the minimum TCP Retransmission Timeout via
a new sysctl "tcp_rto_min" to help those who's networks (eg cellular)
have quite variable RTTs avoid spurrious RTOs.
Signed-off-by: Rick Jones <redacted>
Signed-off-by: Lamont Jones <redacted>
Thanks for doing this work Rick.
But as John Heffner and I both mentioned, it's pretty clear we should
do this as a routing metric. Both for handling realistic scenerios
where the sysctl doesn't work, and to help prevent misuse (example:
someone decides that it would be _totally_ _awesome_ for "Carrier
Grade Linux" to set this to 3 seconds by default in /etc/sysctl.conf
and crap like that).
If nothing else it was worth the practice :) I'll be happy with either
mechanism, just wasn't sure if the jury was still out on whether making
it a routing metric was really necessary. I can see where it would be
goodness if one had separate paths out of a system, one with the highly
variable RTT and one with non-trivial loss rates, just that thusfar I've
not come across any :) I've only seen one path with high RTT
variability and the other path with trivial loss rates.
Also, not surprisingly, the folks for whom I'm doing this are a triffle
"anxious" so I figured that simplicity was worthwhile. Particularly if
it was going to be the case those folks were going to be asking for
back-ports.
Anyhow, I'll try grubbing around the source code (already doing that to
see about writing a pet tcp cong module) but if pointers to the likely
relevant files were available I could try to help thrash-out the routing
metric version. Like I said the consumers of this are a triffle well,
"anxious" :)
rick
From: David Miller <davem@davemloft.net> Date: 2007-08-31 05:09:13
From: Rick Jones <redacted>
Date: Thu, 30 Aug 2007 18:07:13 -0700
Anyhow, I'll try grubbing around the source code (already doing that to
see about writing a pet tcp cong module) but if pointers to the likely
relevant files were available I could try to help thrash-out the routing
metric version. Like I said the consumers of this are a triffle well,
"anxious" :)
The change is actually a lot simpler than the sysctl version.
In fact it borders on trivial :-)
Signed-off-by: David S. Miller <davem@davemloft.net>
@@ -555,6 +555,16 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)tcp_grow_window(sk,skb);}+staticu32tcp_rto_min(structsock*sk)+{+structdst_entry*dst=__sk_dst_get(sk);+u32rto_min=TCP_RTO_MIN;++if(dst_metric_locked(dst,RTAX_RTO_MIN))+rto_min=dst->metrics[RTAX_RTO_MIN-1];+returnrto_min;+}+/* Called to compute a smoothed rtt estimate. The data fed to this*routineeithercomesfromtimestamps,orfromsegmentsthatwere*known_not_tohavebeenretransmitted[seeKarn/Partridge
@@ -616,13 +626,13 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)if(tp->mdev_max<tp->rttvar)tp->rttvar-=(tp->rttvar-tp->mdev_max)>>2;tp->rtt_seq=tp->snd_nxt;-tp->mdev_max=TCP_RTO_MIN;+tp->mdev_max=tcp_rto_min(sk);}}else{/* no previous measure. */tp->srtt=m<<3;/* take the measured time to be rtt */tp->mdev=m<<1;/* make sure rto = 3*rtt */-tp->mdev_max=tp->rttvar=max(tp->mdev,TCP_RTO_MIN);+tp->mdev_max=tp->rttvar=max(tp->mdev,tcp_rto_min(sk));tp->rtt_seq=tp->snd_nxt;}}
From: Rick Jones <hidden> Date: 2007-08-31 17:19:17
John Heffner wrote:
Rick Jones wrote:
quoted
Like I said the consumers of this are a triffle well, "anxious" :)
Just curious, did you or this customer try with F-RTO enabled? Or is
this case you're dealing with truly hopeless?
F-RTO was mentioned to the customer and I'm awaiting their response as
to its efficacy in their situation. Everything I've seen thusfar is
leading me to believe that we'll still need a higher than 200
millisecond minimum rto though.
rick
From: Rick Jones <hidden> Date: 2007-08-31 18:11:54
David Miller wrote:
quoted hunk
From: Rick Jones <redacted>
Date: Thu, 30 Aug 2007 18:07:13 -0700
quoted
Anyhow, I'll try grubbing around the source code (already doing that to
see about writing a pet tcp cong module) but if pointers to the likely
relevant files were available I could try to help thrash-out the routing
metric version. Like I said the consumers of this are a triffle well,
"anxious" :)
The change is actually a lot simpler than the sysctl version.
In fact it borders on trivial :-)
Signed-off-by: David S. Miller <davem@davemloft.net>
@@ -555,6 +555,16 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)tcp_grow_window(sk,skb);}+staticu32tcp_rto_min(structsock*sk)+{+structdst_entry*dst=__sk_dst_get(sk);+u32rto_min=TCP_RTO_MIN;++if(dst_metric_locked(dst,RTAX_RTO_MIN))+rto_min=dst->metrics[RTAX_RTO_MIN-1];+returnrto_min;+}+/* Called to compute a smoothed rtt estimate. The data fed to this*routineeithercomesfromtimestamps,orfromsegmentsthatwere*known_not_tohavebeenretransmitted[seeKarn/Partridge
@@ -616,13 +626,13 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)if(tp->mdev_max<tp->rttvar)tp->rttvar-=(tp->rttvar-tp->mdev_max)>>2;tp->rtt_seq=tp->snd_nxt;-tp->mdev_max=TCP_RTO_MIN;+tp->mdev_max=tcp_rto_min(sk);}}else{/* no previous measure. */tp->srtt=m<<3;/* take the measured time to be rtt */tp->mdev=m<<1;/* make sure rto = 3*rtt */-tp->mdev_max=tp->rttvar=max(tp->mdev,TCP_RTO_MIN);+tp->mdev_max=tp->rttvar=max(tp->mdev,tcp_rto_min(sk));tp->rtt_seq=tp->snd_nxt;}}
At the risk of showing my ignorance (what me worry about that?-) I
presume this is then an interface expecting to take-in jiffies? That
means the user has to know the value of HZ which can be (IIRC) one of
three different values?
rick jones
From: David Miller <davem@davemloft.net> Date: 2007-08-31 18:57:07
From: Rick Jones <redacted>
Date: Fri, 31 Aug 2007 11:11:37 -0700
At the risk of showing my ignorance (what me worry about that?-) I
presume this is then an interface expecting to take-in jiffies? That
means the user has to know the value of HZ which can be (IIRC) one of
three different values?
The iproute2 changes might look something like this:
@@ -74,6 +75,7 @@ static void usage(void)fprintf(stderr," [ rtt NUMBER ] [ rttvar NUMBER ]\n");fprintf(stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");fprintf(stderr," [ ssthresh NUMBER ] [ realms REALM ]\n");+fprintf(stderr," [ rto_min NUMBER ]\n");fprintf(stderr,"TYPE := [ unicast | local | broadcast | multicast | throw |\n");fprintf(stderr," unreachable | prohibit | blackhole | nat ]\n");fprintf(stderr,"TABLE_ID := [ local | main | default | all | NUMBER ]\n");
@@ -520,7 +522,8 @@ int print_route(const struct sockaddr_nlif(mxlock&(1<<i))fprintf(fp," lock");-if(i!=RTAX_RTT&&i!=RTAX_RTTVAR)+if(i!=RTAX_RTT&&i!=RTAX_RTTVAR&&+i!=RTAX_RTO_MIN)fprintf(fp," %u",*(unsigned*)RTA_DATA(mxrta[i]));else{unsignedval=*(unsigned*)RTA_DATA(mxrta[i]);
@@ -528,7 +531,7 @@ int print_route(const struct sockaddr_nlval*=1000;if(i==RTAX_RTT)val/=8;-else+elseif(i==RTAX_RTTVAR)val/=4;if(val>=hz)fprintf(fp," %ums",val/hz);
@@ -803,6 +806,15 @@ int iproute_modify(int cmd, unsigned flaif(get_unsigned(&rtt,*argv,0))invarg("\"rtt\" value is invalid\n",*argv);rta_addattr32(mxrta,sizeof(mxbuf),RTAX_RTT,rtt);+}elseif(strcmp(*argv,"rto_min")==0){+unsignedrto_min;+NEXT_ARG();+mxlock|=(1<<RTAX_RTO_MIN);+if(get_unsigned(&rto_min,*argv,0))+invarg("\"rto_min\" value is invalid\n",+*argv);+rta_addattr32(mxrta,sizeof(mxbuf),RTAX_RTO_MIN,+rto_min);}elseif(matches(*argv,"window")==0){unsignedwin;NEXT_ARG();
Applied and beating on it with a while loop doing a bunch of ip route
del add change stuff while netperf TCP_CRR tests are running. Thusfar
things seem OK wrt the system staying alive, but since I only saw the
failure once I'm not sure how much that is really saying.
I'm going to go ahead and take a look at input vs output units and
differences between those with rto_min vs rtt.
rick jones