Patchwork iptables: xt_hashlimit fix

login
register
mail settings
Submitter Eric Dumazet
Date Feb. 20, 2009, 6:10 p.m.
Message ID <499EF222.3060507@cosmosbay.com>
Download mbox | patch
Permalink /patch/23510/
State Not Applicable
Delegated to: David Miller
Headers show

Comments

Eric Dumazet - Feb. 20, 2009, 6:10 p.m.
Eric Dumazet a écrit :
> Stephen Hemminger a écrit :
>> The reader/writer lock in ip_tables is acquired in the critical path of
>> processing packets and is one of the reasons just loading iptables can cause
>> a 20% performance loss. The rwlock serves two functions:
>>
>> 1) it prevents changes to table state (xt_replace) while table is in use.
>>    This is now handled by doing rcu on the xt_table. When table is
>>    replaced, the new table(s) are put in and the old one table(s) are freed
>>    after RCU period.
>>
>> 2) it provides synchronization when accesing the counter values.
>>    This is now handled by swapping in new table_info entries for each cpu
>>    then summing the old values, and putting the result back onto one
>>    cpu.  On a busy system it may cause sampling to occur at different
>>    times on each cpu, but no packet/byte counts are lost in the process.
>>
>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> 
> Acked-by: Eric Dumazet <dada1@cosmosbay.com>
> 
> Sucessfully tested on my dual quad core machine too, but iptables only (no ipv6 here)
> 
> BTW, my new "tbench 8" result is 2450 MB/s, (it was 2150 MB/s not so long ago)
> 
> Thanks Stephen, thats very cool stuff, yet another rwlock out of kernel :)

Damned this broke xt_hashlimit, version=0

Look file "net/netfilter/xt_hashlimit.c" line 706

    /* Ugly hack: For SMP, we only want to use one set */
    r->u.master = r;

File "include/linux/netfilter/xt_hashlimit.h"

struct xt_hashlimit_info {
        char name [IFNAMSIZ];           /* name */
        struct hashlimit_cfg cfg;

        /* Used internally by the kernel */
        struct xt_hashlimit_htable *hinfo;
        union {
                void *ptr;
                struct xt_hashlimit_info *master;
        } u;
};


So, it appears some modules are using pointers to themselves, what a hack :(

We probably need an audit of other modules.

(net/netfilter/xt_statistic.c, net/netfilter/xt_quota.c,
net/netfilter/xt_limit.c ...)

Unfortunatly I wont have time to do this in following days, any volunteer ?

Thank you

[PATCH] netfilter: xt_hashlimit fix

Commit 784544739a25c30637397ace5489eeb6e15d7d49
(netfilter: iptables: lock free counters) broke xt_hashlimit netfilter module :

This module was storing a pointer inside its xt_hashlimit_info, and this pointer
is not relocated when we temporarly switch tables (iptables -L).

This hack is not not needed at all (probably a leftover from
ancient time), as each cpu should and can access to its own copy.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
---


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Engelhardt - Feb. 20, 2009, 6:33 p.m.
On Friday 2009-02-20 19:10, Eric Dumazet wrote:
>
>Damned this broke xt_hashlimit, version=0
>Look file "net/netfilter/xt_hashlimit.c" line 706
>
>    /* Ugly hack: For SMP, we only want to use one set */
>    r->u.master = r;
>
>So, it appears some modules are using pointers to themselves, what a hack :(
>We probably need an audit of other modules.

xt_limit and xt_statistic are affected; I'll happily fix that up.

>Commit 784544739a25c30637397ace5489eeb6e15d7d49
>(netfilter: iptables: lock free counters) broke xt_hashlimit netfilter module :
>
>This module was storing a pointer inside its xt_hashlimit_info, and 
>this pointer is not relocated when we temporarly switch tables 
>(iptables -L).

Patch ok.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy - Feb. 24, 2009, 2:31 p.m.
Eric Dumazet wrote:
> Damned this broke xt_hashlimit, version=0
> 
> ...
> So, it appears some modules are using pointers to themselves, what a hack :(

Indeed. This is unfortunately necessary in some cases to make sure
that modules using global state actually use global state instead
of the per-CPU copies.

> We probably need an audit of other modules.
> 
> (net/netfilter/xt_statistic.c, net/netfilter/xt_quota.c,
> net/netfilter/xt_limit.c ...)

This seems fine in case of hashlimit since it the match data
is read-only. In case of statistic and quota I think we still
need it I think.

> Unfortunatly I wont have time to do this in following days, any volunteer ?
> 
> Thank you
> 
> [PATCH] netfilter: xt_hashlimit fix
> 
> Commit 784544739a25c30637397ace5489eeb6e15d7d49
> (netfilter: iptables: lock free counters) broke xt_hashlimit netfilter module :
> 
> This module was storing a pointer inside its xt_hashlimit_info, and this pointer
> is not relocated when we temporarly switch tables (iptables -L).
> 
> This hack is not not needed at all (probably a leftover from
> ancient time), as each cpu should and can access to its own copy.

Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 2482055..a5b5369 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -565,8 +565,7 @@  hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
 static bool
 hashlimit_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
 {
-	const struct xt_hashlimit_info *r =
-		((const struct xt_hashlimit_info *)par->matchinfo)->u.master;
+	const struct xt_hashlimit_info *r = par->matchinfo;
 	struct xt_hashlimit_htable *hinfo = r->hinfo;
 	unsigned long now = jiffies;
 	struct dsthash_ent *dh;
@@ -702,8 +701,6 @@  static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
 	}
 	mutex_unlock(&hlimit_mutex);
 
-	/* Ugly hack: For SMP, we only want to use one set */
-	r->u.master = r;
 	return true;
 }