Commit 4aea39c1 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 90ba9b19
...@@ -848,7 +848,6 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, ...@@ -848,7 +848,6 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
err = net_xmit_eval(err); err = net_xmit_eval(err);
} }
dst_release(dst);
return err; return err;
} }
......
...@@ -2442,7 +2442,16 @@ int tcp_send_synack(struct sock *sk) ...@@ -2442,7 +2442,16 @@ int tcp_send_synack(struct sock *sk)
return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
} }
/* Prepare a SYN-ACK. */ /**
* tcp_make_synack - Prepare a SYN-ACK.
* sk: listener socket
* dst: dst entry attached to the SYNACK
* req: request_sock pointer
* rvp: request_values pointer
*
* Allocate one skb and build a SYNACK packet.
* @dst is consumed : Caller should not use it again.
*/
struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
struct request_sock *req, struct request_sock *req,
struct request_values *rvp) struct request_values *rvp)
...@@ -2462,13 +2471,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, ...@@ -2462,13 +2471,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
s_data_desired = cvp->s_data_desired; s_data_desired = cvp->s_data_desired;
skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC); skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC);
if (skb == NULL) if (unlikely(!skb)) {
dst_release(dst);
return NULL; return NULL;
}
/* Reserve space for headers. */ /* Reserve space for headers. */
skb_reserve(skb, MAX_TCP_HEADER); skb_reserve(skb, MAX_TCP_HEADER);
skb_dst_set(skb, dst_clone(dst)); skb_dst_set(skb, dst);
mss = dst_metric_advmss(dst); mss = dst_metric_advmss(dst);
if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
......
...@@ -522,7 +522,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, ...@@ -522,7 +522,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
done: done:
if (opt && opt != np->opt) if (opt && opt != np->opt)
sock_kfree_s(sk, opt, opt->tot_len); sock_kfree_s(sk, opt, opt->tot_len);
dst_release(dst);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment