History

netfilter: xt_NFQUEUE: introduce CPU fanout

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. This 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. The 'flags' are folded into _v2 'bypass'. By changing the way which queue is assigned, I'm able to improve the performance if the processes reading on the NFQUEUs are pinned correctly.

holger@eitzenberger.org committed 13 years ago

Commit 8746ddc1 parent f0165882 files · +48 −2Browse files

Unified · Split

2 files
  1. include/uapi/linux/netfilter/xt_NFQUEUE.h +9 −0
  2. net/netfilter/xt_NFQUEUE.c +39 −2
include/uapi/linux/netfilter/xt_NFQUEUE.h+9−0
@@ -26,4 +26,13 @@ struct xt_NFQ_info_v2 { · 25 unmodified lines
26 __u16 bypass;26 __u16 bypass;
27};27};
28 28
29struct xt_NFQ_info_v3 {
30 __u16 queuenum;
31 __u16 queues_total;
32 __u16 flags;
33#define NFQ_FLAG_BYPASS 0x01 /* for compatibility with v2 */
34#define NFQ_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
35#define NFQ_FLAG_MASK 0x03
36};
37
29#endif /* _XT_NFQ_TARGET_H */38#endif /* _XT_NFQ_TARGET_H */
net/netfilter/xt_NFQUEUE.c+39−2
@@ -108,7 +108,7 @@ nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) · 107 unmodified lines
108 108
109static int nfqueue_tg_check(const struct xt_tgchk_param *par)109static int nfqueue_tg_check(const struct xt_tgchk_param *par)
110{110{
111 const struct xt_NFQ_info_v2 *info = par->targinfo;111 const struct xt_NFQ_info_v3 *info = par->targinfo;
112 u32 maxid;112 u32 maxid;
113 113
114 if (unlikely(!rnd_inited)) {114 if (unlikely(!rnd_inited)) {
@@ -125,11 +125,39 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par) · 10 unmodified lines
125 info->queues_total, maxid);125 info->queues_total, maxid);
126 return -ERANGE;126 return -ERANGE;
127 }127 }
128 if (par->target->revision == 2 && info->bypass > 1)128 if (par->target->revision == 2 && info->flags > 1)
129 return -EINVAL;
130 if (par->target->revision == 3 && info->flags & ~NFQ_FLAG_MASK)
129 return -EINVAL;131 return -EINVAL;
132
130 return 0;133 return 0;
131}134}
132 135
136static unsigned int
137nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
138{
139 const struct xt_NFQ_info_v3 *info = par->targinfo;
140 u32 queue = info->queuenum;
141
142 if (info->queues_total > 1) {
143 if (info->flags & NFQ_FLAG_CPU_FANOUT) {
144 int cpu = smp_processor_id();
145
146 queue = info->queuenum + cpu % info->queues_total;
147 } else {
148 if (par->family == NFPROTO_IPV4)
149 queue = (((u64) hash_v4(skb) * info->queues_total) >>
150 32) + queue;
151#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
152 else if (par->family == NFPROTO_IPV6)
153 queue = (((u64) hash_v6(skb) * info->queues_total) >>
154 32) + queue;
155#endif
156 }
157 }
158 return NF_QUEUE_NR(queue);
159}
160
133static struct xt_target nfqueue_tg_reg[] __read_mostly = {161static struct xt_target nfqueue_tg_reg[] __read_mostly = {
134 {162 {
135 .name = "NFQUEUE",163 .name = "NFQUEUE",
@@ -156,6 +184,15 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = { · 20 unmodified lines
156 .targetsize = sizeof(struct xt_NFQ_info_v2),184 .targetsize = sizeof(struct xt_NFQ_info_v2),
157 .me = THIS_MODULE,185 .me = THIS_MODULE,
158 },186 },
187 {
188 .name = "NFQUEUE",
189 .revision = 3,
190 .family = NFPROTO_UNSPEC,
191 .checkentry = nfqueue_tg_check,
192 .target = nfqueue_tg_v3,
193 .targetsize = sizeof(struct xt_NFQ_info_v3),
194 .me = THIS_MODULE,
195 },
159};196};
160 197
161static int __init nfqueue_tg_init(void)198static int __init nfqueue_tg_init(void)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t