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 47eb67b08abdf28b185514cfc1a99685a8c8b8dd..f5bf7310e3343468bddf7e51940a77ed497ad7f1 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 f83669460d82429e36d2bb4f74366092123c0162..95ab5d7aab96f970a696b3c9f1112887810388d7 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 8910c95677194f4f0261646dc97f0531cbc07670..8e99681c8189d82e3e5f6a3c6089b103c0df2ca3 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 1361a3f45df7635349f13e21db555f1180f174e1..aed314f8c7c60b00191aabc42c733f02304b18b0 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 729ceb5f63c69dc2270aafb81acd2a16ae791f33..8113c30ccf9641a76b1082bc31a9d87c76379f75 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 a95c8eb04ff77883b2b7d27b20df5279ff9f3b77..ddadb318e8507fa5be424f98221fba2079112afd 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 7606eba83e7b36f803271cd6e21ef5ea81aa0315..f610b5310b177959640dd071a5f2882c2ba1857f 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;