* [PATCH RFC 0/3] NFQUEUE: introduce CPU fanout @ 2013-03-19 14:14 holger 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: holger @ 2013-03-19 14:14 UTC (permalink / raw) To: netfilter-devel Hi, with the following patchset I'd like to improve the NFQUEUE performance if the --queue-balance argument is used for steering packets to the NFQUEUEs. By changing the way which NFQUEUE is assgined I'm able to improve the performance if the processes reading on the NFQUEUEs are pinned correctly. Current NFQUEUE target uses a hash, computed over source and destination address (and other parameters), for steering the packet to the actual NFQUEUE. This however forgets about the fact that the packet eventually is handled by a particular CPU on user request. If e. g. 1) IRQ affinity is used to handle packets on a particular CPU already (both single-queue or multi-queue case) and/or 2) RPS is used to steer packets to a specific softirq the target easily chooses an NFQUEUE which is not handled by a process pinned to the same CPU. The idea is therefore to use the CPU index for determining the NFQUEUE handling the packet. E. g. when having a system with 4 CPUs, 4 MQ queues and 4 NFQUEUEs it looks like this: +-----+ +-----+ +-----+ +-----+ |NFQ#0| |NFQ#1| |NFQ#2| |NFQ#3| +-----+ +-----+ +-----+ +-----+ ^ ^ ^ ^ | |NFQUEUE | | + + + + +-----+ +-----+ +-----+ +-----+ |rx-0 | |rx-1 | |rx-2 | |rx-3 | +-----+ +-----+ +-----+ +-----+ The NFQUEUEs not necessarily have to start with number 0, setups with less NFQUEUEs than packet-handling CPUs are not a problem as well. The first patch extends the NFQUEUE target to accept a new NFQ_FLAG_CPU_FANOUT flag. If this is specified the target uses the CPU index for determining the NFQUEUE being used. I have to introduce rev3 for this, sorry. The 2nd patch coalesces rev1 and rev3 hashing by introducing nfqueue_hash(), then used in both revisions. The 3rd patch extends iptables userspace to accept the --queue-cpu-fanout argument. This is an RFC patchset, I very much appreciate your feedback. Thank you. /Holger ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:14 [PATCH RFC 0/3] NFQUEUE: introduce CPU fanout holger @ 2013-03-19 14:14 ` holger 2013-03-19 14:26 ` David Miller 2013-03-19 19:56 ` Florian Westphal 2013-03-19 14:14 ` [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing holger 2013-03-19 14:14 ` [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter holger 2 siblings, 2 replies; 19+ messages in thread From: holger @ 2013-03-19 14:14 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1: net-next/NFQUEUE-cpu-fanout.diff --] [-- Type: text/plain, Size: 2800 bytes --] Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org> --- include/uapi/linux/netfilter/xt_NFQUEUE.h | 8 ++++++ net/netfilter/xt_NFQUEUE.c | 41 ++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/netfilter/xt_NFQUEUE.h b/include/uapi/linux/netfilter/xt_NFQUEUE.h index 9eafdbb..1f24680 100644 --- a/include/uapi/linux/netfilter/xt_NFQUEUE.h +++ b/include/uapi/linux/netfilter/xt_NFQUEUE.h @@ -26,4 +26,12 @@ struct xt_NFQ_info_v2 { __u16 bypass; }; +struct xt_NFQ_info_v3 { + __u16 queuenum; + __u16 queues_total; + __u16 bypass; + __u16 flags; +#define NFQ_FLAG_CPU_FANOUT 0x01 /* use current CPU (no hashing) */ +}; + #endif /* _XT_NFQ_TARGET_H */ diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 817f9e9..cf9c6a1 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -108,7 +108,7 @@ nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) static int nfqueue_tg_check(const struct xt_tgchk_param *par) { - const struct xt_NFQ_info_v2 *info = par->targinfo; + const struct xt_NFQ_info_v3 *info = par->targinfo; u32 maxid; if (unlikely(!rnd_inited)) { @@ -125,11 +125,39 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par) info->queues_total, maxid); return -ERANGE; } - if (par->target->revision == 2 && info->bypass > 1) + if (par->target->revision >= 2 && info->bypass > 1) + return -EINVAL; + if (par->target->revision == 3 && info->flags & ~NFQ_FLAG_CPU_FANOUT) return -EINVAL; + return 0; } +static unsigned int +nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct xt_NFQ_info_v3 *info = par->targinfo; + u32 queue = info->queuenum; + + if (info->queues_total > 1) { + if (info->flags & NFQ_FLAG_CPU_FANOUT) { + int cpu = smp_processor_id(); + + queue = info->queuenum + cpu % info->queues_total; + } else { + if (par->family == NFPROTO_IPV4) + queue = (((u64) hash_v4(skb) * info->queues_total) >> + 32) + queue; +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + else if (par->family == NFPROTO_IPV6) + queue = (((u64) hash_v6(skb) * info->queues_total) >> + 32) + queue; +#endif + } + } + return NF_QUEUE_NR(queue); +} + static struct xt_target nfqueue_tg_reg[] __read_mostly = { { .name = "NFQUEUE", @@ -156,6 +184,15 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = { .targetsize = sizeof(struct xt_NFQ_info_v2), .me = THIS_MODULE, }, + { + .name = "NFQUEUE", + .revision = 3, + .family = NFPROTO_UNSPEC, + .checkentry = nfqueue_tg_check, + .target = nfqueue_tg_v3, + .targetsize = sizeof(struct xt_NFQ_info_v3), + .me = THIS_MODULE, + }, }; static int __init nfqueue_tg_init(void) ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger @ 2013-03-19 14:26 ` David Miller 2013-03-19 14:34 ` Jan Engelhardt 2013-03-19 19:56 ` Florian Westphal 1 sibling, 1 reply; 19+ messages in thread From: David Miller @ 2013-03-19 14:26 UTC (permalink / raw) To: holger; +Cc: netfilter-devel From: holger@eitzenberger.org Date: Tue, 19 Mar 2013 15:14:43 +0100 > + if (par->family == NFPROTO_IPV4) > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > + 32) + queue; > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > + else if (par->family == NFPROTO_IPV6) > + queue = (((u64) hash_v6(skb) * info->queues_total) >> > + 32) + queue; > +#endif Maybe add a helper function so you don't have to indent so deeply. Something like: static u32 compute_queue(struct sk_buff *skb, u32 queue, u16 family, u16 qtotl) { u32 hash; if (family == NFPROTO_IPV4) hash = hash_v4(skb); #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) else if (family == NFPROTO_IPV6) hash = hash_v6(skb); #endif return (((u64) hash * qtotl) >> 32) + queue; } ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:26 ` David Miller @ 2013-03-19 14:34 ` Jan Engelhardt 2013-03-19 14:37 ` David Miller 2013-03-19 21:34 ` Holger Eitzenberger 0 siblings, 2 replies; 19+ messages in thread From: Jan Engelhardt @ 2013-03-19 14:34 UTC (permalink / raw) To: holger; +Cc: David Miller, Netfilter Developer Mailing List On Tuesday 2013-03-19 15:26, David Miller wrote: > >> + if (par->family == NFPROTO_IPV4) >> + queue = (((u64) hash_v4(skb) * info->queues_total) >> >> + 32) + queue; >> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) >> + else if (par->family == NFPROTO_IPV6) >> + queue = (((u64) hash_v6(skb) * info->queues_total) >> >> + 32) + queue; >> +#endif > >Maybe add a helper function so you don't have to indent so deeply. Something >like: And combined with smart arranging of clauses, won't need an extra helper function. http://www.braceless.org/Various/The%20Else%20Statement%20Considered%20Harmful Something like +static unsigned int +nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct xt_NFQ_info_v3 *info = par->targinfo; + u32 queue = info->queuenum; + + if (info->queues_total == 1) + return NF_QUEUE_NR(queue); + if (info->flags & NFQ_FLAG_CPU_FANOUT) { + int cpu = smp_processor_id(); + + queue = info->queuenum + cpu % info->queues_total; + } else if (par->family == NFPROTO_IPV4) { + queue = (((u64) hash_v4(skb) * info->queues_total) >> + 32) + queue; +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + } else if (par->family == NFPROTO_IPV6) { + queue = (((u64) hash_v6(skb) * info->queues_total) >> + 32) + queue; + } +#endif + return NF_QUEUE_NR(queue); +} ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:34 ` Jan Engelhardt @ 2013-03-19 14:37 ` David Miller 2013-03-19 21:38 ` Holger Eitzenberger 2013-03-19 21:34 ` Holger Eitzenberger 1 sibling, 1 reply; 19+ messages in thread From: David Miller @ 2013-03-19 14:37 UTC (permalink / raw) To: jengelh; +Cc: holger, netfilter-devel From: Jan Engelhardt <jengelh@inai.de> Date: Tue, 19 Mar 2013 15:34:56 +0100 (CET) > > On Tuesday 2013-03-19 15:26, David Miller wrote: >> >>> + if (par->family == NFPROTO_IPV4) >>> + queue = (((u64) hash_v4(skb) * info->queues_total) >> >>> + 32) + queue; >>> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) >>> + else if (par->family == NFPROTO_IPV6) >>> + queue = (((u64) hash_v6(skb) * info->queues_total) >> >>> + 32) + queue; >>> +#endif >> >>Maybe add a helper function so you don't have to indent so deeply. Something >>like: > > And combined with smart arranging of clauses, won't need an extra > helper function. > http://www.braceless.org/Various/The%20Else%20Statement%20Considered%20Harmful > > Something like Yes, but: > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > + 32) + queue; ^^^^^^ it's that terribly indented giblet that I want to disappear. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:37 ` David Miller @ 2013-03-19 21:38 ` Holger Eitzenberger 0 siblings, 0 replies; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 21:38 UTC (permalink / raw) To: David Miller; +Cc: netfilter-devel On Tue, Mar 19, 2013 at 10:37:08AM -0400, David S. Miller wrote: > From: Jan Engelhardt <jengelh@inai.de> > Date: Tue, 19 Mar 2013 15:34:56 +0100 (CET) > > > > > On Tuesday 2013-03-19 15:26, David Miller wrote: > >> > >>> + if (par->family == NFPROTO_IPV4) > >>> + queue = (((u64) hash_v4(skb) * info->queues_total) >> > >>> + 32) + queue; > >>> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > >>> + else if (par->family == NFPROTO_IPV6) > >>> + queue = (((u64) hash_v6(skb) * info->queues_total) >> > >>> + 32) + queue; > >>> +#endif > >> > >>Maybe add a helper function so you don't have to indent so deeply. Something > >>like: > > > > And combined with smart arranging of clauses, won't need an extra > > helper function. > > http://www.braceless.org/Various/The%20Else%20Statement%20Considered%20Harmful > > > > Something like > > Yes, but: > > > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > > + 32) + queue; > ^^^^^^ > > it's that terribly indented giblet that I want to disappear. Fully agreed, but at this time I kept the indentation. Take a look at the changes done in nfqueue_tg_v1() from patch #2. Will see how I can address your point. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:34 ` Jan Engelhardt 2013-03-19 14:37 ` David Miller @ 2013-03-19 21:34 ` Holger Eitzenberger 2013-03-19 21:57 ` Jan Engelhardt 1 sibling, 1 reply; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 21:34 UTC (permalink / raw) To: Jan Engelhardt; +Cc: netfilter-devel Hi Jan, > http://www.braceless.org/Various/The%20Else%20Statement%20Considered%20Harmful > > Something like > > +static unsigned int > +nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) > +{ > + const struct xt_NFQ_info_v3 *info = par->targinfo; > + u32 queue = info->queuenum; > + > + if (info->queues_total == 1) > + return NF_QUEUE_NR(queue); > + if (info->flags & NFQ_FLAG_CPU_FANOUT) { > + int cpu = smp_processor_id(); > + > + queue = info->queuenum + cpu % info->queues_total; > + } else if (par->family == NFPROTO_IPV4) { > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > + 32) + queue; > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > + } else if (par->family == NFPROTO_IPV6) { > + queue = (((u64) hash_v6(skb) * info->queues_total) >> > + 32) + queue; > + } > +#endif > + return NF_QUEUE_NR(queue); > +} having read through the webpage - and using 'goto' for error handling in own code quite often - I don't see why your code above should be more readable. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 21:34 ` Holger Eitzenberger @ 2013-03-19 21:57 ` Jan Engelhardt 2013-03-19 22:30 ` Holger Eitzenberger 0 siblings, 1 reply; 19+ messages in thread From: Jan Engelhardt @ 2013-03-19 21:57 UTC (permalink / raw) To: Holger Eitzenberger; +Cc: netfilter-devel On Tuesday 2013-03-19 22:34, Holger Eitzenberger wrote: >> http://www.braceless.org/Various/The%20Else%20Statement%20Considered%20Harmful >> >> Something like >> >> +static unsigned int >> +nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) >> +{ >> + const struct xt_NFQ_info_v3 *info = par->targinfo; >> + u32 queue = info->queuenum; >> + >> + if (info->queues_total == 1) >> + return NF_QUEUE_NR(queue); >> ... >> +} > >having read through the webpage - and using 'goto' for error handling >in own code quite often - I don't see why your code above should be >more readable. It was only coincidental that the webpage also mentioned goto. The general idea (and google keywords) was called something like "Else Considered Harmful", and the lesson consisted of early exclusion of simple cases from the flow of the remainder of the function. Perhaps to illustrate it better: list_for_each_entry(thing, &yourlist, anchor) { if (thing->property == MAGIC) { do_stuff; } } => list_for_each_entry(thing, &yourlist, anchor) { if (thing->property != MAGIC) continue; do_stuff; } Code may become more readable as one gains one level of indent and have some more freedom in arranging the giblets inside the do_stuff parts. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 21:57 ` Jan Engelhardt @ 2013-03-19 22:30 ` Holger Eitzenberger 0 siblings, 0 replies; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 22:30 UTC (permalink / raw) To: Jan Engelhardt; +Cc: netfilter-devel > >having read through the webpage - and using 'goto' for error handling > >in own code quite often - I don't see why your code above should be > >more readable. > > It was only coincidental that the webpage also mentioned goto. > The general idea (and google keywords) was called something like > "Else Considered Harmful", and the lesson consisted of early > exclusion of simple cases from the flow of the remainder of the > function. Perhaps to illustrate it better: > > list_for_each_entry(thing, &yourlist, anchor) { > if (thing->property == MAGIC) { > do_stuff; > } > } > > => > > list_for_each_entry(thing, &yourlist, anchor) { > if (thing->property != MAGIC) > continue; > do_stuff; > } > > Code may become more readable as one gains one level of indent and > have some more freedom in arranging the giblets inside the do_stuff parts. Ack. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger 2013-03-19 14:26 ` David Miller @ 2013-03-19 19:56 ` Florian Westphal 2013-03-19 20:17 ` Holger Eitzenberger 1 sibling, 1 reply; 19+ messages in thread From: Florian Westphal @ 2013-03-19 19:56 UTC (permalink / raw) To: holger; +Cc: netfilter-devel holger@eitzenberger.org <holger@eitzenberger.org> wrote: > +struct xt_NFQ_info_v3 { > + __u16 queuenum; > + __u16 queues_total; > + __u16 bypass; > + __u16 flags; > +#define NFQ_FLAG_CPU_FANOUT 0x01 /* use current CPU (no hashing) */ > +}; minor nit: 'bypass' could be folded into 'flags' via a '#define NFQ_FLAG_BYPASS'. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 1/3] NFQUEUE: introduce CPU fanout 2013-03-19 19:56 ` Florian Westphal @ 2013-03-19 20:17 ` Holger Eitzenberger 0 siblings, 0 replies; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 20:17 UTC (permalink / raw) To: Florian Westphal; +Cc: netfilter-devel > > +struct xt_NFQ_info_v3 { > > + __u16 queuenum; > > + __u16 queues_total; > > + __u16 bypass; > > + __u16 flags; > > +#define NFQ_FLAG_CPU_FANOUT 0x01 /* use current CPU (no hashing) */ > > +}; > > minor nit: > 'bypass' could be folded into 'flags' via a '#define NFQ_FLAG_BYPASS'. Yes, but I still need the new revision. Thanks. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing 2013-03-19 14:14 [PATCH RFC 0/3] NFQUEUE: introduce CPU fanout holger 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger @ 2013-03-19 14:14 ` holger 2013-03-19 14:27 ` David Miller 2013-03-19 14:14 ` [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter holger 2 siblings, 1 reply; 19+ messages in thread From: holger @ 2013-03-19 14:14 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1: net-next/NFQUEUE-coalesce.diff --] [-- Type: text/plain, Size: 2291 bytes --] Because rev1 and rev3 of the target share the same hashing generalize it by introduing nfqueue_hash(). Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org> --- net/netfilter/xt_NFQUEUE.c | 49 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index cf9c6a1..90684a1 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -76,22 +76,37 @@ static u32 hash_v6(const struct sk_buff *skb) } #endif -static unsigned int -nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) +static u32 +nfqueue_hash(const struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_NFQ_info_v1 *info = par->targinfo; - u32 queue = info->queuenum; + u32 queue; - if (info->queues_total > 1) { - if (par->family == NFPROTO_IPV4) - queue = (((u64) hash_v4(skb) * info->queues_total) >> - 32) + queue; + if (par->family == NFPROTO_IPV4) + queue = (((u64) hash_v4(skb) * info->queues_total) >> + 32) + queue; #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) - else if (par->family == NFPROTO_IPV6) - queue = (((u64) hash_v6(skb) * info->queues_total) >> - 32) + queue; + else if (par->family == NFPROTO_IPV6) + queue = (((u64) hash_v6(skb) * info->queues_total) >> + 32) + queue; #endif - } + else + queue = info->queuenum; + + return queue; +} + +static unsigned int +nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct xt_NFQ_info_v1 *info = par->targinfo; + u32 queue; + + if (info->queues_total > 1) + queue = nfqueue_hash(skb, par); + else + queue = info->queuenum; + return NF_QUEUE_NR(queue); } @@ -144,16 +159,8 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) int cpu = smp_processor_id(); queue = info->queuenum + cpu % info->queues_total; - } else { - if (par->family == NFPROTO_IPV4) - queue = (((u64) hash_v4(skb) * info->queues_total) >> - 32) + queue; -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) - else if (par->family == NFPROTO_IPV6) - queue = (((u64) hash_v6(skb) * info->queues_total) >> - 32) + queue; -#endif - } + } else + queue = nfqueue_hash(skb, par); } return NF_QUEUE_NR(queue); } ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing 2013-03-19 14:14 ` [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing holger @ 2013-03-19 14:27 ` David Miller 2013-03-19 14:39 ` Holger Eitzenberger 0 siblings, 1 reply; 19+ messages in thread From: David Miller @ 2013-03-19 14:27 UTC (permalink / raw) To: holger; +Cc: netfilter-devel From: holger@eitzenberger.org Date: Tue, 19 Mar 2013 15:14:44 +0100 > + if (par->family == NFPROTO_IPV4) > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > + 32) + queue; > #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > - else if (par->family == NFPROTO_IPV6) > - queue = (((u64) hash_v6(skb) * info->queues_total) >> > - 32) + queue; > + else if (par->family == NFPROTO_IPV6) > + queue = (((u64) hash_v6(skb) * info->queues_total) >> > + 32) + queue; > #endif Similarly, add a helper function. Since there are so many similar call sites, perhaps put it into a common header file. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing 2013-03-19 14:27 ` David Miller @ 2013-03-19 14:39 ` Holger Eitzenberger 0 siblings, 0 replies; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 14:39 UTC (permalink / raw) To: David Miller; +Cc: netfilter-devel On Tue, Mar 19, 2013 at 10:27:49AM -0400, David S. Miller wrote: > From: holger@eitzenberger.org > Date: Tue, 19 Mar 2013 15:14:44 +0100 > > > + if (par->family == NFPROTO_IPV4) > > + queue = (((u64) hash_v4(skb) * info->queues_total) >> > > + 32) + queue; > > #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > > - else if (par->family == NFPROTO_IPV6) > > - queue = (((u64) hash_v6(skb) * info->queues_total) >> > > - 32) + queue; > > + else if (par->family == NFPROTO_IPV6) > > + queue = (((u64) hash_v6(skb) * info->queues_total) >> > > + 32) + queue; > > #endif > > Similarly, add a helper function. > > Since there are so many similar call sites, perhaps put it into a > common header file. Look at patch #2! :) ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter 2013-03-19 14:14 [PATCH RFC 0/3] NFQUEUE: introduce CPU fanout holger 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger 2013-03-19 14:14 ` [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing holger @ 2013-03-19 14:14 ` holger 2013-03-19 14:34 ` Eric Leblond 2 siblings, 1 reply; 19+ messages in thread From: holger @ 2013-03-19 14:14 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1: iptables/iptables-NFQUEUE-cpu-fanout.diff --] [-- Type: text/plain, Size: 4030 bytes --] Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org> --- extensions/libxt_NFQUEUE.c | 59 +++++++++++++++++++++++++++++++++- include/linux/netfilter/xt_NFQUEUE.h | 8 +++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c index 8c2f699..8106425 100644 --- a/extensions/libxt_NFQUEUE.c +++ b/extensions/libxt_NFQUEUE.c @@ -13,8 +13,10 @@ enum { O_QUEUE_NUM = 0, O_QUEUE_BALANCE, O_QUEUE_BYPASS, + O_QUEUE_CPU_FANOUT, F_QUEUE_NUM = 1 << O_QUEUE_NUM, F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE, + F_QUEUE_CPU_FANOUT = 1 << O_QUEUE_CPU_FANOUT, }; static void NFQUEUE_help(void) @@ -37,7 +39,15 @@ static void NFQUEUE_help_v2(void) { NFQUEUE_help_v1(); printf( -" --queue-bypass Bypass Queueing if no queue instance exists.\n"); +" --queue-bypass Bypass Queueing if no queue instance exists.\n" +" --queue-cpu-fanout Use current CPU (no hashing)\n"); +} + +static void NFQUEUE_help_v3(void) +{ + NFQUEUE_help_v2(); + printf( +" --queue-cpu-fanout Use current CPU (no hashing)\n"); } #define s struct xt_NFQ_info @@ -48,6 +58,8 @@ static const struct xt_option_entry NFQUEUE_opts[] = { {.name = "queue-balance", .id = O_QUEUE_BALANCE, .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM}, {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, + {.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT, + .type = XTTYPE_NONE, .also = O_QUEUE_BALANCE}, XTOPT_TABLEEND, }; #undef s @@ -92,6 +104,18 @@ static void NFQUEUE_parse_v2(struct xt_option_call *cb) } } +static void NFQUEUE_parse_v3(struct xt_option_call *cb) +{ + struct xt_NFQ_info_v3 *info = cb->data; + + NFQUEUE_parse_v2(cb); + switch (cb->entry->id) { + case O_QUEUE_CPU_FANOUT: + info->flags |= NFQ_FLAG_CPU_FANOUT; + break; + } +} + static void NFQUEUE_print(const void *ip, const struct xt_entry_target *target, int numeric) { @@ -124,6 +148,16 @@ static void NFQUEUE_print_v2(const void *ip, printf(" bypass"); } +static void NFQUEUE_print_v3(const void *ip, + const struct xt_entry_target *target, int numeric) +{ + const struct xt_NFQ_info_v3 *info = (void *)target->data; + + NFQUEUE_print_v2(ip, target, numeric); + if (info->flags & NFQ_FLAG_CPU_FANOUT) + printf(" cpu-fanout"); +} + static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) { const struct xt_NFQ_info *tinfo = @@ -155,6 +189,16 @@ static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target printf(" --queue-bypass"); } +static void NFQUEUE_save_v3(const void *ip, + const struct xt_entry_target *target) +{ + const struct xt_NFQ_info_v3 *info = (void *)target->data; + + NFQUEUE_save_v2(ip, target); + if (info->flags & NFQ_FLAG_CPU_FANOUT) + printf(" --queue-cpu-fanout"); +} + static void NFQUEUE_init_v1(struct xt_entry_target *t) { struct xt_NFQ_info_v1 *tinfo = (void *)t->data; @@ -199,6 +243,19 @@ static struct xtables_target nfqueue_targets[] = { .save = NFQUEUE_save_v2, .x6_parse = NFQUEUE_parse_v2, .x6_options = NFQUEUE_opts, +},{ + .family = NFPROTO_UNSPEC, + .revision = 3, + .name = "NFQUEUE", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), + .help = NFQUEUE_help_v3, + .init = NFQUEUE_init_v1, + .print = NFQUEUE_print_v3, + .save = NFQUEUE_save_v3, + .x6_parse = NFQUEUE_parse_v3, + .x6_options = NFQUEUE_opts, } }; diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h index 9eafdbb..1f24680 100644 --- a/include/linux/netfilter/xt_NFQUEUE.h +++ b/include/linux/netfilter/xt_NFQUEUE.h @@ -26,4 +26,12 @@ struct xt_NFQ_info_v2 { __u16 bypass; }; +struct xt_NFQ_info_v3 { + __u16 queuenum; + __u16 queues_total; + __u16 bypass; + __u16 flags; +#define NFQ_FLAG_CPU_FANOUT 0x01 /* use current CPU (no hashing) */ +}; + #endif /* _XT_NFQ_TARGET_H */ ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter 2013-03-19 14:14 ` [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter holger @ 2013-03-19 14:34 ` Eric Leblond 2013-03-19 16:07 ` Holger Eitzenberger 2013-03-23 19:52 ` Holger Eitzenberger 0 siblings, 2 replies; 19+ messages in thread From: Eric Leblond @ 2013-03-19 14:34 UTC (permalink / raw) To: holger; +Cc: netfilter-devel Hello, Cool job! This CPU-based setup has proven to be really efficient on af_packet capture. I hope this will bring a performance boost to NFQ. If possible, it could be interesting to be able to setup the balance parameter by using an option in the same way fail-open option: uint32_t flags = NFQA_CFG_F_FAIL_OPEN; uint32_t mask = NFQA_CFG_F_FAIL_OPEN; int r = nfq_set_queue_flags(qh, mask, flags); This way, it is possible to tune the system without changing the ruleset. What do you think ? BR, On Tue, 2013-03-19 at 15:14 +0100, holger@eitzenberger.org wrote: > plain text document attachment (iptables) > Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org> > > --- > extensions/libxt_NFQUEUE.c | 59 +++++++++++++++++++++++++++++++++- > include/linux/netfilter/xt_NFQUEUE.h | 8 +++++ > 2 files changed, 66 insertions(+), 1 deletion(-) > > diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c > index 8c2f699..8106425 100644 > --- a/extensions/libxt_NFQUEUE.c > +++ b/extensions/libxt_NFQUEUE.c > @@ -13,8 +13,10 @@ enum { > O_QUEUE_NUM = 0, > O_QUEUE_BALANCE, > O_QUEUE_BYPASS, > + O_QUEUE_CPU_FANOUT, > F_QUEUE_NUM = 1 << O_QUEUE_NUM, > F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE, > + F_QUEUE_CPU_FANOUT = 1 << O_QUEUE_CPU_FANOUT, > }; > > static void NFQUEUE_help(void) > @@ -37,7 +39,15 @@ static void NFQUEUE_help_v2(void) > { > NFQUEUE_help_v1(); > printf( > -" --queue-bypass Bypass Queueing if no queue instance exists.\n"); > +" --queue-bypass Bypass Queueing if no queue instance exists.\n" > +" --queue-cpu-fanout Use current CPU (no hashing)\n"); > +} > + > +static void NFQUEUE_help_v3(void) > +{ > + NFQUEUE_help_v2(); > + printf( > +" --queue-cpu-fanout Use current CPU (no hashing)\n"); > } > > #define s struct xt_NFQ_info > @@ -48,6 +58,8 @@ static const struct xt_option_entry NFQUEUE_opts[] = { > {.name = "queue-balance", .id = O_QUEUE_BALANCE, > .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM}, > {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, > + {.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT, > + .type = XTTYPE_NONE, .also = O_QUEUE_BALANCE}, > XTOPT_TABLEEND, > }; > #undef s > @@ -92,6 +104,18 @@ static void NFQUEUE_parse_v2(struct xt_option_call *cb) > } > } > > +static void NFQUEUE_parse_v3(struct xt_option_call *cb) > +{ > + struct xt_NFQ_info_v3 *info = cb->data; > + > + NFQUEUE_parse_v2(cb); > + switch (cb->entry->id) { > + case O_QUEUE_CPU_FANOUT: > + info->flags |= NFQ_FLAG_CPU_FANOUT; > + break; > + } > +} > + > static void NFQUEUE_print(const void *ip, > const struct xt_entry_target *target, int numeric) > { > @@ -124,6 +148,16 @@ static void NFQUEUE_print_v2(const void *ip, > printf(" bypass"); > } > > +static void NFQUEUE_print_v3(const void *ip, > + const struct xt_entry_target *target, int numeric) > +{ > + const struct xt_NFQ_info_v3 *info = (void *)target->data; > + > + NFQUEUE_print_v2(ip, target, numeric); > + if (info->flags & NFQ_FLAG_CPU_FANOUT) > + printf(" cpu-fanout"); > +} > + > static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) > { > const struct xt_NFQ_info *tinfo = > @@ -155,6 +189,16 @@ static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target > printf(" --queue-bypass"); > } > > +static void NFQUEUE_save_v3(const void *ip, > + const struct xt_entry_target *target) > +{ > + const struct xt_NFQ_info_v3 *info = (void *)target->data; > + > + NFQUEUE_save_v2(ip, target); > + if (info->flags & NFQ_FLAG_CPU_FANOUT) > + printf(" --queue-cpu-fanout"); > +} > + > static void NFQUEUE_init_v1(struct xt_entry_target *t) > { > struct xt_NFQ_info_v1 *tinfo = (void *)t->data; > @@ -199,6 +243,19 @@ static struct xtables_target nfqueue_targets[] = { > .save = NFQUEUE_save_v2, > .x6_parse = NFQUEUE_parse_v2, > .x6_options = NFQUEUE_opts, > +},{ > + .family = NFPROTO_UNSPEC, > + .revision = 3, > + .name = "NFQUEUE", > + .version = XTABLES_VERSION, > + .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), > + .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)), > + .help = NFQUEUE_help_v3, > + .init = NFQUEUE_init_v1, > + .print = NFQUEUE_print_v3, > + .save = NFQUEUE_save_v3, > + .x6_parse = NFQUEUE_parse_v3, > + .x6_options = NFQUEUE_opts, > } > }; > > diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h > index 9eafdbb..1f24680 100644 > --- a/include/linux/netfilter/xt_NFQUEUE.h > +++ b/include/linux/netfilter/xt_NFQUEUE.h > @@ -26,4 +26,12 @@ struct xt_NFQ_info_v2 { > __u16 bypass; > }; > > +struct xt_NFQ_info_v3 { > + __u16 queuenum; > + __u16 queues_total; > + __u16 bypass; > + __u16 flags; > +#define NFQ_FLAG_CPU_FANOUT 0x01 /* use current CPU (no hashing) */ > +}; > + > #endif /* _XT_NFQ_TARGET_H */ > > -- > To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Eric Leblond <eric@regit.org> Blog: https://home.regit.org/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter 2013-03-19 14:34 ` Eric Leblond @ 2013-03-19 16:07 ` Holger Eitzenberger 2013-03-23 19:52 ` Holger Eitzenberger 1 sibling, 0 replies; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-19 16:07 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel Hi Eric, > Cool job! This CPU-based setup has proven to be really efficient on > af_packet capture. I hope this will bring a performance boost to NFQ. > > If possible, it could be interesting to be able to setup the balance > parameter by using an option in the same way fail-open option: > uint32_t flags = NFQA_CFG_F_FAIL_OPEN; > uint32_t mask = NFQA_CFG_F_FAIL_OPEN; > int r = nfq_set_queue_flags(qh, mask, flags); > This way, it is possible to tune the system without changing the > ruleset. > > What do you think ? seems like a good change to me. I will add that as well! ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter 2013-03-19 14:34 ` Eric Leblond 2013-03-19 16:07 ` Holger Eitzenberger @ 2013-03-23 19:52 ` Holger Eitzenberger 2013-03-23 21:53 ` Eric Leblond 1 sibling, 1 reply; 19+ messages in thread From: Holger Eitzenberger @ 2013-03-23 19:52 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel Hi Eric, > If possible, it could be interesting to be able to setup the balance > parameter by using an option in the same way fail-open option: > uint32_t flags = NFQA_CFG_F_FAIL_OPEN; > uint32_t mask = NFQA_CFG_F_FAIL_OPEN; > int r = nfq_set_queue_flags(qh, mask, flags); > This way, it is possible to tune the system without changing the > ruleset. Not sure how the FAIL_OPEN relates to the CPU fanout. Do you want to setup the CPU fanout (on, off) per queue? /Holger ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter 2013-03-23 19:52 ` Holger Eitzenberger @ 2013-03-23 21:53 ` Eric Leblond 0 siblings, 0 replies; 19+ messages in thread From: Eric Leblond @ 2013-03-23 21:53 UTC (permalink / raw) To: Holger Eitzenberger; +Cc: netfilter-devel Hi, On Sat, 2013-03-23 at 20:52 +0100, Holger Eitzenberger wrote: > Hi Eric, > > > If possible, it could be interesting to be able to setup the balance > > parameter by using an option in the same way fail-open option: > > uint32_t flags = NFQA_CFG_F_FAIL_OPEN; > > uint32_t mask = NFQA_CFG_F_FAIL_OPEN; > > int r = nfq_set_queue_flags(qh, mask, flags); > > This way, it is possible to tune the system without changing the > > ruleset. > > Not sure how the FAIL_OPEN relates to the CPU fanout. Do you want to > setup the CPU fanout (on, off) per queue? You are right on a major point. FAIL_OPEN is definitely per-queue and CPU fanout is related to a fanout group. So we will have to have the whole mechanism bind to a queue, warn the kernel that it is in a fanout group... That could be interesting as we will be able to tune the setting from the application but this seems to be a lot of work too. And I don't see any functional benefit omit this tuning from the application. So, if you don't find any other one, forgot my request for now :) BR, -- Eric Leblond <eric@regit.org> Blog: https://home.regit.org/ ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2013-03-23 21:53 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-03-19 14:14 [PATCH RFC 0/3] NFQUEUE: introduce CPU fanout holger 2013-03-19 14:14 ` [PATCH RFC 1/3] " holger 2013-03-19 14:26 ` David Miller 2013-03-19 14:34 ` Jan Engelhardt 2013-03-19 14:37 ` David Miller 2013-03-19 21:38 ` Holger Eitzenberger 2013-03-19 21:34 ` Holger Eitzenberger 2013-03-19 21:57 ` Jan Engelhardt 2013-03-19 22:30 ` Holger Eitzenberger 2013-03-19 19:56 ` Florian Westphal 2013-03-19 20:17 ` Holger Eitzenberger 2013-03-19 14:14 ` [PATCH RFC 2/3] NFQUEUE: coalesce IPv4 and IPv6 hashing holger 2013-03-19 14:27 ` David Miller 2013-03-19 14:39 ` Holger Eitzenberger 2013-03-19 14:14 ` [PATCH RFC 3/3] NFQUEUE: add --queue-cpu-fanout parameter holger 2013-03-19 14:34 ` Eric Leblond 2013-03-19 16:07 ` Holger Eitzenberger 2013-03-23 19:52 ` Holger Eitzenberger 2013-03-23 21:53 ` Eric Leblond
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.