summaryrefslogtreecommitdiff
path: root/include/net
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-08-09 20:09:06 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 15:42:08 -0700
commit33b62231908c58ae04185e4f1063d1e35a7c8576 (patch)
tree502ba8c1c445d0b0f4c19d1aa3b86b01ea88478d /include/net
parent81849d106b1fb97f8e2d311c0c4d36347def55b8 (diff)
downloadlinux-3.10-33b62231908c58ae04185e4f1063d1e35a7c8576.tar.gz
linux-3.10-33b62231908c58ae04185e4f1063d1e35a7c8576.tar.bz2
linux-3.10-33b62231908c58ae04185e4f1063d1e35a7c8576.zip
[INET]: Generalise tcp_v4_lookup_listener
[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>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/inet_hashtables.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 6731df2cea6..1c4fa0065a8 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -16,8 +16,10 @@
#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 */