From ba419aff2cda91680e5d4d3eeff95df49bd2edec Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 31 Jan 2008 04:39:23 -0800 Subject: [PATCH] [NETFILTER]: nf_conntrack: optimize __nf_conntrack_find() Ignoring specific entries in __nf_conntrack_find() is only needed by NAT for nf_conntrack_tuple_taken(). Remove it from __nf_conntrack_find() and make nf_conntrack_tuple_taken() search the hash itself. Saves 54 bytes of text in the hotpath on x86_64: __nf_conntrack_find | -54 # 321 -> 267, # inlines: 3 -> 2, size inlines: 181 -> 127 nf_conntrack_tuple_taken | +305 # 15 -> 320, lexblocks: 0 -> 3, # inlines: 0 -> 3, size inlines: 0 -> 181 nf_conntrack_find_get | -2 # 90 -> 88 3 functions changed, 305 bytes added, 56 bytes removed, diff: +249 Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 3 +-- net/netfilter/nf_conntrack_core.c | 22 +++++++++++++++------- net/netfilter/nf_conntrack_netlink.c | 6 +++--- net/netfilter/xt_connlimit.c | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 561ae7658f55..14e0cc8364f2 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -178,8 +178,7 @@ extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int size); extern struct nf_conntrack_tuple_hash * -__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack); +__nf_conntrack_find(const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f284dddfc899..ce4c4ba31cb1 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -246,16 +246,14 @@ static void death_by_timeout(unsigned long ul_conntrack) } struct nf_conntrack_tuple_hash * -__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack) +__nf_conntrack_find(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; struct hlist_node *n; unsigned int hash = hash_conntrack(tuple); hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) { - if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && - nf_ct_tuple_equal(tuple, &h->tuple)) { + if (nf_ct_tuple_equal(tuple, &h->tuple)) { NF_CT_STAT_INC(found); return h; } @@ -274,7 +272,7 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple) struct nf_conn *ct; rcu_read_lock(); - h = __nf_conntrack_find(tuple, NULL); + h = __nf_conntrack_find(tuple); if (h) { ct = nf_ct_tuplehash_to_ctrack(h); if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) @@ -395,12 +393,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack) { struct nf_conntrack_tuple_hash *h; + struct hlist_node *n; + unsigned int hash = hash_conntrack(tuple); rcu_read_lock(); - h = __nf_conntrack_find(tuple, ignored_conntrack); + hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) { + if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && + nf_ct_tuple_equal(tuple, &h->tuple)) { + NF_CT_STAT_INC(found); + rcu_read_unlock(); + return 1; + } + NF_CT_STAT_INC(searched); + } rcu_read_unlock(); - return h != NULL; + return 0; } EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b6a8c089a075..bf86fdd89fd0 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1222,9 +1222,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, spin_lock_bh(&nf_conntrack_lock); if (cda[CTA_TUPLE_ORIG]) - h = __nf_conntrack_find(&otuple, NULL); + h = __nf_conntrack_find(&otuple); else if (cda[CTA_TUPLE_REPLY]) - h = __nf_conntrack_find(&rtuple, NULL); + h = __nf_conntrack_find(&rtuple); if (h == NULL) { struct nf_conntrack_tuple master; @@ -1239,7 +1239,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) goto out_unlock; - master_h = __nf_conntrack_find(&master, NULL); + master_h = __nf_conntrack_find(&master); if (master_h == NULL) { err = -ENOENT; goto out_unlock; diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index f9b59a6753ee..3b0111933f60 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -124,7 +124,7 @@ static int count_them(struct xt_connlimit_data *data, /* check the saved connections */ list_for_each_entry_safe(conn, tmp, hash, list) { - found = __nf_conntrack_find(&conn->tuple, NULL); + found = __nf_conntrack_find(&conn->tuple); found_ct = NULL; if (found != NULL) -- 2.20.1