Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -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);


+15 −7
Original line number Original line Diff line number Diff line
@@ -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)
	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,
			 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);


+3 −3
Original line number Original line Diff line number Diff line
@@ -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,
			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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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)