aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_minisocks.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-06-09 17:56:12 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-09 17:56:12 -0400
commit2397849baa7c44c242e5d5142d5d16d1e7ed53d0 (patch)
tree0ee2012361d1b0f8a92b68da7d0d92209613ecaf /net/ipv4/tcp_minisocks.c
parent4670fd819e7f47392c7c6fc6168ea2857c66d163 (diff)
[PATCH] tcp: Cache inetpeer in timewait socket, and only when necessary.
Since it's guarenteed that we will access the inetpeer if we're trying to do timewait recycling and TCP options were enabled on the connection, just cache the peer in the timewait socket. In the future, inetpeer lookups will be context dependent (per routing realm), and this helps facilitate that as well. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_minisocks.c')
-rw-r--r--net/ipv4/tcp_minisocks.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index fef9dbf3af00..cb015317c9f7 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -77,20 +77,19 @@ static bool tcp_remember_stamp(struct sock *sk)
77 77
78static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) 78static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw)
79{ 79{
80 const struct tcp_timewait_sock *tcptw;
80 struct sock *sk = (struct sock *) tw; 81 struct sock *sk = (struct sock *) tw;
81 struct inet_peer *peer; 82 struct inet_peer *peer;
82 83
83 peer = twsk_getpeer(sk); 84 tcptw = tcp_twsk(sk);
85 peer = tcptw->tw_peer;
84 if (peer) { 86 if (peer) {
85 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
86
87 if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 || 87 if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
88 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && 88 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
89 peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { 89 peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
90 peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; 90 peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
91 peer->tcp_ts = tcptw->tw_ts_recent; 91 peer->tcp_ts = tcptw->tw_ts_recent;
92 } 92 }
93 inet_putpeer(peer);
94 return true; 93 return true;
95 } 94 }
96 return false; 95 return false;
@@ -314,9 +313,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
314 const struct inet_connection_sock *icsk = inet_csk(sk); 313 const struct inet_connection_sock *icsk = inet_csk(sk);
315 const struct tcp_sock *tp = tcp_sk(sk); 314 const struct tcp_sock *tp = tcp_sk(sk);
316 bool recycle_ok = false; 315 bool recycle_ok = false;
316 bool recycle_on = false;
317 317
318 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) 318 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) {
319 recycle_ok = tcp_remember_stamp(sk); 319 recycle_ok = tcp_remember_stamp(sk);
320 recycle_on = true;
321 }
320 322
321 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) 323 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
322 tw = inet_twsk_alloc(sk, state); 324 tw = inet_twsk_alloc(sk, state);
@@ -324,8 +326,10 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
324 if (tw != NULL) { 326 if (tw != NULL) {
325 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); 327 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
326 const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); 328 const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
329 struct inet_sock *inet = inet_sk(sk);
330 struct inet_peer *peer = NULL;
327 331
328 tw->tw_transparent = inet_sk(sk)->transparent; 332 tw->tw_transparent = inet->transparent;
329 tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; 333 tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
330 tcptw->tw_rcv_nxt = tp->rcv_nxt; 334 tcptw->tw_rcv_nxt = tp->rcv_nxt;
331 tcptw->tw_snd_nxt = tp->snd_nxt; 335 tcptw->tw_snd_nxt = tp->snd_nxt;
@@ -347,6 +351,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
347 } 351 }
348#endif 352#endif
349 353
354 if (recycle_on)
355 peer = icsk->icsk_af_ops->get_peer(sk);
356 tcptw->tw_peer = peer;
357 if (peer)
358 atomic_inc(&peer->refcnt);
359
350#ifdef CONFIG_TCP_MD5SIG 360#ifdef CONFIG_TCP_MD5SIG
351 /* 361 /*
352 * The timewait bucket does not have the key DB from the 362 * The timewait bucket does not have the key DB from the
@@ -398,8 +408,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
398 408
399void tcp_twsk_destructor(struct sock *sk) 409void tcp_twsk_destructor(struct sock *sk)
400{ 410{
401#ifdef CONFIG_TCP_MD5SIG
402 struct tcp_timewait_sock *twsk = tcp_twsk(sk); 411 struct tcp_timewait_sock *twsk = tcp_twsk(sk);
412
413 if (twsk->tw_peer)
414 inet_putpeer(twsk->tw_peer);
415#ifdef CONFIG_TCP_MD5SIG
403 if (twsk->tw_md5_key) { 416 if (twsk->tw_md5_key) {
404 tcp_free_md5sig_pool(); 417 tcp_free_md5sig_pool();
405 kfree_rcu(twsk->tw_md5_key, rcu); 418 kfree_rcu(twsk->tw_md5_key, rcu);