tcp/dccp: get rid of central timewait timer
Using a timer wheel for timewait sockets was nice ~15 years ago when memory was expensive and machines had a single processor. This does not scale, code is ugly and source of huge latencies (Typically 30 ms have been seen, cpus spinning on death_lock spinlock.) We can afford to use an extra 64 bytes per timewait sock and spread timewait load to all cpus to have better behavior. Tested: On following test, /proc/sys/net/ipv4/tcp_tw_recycle is set to 1 on the target (lpaa24) Before patch : lpaa23:~# ./super_netperf 200 -H lpaa24 -t TCP_CC -l 60 -- -p0,0 419594 lpaa23:~# ./super_netperf 200 -H lpaa24 -t TCP_CC -l 60 -- -p0,0 437171 While test is running, we can observe 25 or even 33 ms latencies. lpaa24:~# ping -c 1000 -i 0.02 -qn lpaa23 ... 1000 packets transmitted, 1000 received, 0% packet loss, time 20601ms rtt min/avg/max/mdev = 0.020/0.217/25.771/1.535 ms, pipe 2 lpaa24:~# ping -c 1000 -i 0.02 -qn lpaa23 ... 1000 packets transmitted, 1000 received, 0% packet loss, time 20702ms rtt min/avg/max/mdev = 0.019/0.183/33.761/1.441 ms, pipe 2 After patch : About 90% increase of throughput : lpaa23:~# ./super_netperf 200 -H lpaa24 -t TCP_CC -l 60 -- -p0,0 810442 lpaa23:~# ./super_netperf 200 -H lpaa24 -t TCP_CC -l 60 -- -p0,0 800992 And latencies are kept to minimal values during this load, even if network utilization is 90% higher : lpaa24:~# ping -c 1000 -i 0.02 -qn lpaa23 ... 1000 packets transmitted, 1000 received, 0% packet loss, time 19991ms rtt min/avg/max/mdev = 0.023/0.064/0.360/0.042 ms Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
20a1d16526
commit
789f558cfb
@@ -27,28 +27,16 @@
|
||||
|
||||
struct inet_timewait_death_row dccp_death_row = {
|
||||
.sysctl_max_tw_buckets = NR_FILE * 2,
|
||||
.period = DCCP_TIMEWAIT_LEN / INET_TWDR_TWKILL_SLOTS,
|
||||
.death_lock = __SPIN_LOCK_UNLOCKED(dccp_death_row.death_lock),
|
||||
.hashinfo = &dccp_hashinfo,
|
||||
.tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0,
|
||||
(unsigned long)&dccp_death_row),
|
||||
.twkill_work = __WORK_INITIALIZER(dccp_death_row.twkill_work,
|
||||
inet_twdr_twkill_work),
|
||||
/* Short-time timewait calendar */
|
||||
|
||||
.twcal_hand = -1,
|
||||
.twcal_timer = TIMER_INITIALIZER(inet_twdr_twcal_tick, 0,
|
||||
(unsigned long)&dccp_death_row),
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_death_row);
|
||||
|
||||
void dccp_time_wait(struct sock *sk, int state, int timeo)
|
||||
{
|
||||
struct inet_timewait_sock *tw = NULL;
|
||||
struct inet_timewait_sock *tw;
|
||||
|
||||
if (dccp_death_row.tw_count < dccp_death_row.sysctl_max_tw_buckets)
|
||||
tw = inet_twsk_alloc(sk, state);
|
||||
tw = inet_twsk_alloc(sk, &dccp_death_row, state);
|
||||
|
||||
if (tw != NULL) {
|
||||
const struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
@@ -71,8 +59,7 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
|
||||
if (state == DCCP_TIME_WAIT)
|
||||
timeo = DCCP_TIMEWAIT_LEN;
|
||||
|
||||
inet_twsk_schedule(tw, &dccp_death_row, timeo,
|
||||
DCCP_TIMEWAIT_LEN);
|
||||
inet_twsk_schedule(tw, timeo);
|
||||
inet_twsk_put(tw);
|
||||
} else {
|
||||
/* Sorry, if we're out of memory, just CLOSE this
|
||||
|
Reference in New Issue
Block a user