Commit ba419aff authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f8ba1aff
...@@ -178,8 +178,7 @@ extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, ...@@ -178,8 +178,7 @@ extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced,
unsigned int size); unsigned int size);
extern struct nf_conntrack_tuple_hash * extern struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, __nf_conntrack_find(const struct nf_conntrack_tuple *tuple);
const struct nf_conn *ignored_conntrack);
extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_conntrack_hash_insert(struct nf_conn *ct);
......
...@@ -246,16 +246,14 @@ static void death_by_timeout(unsigned long ul_conntrack) ...@@ -246,16 +246,14 @@ static void death_by_timeout(unsigned long ul_conntrack)
} }
struct nf_conntrack_tuple_hash * struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, __nf_conntrack_find(const struct nf_conntrack_tuple *tuple)
const struct nf_conn *ignored_conntrack)
{ {
struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple_hash *h;
struct hlist_node *n; struct hlist_node *n;
unsigned int hash = hash_conntrack(tuple); unsigned int hash = hash_conntrack(tuple);
hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) { hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) {
if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && if (nf_ct_tuple_equal(tuple, &h->tuple)) {
nf_ct_tuple_equal(tuple, &h->tuple)) {
NF_CT_STAT_INC(found); NF_CT_STAT_INC(found);
return h; return h;
} }
...@@ -274,7 +272,7 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple) ...@@ -274,7 +272,7 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple)
struct nf_conn *ct; struct nf_conn *ct;
rcu_read_lock(); rcu_read_lock();
h = __nf_conntrack_find(tuple, NULL); h = __nf_conntrack_find(tuple);
if (h) { if (h) {
ct = nf_ct_tuplehash_to_ctrack(h); ct = nf_ct_tuplehash_to_ctrack(h);
if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
...@@ -395,12 +393,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, ...@@ -395,12 +393,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack) const struct nf_conn *ignored_conntrack)
{ {
struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple_hash *h;
struct hlist_node *n;
unsigned int hash = hash_conntrack(tuple);
rcu_read_lock(); 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(); rcu_read_unlock();
return h != NULL; return 0;
} }
EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
......
...@@ -1222,9 +1222,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1222,9 +1222,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
if (cda[CTA_TUPLE_ORIG]) if (cda[CTA_TUPLE_ORIG])
h = __nf_conntrack_find(&otuple, NULL); h = __nf_conntrack_find(&otuple);
else if (cda[CTA_TUPLE_REPLY]) else if (cda[CTA_TUPLE_REPLY])
h = __nf_conntrack_find(&rtuple, NULL); h = __nf_conntrack_find(&rtuple);
if (h == NULL) { if (h == NULL) {
struct nf_conntrack_tuple master; struct nf_conntrack_tuple master;
...@@ -1239,7 +1239,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1239,7 +1239,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0) if (err < 0)
goto out_unlock; goto out_unlock;
master_h = __nf_conntrack_find(&master, NULL); master_h = __nf_conntrack_find(&master);
if (master_h == NULL) { if (master_h == NULL) {
err = -ENOENT; err = -ENOENT;
goto out_unlock; goto out_unlock;
......
...@@ -124,7 +124,7 @@ static int count_them(struct xt_connlimit_data *data, ...@@ -124,7 +124,7 @@ static int count_them(struct xt_connlimit_data *data,
/* check the saved connections */ /* check the saved connections */
list_for_each_entry_safe(conn, tmp, hash, list) { 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; found_ct = NULL;
if (found != NULL) if (found != NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment