aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-06-03 16:33:21 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-04 11:27:39 -0400
commit4aea39c11c610e411768649fdc04777903ebfe07 (patch)
tree0389be795b0ebd8c75992eedf511e2346cfbf10f
parent90ba9b1986b5ac4b2d184575847147ea7c4280a2 (diff)
tcp: tcp_make_synack() consumes dst parameter
tcp_make_synack() clones the dst, and callers release it. We can avoid two atomic operations per SYNACK if tcp_make_synack() consumes dst instead of cloning it. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c18
-rw-r--r--net/ipv6/tcp_ipv6.c1
3 files changed, 14 insertions, 6 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c8d28c433b2b..3d9c1a4b8819 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -848,7 +848,6 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
848 err = net_xmit_eval(err); 848 err = net_xmit_eval(err);
849 } 849 }
850 850
851 dst_release(dst);
852 return err; 851 return err;
853} 852}
854 853
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f0b0e4414b00..c465d3e51e28 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2442,7 +2442,16 @@ int tcp_send_synack(struct sock *sk)
2442 return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); 2442 return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
2443} 2443}
2444 2444
2445/* Prepare a SYN-ACK. */ 2445/**
2446 * tcp_make_synack - Prepare a SYN-ACK.
2447 * sk: listener socket
2448 * dst: dst entry attached to the SYNACK
2449 * req: request_sock pointer
2450 * rvp: request_values pointer
2451 *
2452 * Allocate one skb and build a SYNACK packet.
2453 * @dst is consumed : Caller should not use it again.
2454 */
2446struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, 2455struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2447 struct request_sock *req, 2456 struct request_sock *req,
2448 struct request_values *rvp) 2457 struct request_values *rvp)
@@ -2462,13 +2471,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2462 if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) 2471 if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
2463 s_data_desired = cvp->s_data_desired; 2472 s_data_desired = cvp->s_data_desired;
2464 skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC); 2473 skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC);
2465 if (skb == NULL) 2474 if (unlikely(!skb)) {
2475 dst_release(dst);
2466 return NULL; 2476 return NULL;
2467 2477 }
2468 /* Reserve space for headers. */ 2478 /* Reserve space for headers. */
2469 skb_reserve(skb, MAX_TCP_HEADER); 2479 skb_reserve(skb, MAX_TCP_HEADER);
2470 2480
2471 skb_dst_set(skb, dst_clone(dst)); 2481 skb_dst_set(skb, dst);
2472 2482
2473 mss = dst_metric_advmss(dst); 2483 mss = dst_metric_advmss(dst);
2474 if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) 2484 if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3a9aec29581a..80758255556c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -522,7 +522,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
522done: 522done:
523 if (opt && opt != np->opt) 523 if (opt && opt != np->opt)
524 sock_kfree_s(sk, opt, opt->tot_len); 524 sock_kfree_s(sk, opt, opt->tot_len);
525 dst_release(dst);
526 return err; 525 return err;
527} 526}
528 527