diff options
author | Eric Dumazet <edumazet@google.com> | 2012-06-03 16:33:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-04 11:27:39 -0400 |
commit | 4aea39c11c610e411768649fdc04777903ebfe07 (patch) | |
tree | 0389be795b0ebd8c75992eedf511e2346cfbf10f | |
parent | 90ba9b1986b5ac4b2d184575847147ea7c4280a2 (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.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 18 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 1 |
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 | */ | ||
2446 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | 2455 | struct 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, | |||
522 | done: | 522 | done: |
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 | ||