[INET]: Generalise tcp_v4_lookup_listener
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>
Wed, 10 Aug 2005 03:09:06 +0000 (20:09 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 22:42:08 +0000 (15:42 -0700)
[acme@toy net-2.6.14]$ grep built-in /tmp/before /tmp/after
/tmp/before: 282560       13122    9312  304994   4a762 net/ipv4/built-in.o
/tmp/after:  282560       13122    9312  304994   4a762 net/ipv4/built-in.o

Will be used in DCCP, not exporting it right now not to get in Adrian
Bunk's exported-but-not-used-on-modules radar 8)

Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_hashtables.h
net/ipv4/inet_hashtables.c
net/ipv4/tcp_ipv4.c

index 6731df2cea675f9232c35b368c13afd1557ed605..1c4fa0065a8e6277821a14a8ce2c92bbd151aead 100644 (file)
 
 #include <linux/interrupt.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/socket.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -274,4 +276,38 @@ out:
        if (sk->sk_state == TCP_LISTEN)
                wake_up(&hashinfo->lhash_wait);
 }
+
+extern struct sock *__inet_lookup_listener(const struct hlist_head *head,
+                                          const u32 daddr,
+                                          const unsigned short hnum,
+                                          const int dif);
+
+/* Optimize the common listener case. */
+static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
+                                               const u32 daddr,
+                                               const unsigned short hnum,
+                                               const int dif)
+{
+       struct sock *sk = NULL;
+       struct hlist_head *head;
+
+       read_lock(&hashinfo->lhash_lock);
+       head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
+       if (!hlist_empty(head)) {
+               const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
+
+               if (inet->num == hnum && !sk->sk_node.next &&
+                   (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
+                   (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+                   !sk->sk_bound_dev_if)
+                       goto sherry_cache;
+               sk = __inet_lookup_listener(head, daddr, hnum, dif);
+       }
+       if (sk) {
+sherry_cache:
+               sock_hold(sk);
+       }
+       read_unlock(&hashinfo->lhash_lock);
+       return sk;
+}
 #endif /* _INET_HASHTABLES_H */
index 06cbc6f689c5d161bab70c2dfecd1100428729c4..88fcba05b7d646fb6b6d00e7b934063e4a79352e 100644 (file)
@@ -121,3 +121,44 @@ void inet_listen_wlock(struct inet_hashinfo *hashinfo)
 }
 
 EXPORT_SYMBOL(inet_listen_wlock);
+
+/*
+ * Don't inline this cruft. Here are some nice properties to exploit here. The
+ * BSD API does not allow a listening sock to specify the remote port nor the
+ * remote address for the connection. So always assume those are both
+ * wildcarded during the search since they can never be otherwise.
+ */
+struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr,
+                                   const unsigned short hnum, const int dif)
+{
+       struct sock *result = NULL, *sk;
+       const struct hlist_node *node;
+       int hiscore = -1;
+
+       sk_for_each(sk, node, head) {
+               const struct inet_sock *inet = inet_sk(sk);
+
+               if (inet->num == hnum && !ipv6_only_sock(sk)) {
+                       const __u32 rcv_saddr = inet->rcv_saddr;
+                       int score = sk->sk_family == PF_INET ? 1 : 0;
+
+                       if (rcv_saddr) {
+                               if (rcv_saddr != daddr)
+                                       continue;
+                               score += 2;
+                       }
+                       if (sk->sk_bound_dev_if) {
+                               if (sk->sk_bound_dev_if != dif)
+                                       continue;
+                               score += 2;
+                       }
+                       if (score == 5)
+                               return sk;
+                       if (score > hiscore) {
+                               hiscore = score;
+                               result  = sk;
+                       }
+               }
+       }
+       return result;
+}
index dca1be67164b0c1d3555d09e29283e835a1c8038..a678709b36f678b8a7dea8efd84520c2522047dd 100644 (file)
@@ -238,78 +238,6 @@ void tcp_unhash(struct sock *sk)
        inet_unhash(&tcp_hashinfo, sk);
 }
 
-/* Don't inline this cruft.  Here are some nice properties to
- * exploit here.  The BSD API does not allow a listening TCP
- * to specify the remote port nor the remote address for the
- * connection.  So always assume those are both wildcarded
- * during the search since they can never be otherwise.
- */
-static struct sock *__tcp_v4_lookup_listener(struct hlist_head *head,
-                                            const u32 daddr,
-                                            const unsigned short hnum,
-                                            const int dif)
-{
-       struct sock *result = NULL, *sk;
-       struct hlist_node *node;
-       int score, hiscore;
-
-       hiscore=-1;
-       sk_for_each(sk, node, head) {
-               struct inet_sock *inet = inet_sk(sk);
-
-               if (inet->num == hnum && !ipv6_only_sock(sk)) {
-                       __u32 rcv_saddr = inet->rcv_saddr;
-
-                       score = (sk->sk_family == PF_INET ? 1 : 0);
-                       if (rcv_saddr) {
-                               if (rcv_saddr != daddr)
-                                       continue;
-                               score+=2;
-                       }
-                       if (sk->sk_bound_dev_if) {
-                               if (sk->sk_bound_dev_if != dif)
-                                       continue;
-                               score+=2;
-                       }
-                       if (score == 5)
-                               return sk;
-                       if (score > hiscore) {
-                               hiscore = score;
-                               result = sk;
-                       }
-               }
-       }
-       return result;
-}
-
-/* Optimize the common listener case. */
-static inline struct sock *tcp_v4_lookup_listener(const u32 daddr,
-                                                 const unsigned short hnum,
-                                                 const int dif)
-{
-       struct sock *sk = NULL;
-       struct hlist_head *head;
-
-       read_lock(&tcp_hashinfo.lhash_lock);
-       head = &tcp_hashinfo.listening_hash[inet_lhashfn(hnum)];
-       if (!hlist_empty(head)) {
-               struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
-
-               if (inet->num == hnum && !sk->sk_node.next &&
-                   (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
-                   (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
-                   !sk->sk_bound_dev_if)
-                       goto sherry_cache;
-               sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
-       }
-       if (sk) {
-sherry_cache:
-               sock_hold(sk);
-       }
-       read_unlock(&tcp_hashinfo.lhash_lock);
-       return sk;
-}
-
 /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
  * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
  *
@@ -358,7 +286,7 @@ static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
        struct sock *sk = __tcp_v4_lookup_established(saddr, sport,
                                                      daddr, hnum, dif);
 
-       return sk ? : tcp_v4_lookup_listener(daddr, hnum, dif);
+       return sk ? : inet_lookup_listener(&tcp_hashinfo, daddr, hnum, dif);
 }
 
 inline struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr,
@@ -1641,9 +1569,10 @@ do_time_wait:
        switch (tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
                                           skb, th, skb->len)) {
        case TCP_TW_SYN: {
-               struct sock *sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr,
-                                                         ntohs(th->dest),
-                                                         tcp_v4_iif(skb));
+               struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
+                                                       skb->nh.iph->daddr,
+                                                       ntohs(th->dest),
+                                                       tcp_v4_iif(skb));
                if (sk2) {
                        tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
                        tcp_tw_put((struct tcp_tw_bucket *)sk);