tcp: avoid two atomic ops for syncookies
authorEric Dumazet <edumazet@google.com>
Mon, 5 Oct 2015 04:08:11 +0000 (21:08 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 5 Oct 2015 09:45:27 +0000 (02:45 -0700)
inet_reqsk_alloc() is used to allocate a temporary request
in order to generate a SYNACK with a cookie. Then later,
syncookie validation also uses a temporary request.

These paths already took a reference on listener refcount,
we can avoid a couple of atomic operations.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_sock.h
include/net/request_sock.h
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ipv4/syncookies.c
net/ipv4/tcp_input.c
net/ipv6/syncookies.c

index 47eb67b..f5bf731 100644 (file)
@@ -245,7 +245,8 @@ static inline unsigned int __inet_ehashfn(const __be32 laddr,
 }
 
 struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
-                                     struct sock *sk_listener);
+                                     struct sock *sk_listener,
+                                     bool attach_listener);
 
 static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
 {
index f836694..95ab5d7 100644 (file)
@@ -80,7 +80,8 @@ static inline struct sock *req_to_sk(struct request_sock *req)
 }
 
 static inline struct request_sock *
-reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener)
+reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
+           bool attach_listener)
 {
        struct request_sock *req;
 
@@ -88,8 +89,12 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener)
 
        if (req) {
                req->rsk_ops = ops;
-               sock_hold(sk_listener);
-               req->rsk_listener = sk_listener;
+               if (attach_listener) {
+                       sock_hold(sk_listener);
+                       req->rsk_listener = sk_listener;
+               } else {
+                       req->rsk_listener = NULL;
+               }
                req_to_sk(req)->sk_prot = sk_listener->sk_prot;
                sk_node_init(&req_to_sk(req)->sk_node);
                sk_tx_queue_clear(req_to_sk(req));
index 8910c95..8e99681 100644 (file)
@@ -595,7 +595,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
                goto drop;
 
-       req = inet_reqsk_alloc(&dccp_request_sock_ops, sk);
+       req = inet_reqsk_alloc(&dccp_request_sock_ops, sk, true);
        if (req == NULL)
                goto drop;
 
index 1361a3f..aed314f 100644 (file)
@@ -319,7 +319,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
                goto drop;
 
-       req = inet_reqsk_alloc(&dccp6_request_sock_ops, sk);
+       req = inet_reqsk_alloc(&dccp6_request_sock_ops, sk, true);
        if (req == NULL)
                goto drop;
 
index 729ceb5..8113c30 100644 (file)
@@ -326,7 +326,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
                goto out;
 
        ret = NULL;
-       req = inet_reqsk_alloc(&tcp_request_sock_ops, sk); /* for safety */
+       req = inet_reqsk_alloc(&tcp_request_sock_ops, sk, false); /* for safety */
        if (!req)
                goto out;
 
index a95c8eb..ddadb31 100644 (file)
@@ -6042,9 +6042,11 @@ static void tcp_openreq_init(struct request_sock *req,
 }
 
 struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
-                                     struct sock *sk_listener)
+                                     struct sock *sk_listener,
+                                     bool attach_listener)
 {
-       struct request_sock *req = reqsk_alloc(ops, sk_listener);
+       struct request_sock *req = reqsk_alloc(ops, sk_listener,
+                                              attach_listener);
 
        if (req) {
                struct inet_request_sock *ireq = inet_rsk(req);
@@ -6143,7 +6145,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                goto drop;
        }
 
-       req = inet_reqsk_alloc(rsk_ops, sk);
+       req = inet_reqsk_alloc(rsk_ops, sk, !want_cookie);
        if (!req)
                goto drop;
 
index 7606eba..f610b53 100644 (file)
@@ -170,7 +170,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
                goto out;
 
        ret = NULL;
-       req = inet_reqsk_alloc(&tcp6_request_sock_ops, sk);
+       req = inet_reqsk_alloc(&tcp6_request_sock_ops, sk, false);
        if (!req)
                goto out;