* [PATCH 1/2] netfilter: nft: fix issue with verdict support
2013-11-30 10:52 [nft PATCH] add support for queue target Eric Leblond
@ 2013-11-30 10:56 ` Eric Leblond
2013-11-30 10:56 ` [PATCH 2/2] netfilter: nft: add queue module Eric Leblond
2013-11-30 10:57 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Eric Leblond
2013-11-30 10:57 ` [nft PATCH] Add support for queue target Eric Leblond
2 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 10:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
The test on verdict was simply done on the value of the verdict
which is not correct as far as queue is concern. In fact, the test
of verdict test must be done with respect to the verdict mask for
verdicts which are not internal to nftables.
Signed-off-by: Eric Leblond <eric@regit.org>
---
net/netfilter/nf_tables_core.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index cb9e685..e8fcc34 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -164,7 +164,7 @@ next_rule:
break;
}
- switch (data[NFT_REG_VERDICT].verdict) {
+ switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule:
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
return data[NFT_REG_VERDICT].verdict;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict) {
case NFT_JUMP:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH 2/2] netfilter: nft: add queue module
2013-11-30 10:56 ` [PATCH 1/2] netfilter: nft: fix issue with verdict support Eric Leblond
@ 2013-11-30 10:56 ` Eric Leblond
2013-11-30 12:26 ` Florian Westphal
2013-12-02 6:39 ` [PATCH 2/2] " Tomasz Bursztyka
0 siblings, 2 replies; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 10:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
This patch adds a new nft module named "nft_queue" which is a
nftables target sending packet to nfnetlink_queue subsystem. It has
the same level of functionnality as is iptables ancestor and share
some code with it.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/uapi/linux/netfilter/nf_tables.h | 21 ++++
net/netfilter/Kconfig | 9 ++
net/netfilter/Makefile | 1 +
net/netfilter/nft_queue.c | 189 +++++++++++++++++++++++++++++++
4 files changed, 220 insertions(+)
create mode 100644 net/netfilter/nft_queue.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index fbfd229..ffcb685 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -658,6 +658,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
@@ -682,6 +702,7 @@ enum nft_reject_attributes {
};
#define NFTA_REJECT_MAX (__NFTA_REJECT_MAX - 1)
+
/**
* enum nft_nat_types - nf_tables nat expression NAT types
*
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c3398cd..cf0872d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -456,6 +456,15 @@ config NFT_NAT
depends on NF_NAT
tristate "Netfilter nf_tables nat module"
+config NFT_QUEUE
+ depends on NF_TABLES
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_NETLINK_QUEUE
+ tristate "Netfilter nf_tables queue module"
+ help
+ This is required if you intend to use nfnetlink queue
+ on more than the default queue 0 or with the other features
+
config NFT_COMPAT
depends on NF_TABLES
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 394483b..e763746 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
obj-$(CONFIG_NFT_CT) += nft_ct.o
obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
obj-$(CONFIG_NFT_NAT) += nft_nat.o
+obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
#nf_tables-objs += nft_meta_target.o
obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
obj-$(CONFIG_NFT_HASH) += nft_hash.o
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644
index 0000000..3f7cdd1
--- /dev/null
+++ b/net/netfilter/nft_queue.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
+#include <linux/jhash.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+struct nft_queue {
+ u16 queuenum;
+ u16 queues_total;
+ u16 flags;
+ int family;
+};
+
+static u32 jhash_initval __read_mostly;
+
+static u32 hash_v4(const struct sk_buff *skb)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+
+ /* packets in either direction go into same queue */
+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+ return jhash_3words((__force u32)iph->saddr,
+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+ return jhash_3words((__force u32)iph->daddr,
+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static u32 hash_v6(const struct sk_buff *skb)
+{
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ u32 a, b, c;
+
+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
+ (__force u32)ip6h->daddr.s6_addr32[3]) {
+ a = (__force u32) ip6h->saddr.s6_addr32[3];
+ b = (__force u32) ip6h->daddr.s6_addr32[3];
+ } else {
+ b = (__force u32) ip6h->saddr.s6_addr32[3];
+ a = (__force u32) ip6h->daddr.s6_addr32[3];
+ }
+
+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
+ (__force u32)ip6h->daddr.s6_addr32[1])
+ c = (__force u32) ip6h->saddr.s6_addr32[1];
+ else
+ c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+ return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static u32
+nfqueue_hash(const struct nft_pktinfo *pkt, const struct nft_queue *priv)
+{
+ u32 queue = priv->queuenum;
+
+ if (priv->family == AF_INET)
+ queue += ((u64) hash_v4(pkt->skb) * priv->queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+ else if (priv->family == AF_INET6)
+ queue += ((u64) hash_v6(pkt->skb) * priv->queues_total) >> 32;
+#endif
+
+ return queue;
+}
+
+static void nft_queue_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1],
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+ u32 queue = priv->queuenum;
+ u32 ret;
+
+ if (priv->queues_total > 1) {
+ if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ int cpu = smp_processor_id();
+
+ queue = priv->queuenum + cpu % priv->queues_total;
+ } else
+ queue = nfqueue_hash(pkt, priv);
+ }
+
+ ret = NF_QUEUE_NR(queue);
+ if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
+ ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+ data[NFT_REG_VERDICT].verdict = ret;
+}
+
+static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+ [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
+ [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
+ [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
+};
+
+static int nft_queue_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+
+ priv->family = ctx->afi->family;
+
+ if (tb[NFTA_QUEUE_NUM] == NULL)
+ return -EINVAL;
+ priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
+
+ if (tb[NFTA_QUEUE_TOTAL] != NULL)
+ priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
+ if (tb[NFTA_QUEUE_FLAGS] != NULL) {
+ priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
+ if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_queue *priv = nft_expr_priv(expr);
+
+ if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)))
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)))
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_queue_type;
+static const struct nft_expr_ops nft_queue_ops = {
+ .type = &nft_queue_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
+ .eval = nft_queue_eval,
+ .init = nft_queue_init,
+ .dump = nft_queue_dump,
+};
+
+static struct nft_expr_type nft_queue_type __read_mostly = {
+ .name = "queue",
+ .ops = &nft_queue_ops,
+ .policy = nft_queue_policy,
+ .maxattr = NFTA_QUEUE_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_queue_module_init(void)
+{
+ return nft_register_expr(&nft_queue_type);
+}
+
+static void __exit nft_queue_module_exit(void)
+{
+ nft_unregister_expr(&nft_queue_type);
+}
+
+module_init(nft_queue_module_init);
+module_exit(nft_queue_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
+MODULE_ALIAS_NFT_EXPR("queue");
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 2/2] netfilter: nft: add queue module
2013-11-30 10:56 ` [PATCH 2/2] netfilter: nft: add queue module Eric Leblond
@ 2013-11-30 12:26 ` Florian Westphal
2013-11-30 15:14 ` [PATCHv2] " Eric Leblond
2013-12-02 6:39 ` [PATCH 2/2] " Tomasz Bursztyka
1 sibling, 1 reply; 32+ messages in thread
From: Florian Westphal @ 2013-11-30 12:26 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
Eric Leblond <eric@regit.org> wrote:
> This patch adds a new nft module named "nft_queue" which is a
> nftables target sending packet to nfnetlink_queue subsystem. It has
> the same level of functionnality as is iptables ancestor and share
> some code with it.
> +static u32 jhash_initval __read_mostly;
Consider adding something like
> +static int nft_queue_init(const struct nft_ctx *ctx,
> + const struct nft_expr *expr,
> + const struct nlattr * const tb[])
> +{
> + struct nft_queue *priv = nft_expr_priv(expr);
while (jhash_initval == 0)
jhash_initval = prandom_u32();
Other than this, it looks good to me.
Thanks for spending time on this!
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv2] netfilter: nft: add queue module
2013-11-30 12:26 ` Florian Westphal
@ 2013-11-30 15:14 ` Eric Leblond
2013-12-04 11:00 ` Pablo Neira Ayuso
0 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 15:14 UTC (permalink / raw)
To: Florian Westphal, pablo; +Cc: netfilter-devel, Eric Leblond
This patch adds a new nft module named "nft_queue" which is a
nftables target sending packet to nfnetlink_queue subsystem. It has
the same level of functionnality as is iptables ancestor and share
some code with it.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/uapi/linux/netfilter/nf_tables.h | 20 ++++
net/netfilter/Kconfig | 9 ++
net/netfilter/Makefile | 1 +
net/netfilter/nft_queue.c | 192 +++++++++++++++++++++++++++++++
4 files changed, 222 insertions(+)
create mode 100644 net/netfilter/nft_queue.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index fbfd229..256d36b 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -658,6 +658,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c3398cd..cf0872d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -456,6 +456,15 @@ config NFT_NAT
depends on NF_NAT
tristate "Netfilter nf_tables nat module"
+config NFT_QUEUE
+ depends on NF_TABLES
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_NETLINK_QUEUE
+ tristate "Netfilter nf_tables queue module"
+ help
+ This is required if you intend to use nfnetlink queue
+ on more than the default queue 0 or with the other features
+
config NFT_COMPAT
depends on NF_TABLES
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 394483b..e763746 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
obj-$(CONFIG_NFT_CT) += nft_ct.o
obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
obj-$(CONFIG_NFT_NAT) += nft_nat.o
+obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
#nf_tables-objs += nft_meta_target.o
obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
obj-$(CONFIG_NFT_HASH) += nft_hash.o
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644
index 0000000..88cdf16
--- /dev/null
+++ b/net/netfilter/nft_queue.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
+#include <linux/jhash.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+struct nft_queue {
+ u16 queuenum;
+ u16 queues_total;
+ u16 flags;
+ int family;
+};
+
+static u32 jhash_initval __read_mostly;
+
+static u32 hash_v4(const struct sk_buff *skb)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+
+ /* packets in either direction go into same queue */
+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+ return jhash_3words((__force u32)iph->saddr,
+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+ return jhash_3words((__force u32)iph->daddr,
+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static u32 hash_v6(const struct sk_buff *skb)
+{
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ u32 a, b, c;
+
+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
+ (__force u32)ip6h->daddr.s6_addr32[3]) {
+ a = (__force u32) ip6h->saddr.s6_addr32[3];
+ b = (__force u32) ip6h->daddr.s6_addr32[3];
+ } else {
+ b = (__force u32) ip6h->saddr.s6_addr32[3];
+ a = (__force u32) ip6h->daddr.s6_addr32[3];
+ }
+
+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
+ (__force u32)ip6h->daddr.s6_addr32[1])
+ c = (__force u32) ip6h->saddr.s6_addr32[1];
+ else
+ c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+ return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static u32
+nfqueue_hash(const struct nft_pktinfo *pkt, const struct nft_queue *priv)
+{
+ u32 queue = priv->queuenum;
+
+ if (priv->family == AF_INET)
+ queue += ((u64) hash_v4(pkt->skb) * priv->queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+ else if (priv->family == AF_INET6)
+ queue += ((u64) hash_v6(pkt->skb) * priv->queues_total) >> 32;
+#endif
+
+ return queue;
+}
+
+static void nft_queue_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1],
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+ u32 queue = priv->queuenum;
+ u32 ret;
+
+ if (priv->queues_total > 1) {
+ if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ int cpu = smp_processor_id();
+
+ queue = priv->queuenum + cpu % priv->queues_total;
+ } else
+ queue = nfqueue_hash(pkt, priv);
+ }
+
+ ret = NF_QUEUE_NR(queue);
+ if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
+ ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+ data[NFT_REG_VERDICT].verdict = ret;
+}
+
+static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+ [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
+ [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
+ [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
+};
+
+static int nft_queue_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+
+ while (jhash_initval == 0)
+ jhash_initval = prandom_u32();
+
+ priv->family = ctx->afi->family;
+
+ if (tb[NFTA_QUEUE_NUM] == NULL)
+ return -EINVAL;
+ priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
+
+ if (tb[NFTA_QUEUE_TOTAL] != NULL)
+ priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
+ if (tb[NFTA_QUEUE_FLAGS] != NULL) {
+ priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
+ if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_queue *priv = nft_expr_priv(expr);
+
+ if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)))
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)))
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_queue_type;
+static const struct nft_expr_ops nft_queue_ops = {
+ .type = &nft_queue_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
+ .eval = nft_queue_eval,
+ .init = nft_queue_init,
+ .dump = nft_queue_dump,
+};
+
+static struct nft_expr_type nft_queue_type __read_mostly = {
+ .name = "queue",
+ .ops = &nft_queue_ops,
+ .policy = nft_queue_policy,
+ .maxattr = NFTA_QUEUE_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_queue_module_init(void)
+{
+ return nft_register_expr(&nft_queue_type);
+}
+
+static void __exit nft_queue_module_exit(void)
+{
+ nft_unregister_expr(&nft_queue_type);
+}
+
+module_init(nft_queue_module_init);
+module_exit(nft_queue_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
+MODULE_ALIAS_NFT_EXPR("queue");
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCHv2] netfilter: nft: add queue module
2013-11-30 15:14 ` [PATCHv2] " Eric Leblond
@ 2013-12-04 11:00 ` Pablo Neira Ayuso
2013-12-04 11:31 ` Florian Westphal
2013-12-04 12:47 ` Eric Leblond
0 siblings, 2 replies; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-04 11:00 UTC (permalink / raw)
To: Eric Leblond; +Cc: Florian Westphal, netfilter-devel
Hi Eric,
First off, thanks for this patch. Some comments below.
On Sat, Nov 30, 2013 at 04:14:04PM +0100, Eric Leblond wrote:
> This patch adds a new nft module named "nft_queue" which is a
> nftables target sending packet to nfnetlink_queue subsystem. It has
> the same level of functionnality as is iptables ancestor and share
> some code with it.
>
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> include/uapi/linux/netfilter/nf_tables.h | 20 ++++
> net/netfilter/Kconfig | 9 ++
> net/netfilter/Makefile | 1 +
> net/netfilter/nft_queue.c | 192 +++++++++++++++++++++++++++++++
> 4 files changed, 222 insertions(+)
> create mode 100644 net/netfilter/nft_queue.c
>
> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
> index fbfd229..256d36b 100644
> --- a/include/uapi/linux/netfilter/nf_tables.h
> +++ b/include/uapi/linux/netfilter/nf_tables.h
> @@ -658,6 +658,26 @@ enum nft_log_attributes {
> #define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
>
> /**
> + * enum nft_queue_attributes - nf_tables queue expression netlink attributes
> + *
> + * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
> + * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
> + * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
> + */
> +enum nft_queue_attributes {
> + NFTA_QUEUE_UNSPEC,
> + NFTA_QUEUE_NUM,
> + NFTA_QUEUE_TOTAL,
> + NFTA_QUEUE_FLAGS,
> + __NFTA_QUEUE_MAX
> +};
> +#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
> +
> +#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
> +#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
> +#define NFT_QUEUE_FLAG_MASK 0x03
> +
> +/**
> * enum nft_reject_types - nf_tables reject expression reject types
> *
> * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index c3398cd..cf0872d 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -456,6 +456,15 @@ config NFT_NAT
> depends on NF_NAT
> tristate "Netfilter nf_tables nat module"
>
> +config NFT_QUEUE
> + depends on NF_TABLES
> + depends on NETFILTER_XTABLES
> + depends on NETFILTER_NETLINK_QUEUE
> + tristate "Netfilter nf_tables queue module"
> + help
> + This is required if you intend to use nfnetlink queue
> + on more than the default queue 0 or with the other features
> +
> config NFT_COMPAT
> depends on NF_TABLES
> depends on NETFILTER_XTABLES
> diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
> index 394483b..e763746 100644
> --- a/net/netfilter/Makefile
> +++ b/net/netfilter/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
> obj-$(CONFIG_NFT_CT) += nft_ct.o
> obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
> obj-$(CONFIG_NFT_NAT) += nft_nat.o
> +obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
> #nf_tables-objs += nft_meta_target.o
> obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
> obj-$(CONFIG_NFT_HASH) += nft_hash.o
> diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
> new file mode 100644
> index 0000000..88cdf16
> --- /dev/null
> +++ b/net/netfilter/nft_queue.c
> @@ -0,0 +1,192 @@
> +/*
> + * Copyright (c) 2013 Eric Leblond <eric@regit.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/netlink.h>
> +
> +#include <linux/ip.h>
> +#include <linux/ipv6.h>
> +#include <linux/jhash.h>
> +
> +#include <linux/jhash.h>
> +#include <linux/netfilter.h>
> +#include <linux/netfilter/nf_tables.h>
> +#include <net/netfilter/nf_tables.h>
> +
> +struct nft_queue {
> + u16 queuenum;
> + u16 queues_total;
> + u16 flags;
> + int family;
^
This structure is very important that it doesn't have any hole (at its
best) to reduce the size of the expression area in the rule. My
proposal:
...
{
u16 queue_num;
u16 queue_total;
u16 flags;
u8 family;
}
> +};
> +
> +static u32 jhash_initval __read_mostly;
>From here:
> +static u32 hash_v4(const struct sk_buff *skb)
> +{
> + const struct iphdr *iph = ip_hdr(skb);
> +
> + /* packets in either direction go into same queue */
> + if ((__force u32)iph->saddr < (__force u32)iph->daddr)
> + return jhash_3words((__force u32)iph->saddr,
> + (__force u32)iph->daddr, iph->protocol, jhash_initval);
> +
> + return jhash_3words((__force u32)iph->daddr,
> + (__force u32)iph->saddr, iph->protocol, jhash_initval);
> +}
> +
> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> +static u32 hash_v6(const struct sk_buff *skb)
> +{
> + const struct ipv6hdr *ip6h = ipv6_hdr(skb);
> + u32 a, b, c;
> +
> + if ((__force u32)ip6h->saddr.s6_addr32[3] <
> + (__force u32)ip6h->daddr.s6_addr32[3]) {
> + a = (__force u32) ip6h->saddr.s6_addr32[3];
> + b = (__force u32) ip6h->daddr.s6_addr32[3];
> + } else {
> + b = (__force u32) ip6h->saddr.s6_addr32[3];
> + a = (__force u32) ip6h->daddr.s6_addr32[3];
> + }
> +
> + if ((__force u32)ip6h->saddr.s6_addr32[1] <
> + (__force u32)ip6h->daddr.s6_addr32[1])
> + c = (__force u32) ip6h->saddr.s6_addr32[1];
> + else
> + c = (__force u32) ip6h->daddr.s6_addr32[1];
> +
> + return jhash_3words(a, b, c, jhash_initval);
> +}
> +#endif
> +
> +static u32
> +nfqueue_hash(const struct nft_pktinfo *pkt, const struct nft_queue *priv)
> +{
> + u32 queue = priv->queuenum;
> +
> + if (priv->family == AF_INET)
> + queue += ((u64) hash_v4(pkt->skb) * priv->queues_total) >> 32;
> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> + else if (priv->family == AF_INET6)
> + queue += ((u64) hash_v6(pkt->skb) * priv->queues_total) >> 32;
> +#endif
> +
> + return queue;
> +}
to there, it looks very similar to NFQUEUE. You can move these
functions to net/netfilter/nf_queue.h. You'll have to inline them and
add the jhash_initval parameter. You'll need an initial patch to
prepare this change and adapt xt_NFQUEUE.c
> +
> +static void nft_queue_eval(const struct nft_expr *expr,
> + struct nft_data data[NFT_REG_MAX + 1],
> + const struct nft_pktinfo *pkt)
> +{
> + struct nft_queue *priv = nft_expr_priv(expr);
> + u32 queue = priv->queuenum;
> + u32 ret;
> +
> + if (priv->queues_total > 1) {
> + if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
> + int cpu = smp_processor_id();
> +
> + queue = priv->queuenum + cpu % priv->queues_total;
> + } else
> + queue = nfqueue_hash(pkt, priv);
> + }
> +
> + ret = NF_QUEUE_NR(queue);
> + if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
> + ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
> +
> + data[NFT_REG_VERDICT].verdict = ret;
> +}
> +
> +static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
> + [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
> + [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
> + [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
^------------^
Comestic: I think one tab should be fine.
> +};
> +
> +static int nft_queue_init(const struct nft_ctx *ctx,
> + const struct nft_expr *expr,
> + const struct nlattr * const tb[])
> +{
> + struct nft_queue *priv = nft_expr_priv(expr);
> +
> + while (jhash_initval == 0)
> + jhash_initval = prandom_u32();
Different initialization approach with regards to xt_NFQUEUE, any
reason for that change?
> +
> + priv->family = ctx->afi->family;
> +
> + if (tb[NFTA_QUEUE_NUM] == NULL)
> + return -EINVAL;
> + priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
> +
> + if (tb[NFTA_QUEUE_TOTAL] != NULL)
> + priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
> + if (tb[NFTA_QUEUE_FLAGS] != NULL) {
> + priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
> + if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
> +{
> + const struct nft_queue *priv = nft_expr_priv(expr);
> +
> + if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)))
> + goto nla_put_failure;
> +
> + if (nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)))
> + goto nla_put_failure;
> +
> + if (nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
> + goto nla_put_failure;
Comestic: Perhaps you can squash these three put lines in one single
if to save a couple of lines, the code will be still quite readable.
> +
> + return 0;
> +
> +nla_put_failure:
> + return -1;
> +}
> +
> +static struct nft_expr_type nft_queue_type;
> +static const struct nft_expr_ops nft_queue_ops = {
> + .type = &nft_queue_type,
> + .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
> + .eval = nft_queue_eval,
> + .init = nft_queue_init,
> + .dump = nft_queue_dump,
> +};
> +
> +static struct nft_expr_type nft_queue_type __read_mostly = {
> + .name = "queue",
> + .ops = &nft_queue_ops,
> + .policy = nft_queue_policy,
> + .maxattr = NFTA_QUEUE_MAX,
> + .owner = THIS_MODULE,
> +};
> +
> +static int __init nft_queue_module_init(void)
> +{
> + return nft_register_expr(&nft_queue_type);
> +}
> +
> +static void __exit nft_queue_module_exit(void)
> +{
> + nft_unregister_expr(&nft_queue_type);
> +}
> +
> +module_init(nft_queue_module_init);
> +module_exit(nft_queue_module_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
> +MODULE_ALIAS_NFT_EXPR("queue");
> --
> 1.8.4.4
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCHv2] netfilter: nft: add queue module
2013-12-04 11:00 ` Pablo Neira Ayuso
@ 2013-12-04 11:31 ` Florian Westphal
2013-12-04 11:39 ` Pablo Neira Ayuso
2013-12-04 12:47 ` Eric Leblond
1 sibling, 1 reply; 32+ messages in thread
From: Florian Westphal @ 2013-12-04 11:31 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Eric Leblond, Florian Westphal, netfilter-devel
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > + while (jhash_initval == 0)
> > + jhash_initval = prandom_u32();
>
> Different initialization approach with regards to xt_NFQUEUE, any
> reason for that change?
I suggested this -- get_random_bytes is overkill for nfqueue
purposes.
In fact, I think xt_NFQUEUE should be switched to prandom interface
as well.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCHv2] netfilter: nft: add queue module
2013-12-04 11:31 ` Florian Westphal
@ 2013-12-04 11:39 ` Pablo Neira Ayuso
0 siblings, 0 replies; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-04 11:39 UTC (permalink / raw)
To: Florian Westphal; +Cc: Eric Leblond, netfilter-devel
On Wed, Dec 04, 2013 at 12:31:43PM +0100, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > + while (jhash_initval == 0)
> > > + jhash_initval = prandom_u32();
> >
> > Different initialization approach with regards to xt_NFQUEUE, any
> > reason for that change?
>
> I suggested this -- get_random_bytes is overkill for nfqueue
> purposes.
>
> In fact, I think xt_NFQUEUE should be switched to prandom interface
> as well.
I see. For consistency, it would be good to get a patch so both are in
sync.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCHv2] netfilter: nft: add queue module
2013-12-04 11:00 ` Pablo Neira Ayuso
2013-12-04 11:31 ` Florian Westphal
@ 2013-12-04 12:47 ` Eric Leblond
2013-12-05 17:09 ` Pablo Neira Ayuso
1 sibling, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-04 12:47 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel
Hi,
On Wed, 2013-12-04 at 12:00 +0100, Pablo Neira Ayuso wrote:
> Hi Eric,
>
> First off, thanks for this patch. Some comments below.
>
> On Sat, Nov 30, 2013 at 04:14:04PM +0100, Eric Leblond wrote:
> > This patch adds a new nft module named "nft_queue" which is a
> > nftables target sending packet to nfnetlink_queue subsystem. It has
> > the same level of functionnality as is iptables ancestor and share
> > some code with it.
> >
> > Signed-off-by: Eric Leblond <eric@regit.org>
> > ---
> > include/uapi/linux/netfilter/nf_tables.h | 20 ++++
...
> > +#include <linux/jhash.h>
> > +#include <linux/netfilter.h>
> > +#include <linux/netfilter/nf_tables.h>
> > +#include <net/netfilter/nf_tables.h>
> > +
> > +struct nft_queue {
> > + u16 queuenum;
> > + u16 queues_total;
> > + u16 flags;
> > + int family;
> ^
> This structure is very important that it doesn't have any hole (at its
> best) to reduce the size of the expression area in the rule. My
> proposal:
OK, fixing this.
> ...
> {
> u16 queue_num;
> u16 queue_total;
> u16 flags;
> u8 family;
> }
>
> > +};
> > +
> > +static u32 jhash_initval __read_mostly;
>
> From here:
>
> > +static u32 hash_v4(const struct sk_buff *skb)
> > +{
> > + const struct iphdr *iph = ip_hdr(skb);
> > +
> > + /* packets in either direction go into same queue */
> > + if ((__force u32)iph->saddr < (__force u32)iph->daddr)
> > + return jhash_3words((__force u32)iph->saddr,
> > + (__force u32)iph->daddr, iph->protocol, jhash_initval);
> > +
> > + return jhash_3words((__force u32)iph->daddr,
> > + (__force u32)iph->saddr, iph->protocol, jhash_initval);
> > +}
> > +
> > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> > +static u32 hash_v6(const struct sk_buff *skb)
> > +{
> > + const struct ipv6hdr *ip6h = ipv6_hdr(skb);
> > + u32 a, b, c;
> > +
> > + if ((__force u32)ip6h->saddr.s6_addr32[3] <
> > + (__force u32)ip6h->daddr.s6_addr32[3]) {
> > + a = (__force u32) ip6h->saddr.s6_addr32[3];
> > + b = (__force u32) ip6h->daddr.s6_addr32[3];
> > + } else {
> > + b = (__force u32) ip6h->saddr.s6_addr32[3];
> > + a = (__force u32) ip6h->daddr.s6_addr32[3];
> > + }
> > +
> > + if ((__force u32)ip6h->saddr.s6_addr32[1] <
> > + (__force u32)ip6h->daddr.s6_addr32[1])
> > + c = (__force u32) ip6h->saddr.s6_addr32[1];
> > + else
> > + c = (__force u32) ip6h->daddr.s6_addr32[1];
> > +
> > + return jhash_3words(a, b, c, jhash_initval);
> > +}
> > +#endif
> > +
> > +static u32
> > +nfqueue_hash(const struct nft_pktinfo *pkt, const struct nft_queue *priv)
> > +{
> > + u32 queue = priv->queuenum;
> > +
> > + if (priv->family == AF_INET)
> > + queue += ((u64) hash_v4(pkt->skb) * priv->queues_total) >> 32;
> > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> > + else if (priv->family == AF_INET6)
> > + queue += ((u64) hash_v6(pkt->skb) * priv->queues_total) >> 32;
> > +#endif
> > +
> > + return queue;
> > +}
>
> to there, it looks very similar to NFQUEUE. You can move these
> functions to net/netfilter/nf_queue.h. You'll have to inline them and
> add the jhash_initval parameter. You'll need an initial patch to
> prepare this change and adapt xt_NFQUEUE.c
I'm ok with the two hash functions but the nfqueue_hash the second
argument is different. Do you want me to introduce a new common
structure for xt_NFQUEUE and nft_queue ?
> > +
> > +static void nft_queue_eval(const struct nft_expr *expr,
> > + struct nft_data data[NFT_REG_MAX + 1],
> > + const struct nft_pktinfo *pkt)
> > +{
> > + struct nft_queue *priv = nft_expr_priv(expr);
...
> ret = NF_QUEUE_NR(queue);
> > + if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
> > + ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
> > +
> > + data[NFT_REG_VERDICT].verdict = ret;
> > +}
> > +
> > +static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
> > + [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
> > + [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
> > + [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
> ^------------^
> Comestic: I think one tab should be fine.
OK.
> > +};
> > +
> > +static int nft_queue_init(const struct nft_ctx *ctx,
> > + const struct nft_expr *expr,
..
> > +}
> > +
> > +static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
> > +{
> > + const struct nft_queue *priv = nft_expr_priv(expr);
> > +
> > + if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)))
> > + goto nla_put_failure;
> > +
> > + if (nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)))
> > + goto nla_put_failure;
> > +
> > + if (nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
> > + goto nla_put_failure;
>
> Comestic: Perhaps you can squash these three put lines in one single
> if to save a couple of lines, the code will be still quite readable.
Done.
BR
--
Eric Leblond <eric@regit.org>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCHv2] netfilter: nft: add queue module
2013-12-04 12:47 ` Eric Leblond
@ 2013-12-05 17:09 ` Pablo Neira Ayuso
2013-12-05 21:31 ` [PATCHv3 0/3] add nft_queue module Eric Leblond
0 siblings, 1 reply; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-05 17:09 UTC (permalink / raw)
To: Eric Leblond; +Cc: Florian Westphal, netfilter-devel
Hi Eric,
On Wed, Dec 04, 2013 at 01:47:43PM +0100, Eric Leblond wrote:
[...]
> > > +static u32
> > > +nfqueue_hash(const struct nft_pktinfo *pkt, const struct nft_queue *priv)
> > > +{
> > > + u32 queue = priv->queuenum;
> > > +
> > > + if (priv->family == AF_INET)
> > > + queue += ((u64) hash_v4(pkt->skb) * priv->queues_total) >> 32;
> > > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> > > + else if (priv->family == AF_INET6)
> > > + queue += ((u64) hash_v6(pkt->skb) * priv->queues_total) >> 32;
> > > +#endif
> > > +
> > > + return queue;
> > > +}
> >
> > to there, it looks very similar to NFQUEUE. You can move these
> > functions to net/netfilter/nf_queue.h. You'll have to inline them and
> > add the jhash_initval parameter. You'll need an initial patch to
> > prepare this change and adapt xt_NFQUEUE.c
>
> I'm ok with the two hash functions but the nfqueue_hash the second
> argument is different. Do you want me to introduce a new common
> structure for xt_NFQUEUE and nft_queue ?
My suggestion is to add something like:
static inline u32 nfqueue_hash(const struct sk_buff *skb, u16 queuenum,
u16 queues_total, u8 family)
that can be used by both, it will also be defined in
net/netfilter/nf_queue.h
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv3 0/3] add nft_queue module
2013-12-05 17:09 ` Pablo Neira Ayuso
@ 2013-12-05 21:31 ` Eric Leblond
2013-12-05 21:31 ` [PATCHv3 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
` (2 more replies)
0 siblings, 3 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 21:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw
Hello,
This patch is a rework of previous patchset which fix comments
sent by Pablo. Code commons to xf_NFQUEUE and nft_queue has been
put in a common header. Other minor points have been fixed to.
BR,
--
Eric
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv3 1/3] netfilter: nft: fix issue with verdict support
2013-12-05 21:31 ` [PATCHv3 0/3] add nft_queue module Eric Leblond
@ 2013-12-05 21:31 ` Eric Leblond
2013-12-05 21:31 ` [PATCHv3 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
2013-12-05 21:31 ` [PATCHv3 3/3] netfilter: nft: add queue module Eric Leblond
2 siblings, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 21:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
The test on verdict was simply done on the value of the verdict
which is not correct as far as queue is concern. In fact, the test
of verdict test must be done with respect to the verdict mask for
verdicts which are not internal to nftables.
Signed-off-by: Eric Leblond <eric@regit.org>
---
net/netfilter/nf_tables_core.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index cb9e685..e8fcc34 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -164,7 +164,7 @@ next_rule:
break;
}
- switch (data[NFT_REG_VERDICT].verdict) {
+ switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule:
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
return data[NFT_REG_VERDICT].verdict;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict) {
case NFT_JUMP:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCHv3 2/3] netfilter: xt_NFQUEUE: separate reusable code
2013-12-05 21:31 ` [PATCHv3 0/3] add nft_queue module Eric Leblond
2013-12-05 21:31 ` [PATCHv3 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
@ 2013-12-05 21:31 ` Eric Leblond
2013-12-05 21:41 ` Pablo Neira Ayuso
2013-12-05 21:31 ` [PATCHv3 3/3] netfilter: nft: add queue module Eric Leblond
2 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 21:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
This patch prepares the adding of nft_queue module by putting
reusable code into a header file.
Signed-off-by: Eric Leblond <eric@regit.org>
---
net/netfilter/nf_queue.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++
net/netfilter/xt_NFQUEUE.c | 75 +++++---------------------------------------
2 files changed, 85 insertions(+), 67 deletions(-)
create mode 100644 net/netfilter/nf_queue.h
diff --git a/net/netfilter/nf_queue.h b/net/netfilter/nf_queue.h
new file mode 100644
index 0000000..c8225a1
--- /dev/null
+++ b/net/netfilter/nf_queue.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * (C) 2013 by Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _NF_QUEUE_H
+#define _NF_QUEUE_H
+
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
+static u32 jhash_initval __read_mostly;
+
+static inline void init_hashrandom(void)
+{
+ while (jhash_initval == 0)
+ jhash_initval = prandom_u32();
+}
+
+static inline u32 hash_v4(const struct sk_buff *skb)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+
+ /* packets in either direction go into same queue */
+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+ return jhash_3words((__force u32)iph->saddr,
+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+ return jhash_3words((__force u32)iph->daddr,
+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static inline u32 hash_v6(const struct sk_buff *skb)
+{
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ u32 a, b, c;
+
+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
+ (__force u32)ip6h->daddr.s6_addr32[3]) {
+ a = (__force u32) ip6h->saddr.s6_addr32[3];
+ b = (__force u32) ip6h->daddr.s6_addr32[3];
+ } else {
+ b = (__force u32) ip6h->saddr.s6_addr32[3];
+ a = (__force u32) ip6h->daddr.s6_addr32[3];
+ }
+
+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
+ (__force u32)ip6h->daddr.s6_addr32[1])
+ c = (__force u32) ip6h->saddr.s6_addr32[1];
+ else
+ c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+ return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static inline u32
+nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family)
+{
+ if (family == NFPROTO_IPV4)
+ queue += ((u64) hash_v4(skb) * queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+ else if (family == NFPROTO_IPV6)
+ queue += ((u64) hash_v6(skb) * queues_total) >> 32;
+#endif
+
+ return queue;
+}
+
+#endif /* _NF_QUEUE_H */
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index ed00fef..81da4ab 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -11,15 +11,13 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/jhash.h>
-
#include <linux/netfilter.h>
#include <linux/netfilter_arp.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFQUEUE.h>
+#include "nf_queue.h"
+
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
MODULE_LICENSE("GPL");
@@ -27,9 +25,6 @@ MODULE_ALIAS("ipt_NFQUEUE");
MODULE_ALIAS("ip6t_NFQUEUE");
MODULE_ALIAS("arpt_NFQUEUE");
-static u32 jhash_initval __read_mostly;
-static bool rnd_inited __read_mostly;
-
static unsigned int
nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
@@ -38,60 +33,6 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
return NF_QUEUE_NR(tinfo->queuenum);
}
-static u32 hash_v4(const struct sk_buff *skb)
-{
- const struct iphdr *iph = ip_hdr(skb);
-
- /* packets in either direction go into same queue */
- if ((__force u32)iph->saddr < (__force u32)iph->daddr)
- return jhash_3words((__force u32)iph->saddr,
- (__force u32)iph->daddr, iph->protocol, jhash_initval);
-
- return jhash_3words((__force u32)iph->daddr,
- (__force u32)iph->saddr, iph->protocol, jhash_initval);
-}
-
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-static u32 hash_v6(const struct sk_buff *skb)
-{
- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
- u32 a, b, c;
-
- if ((__force u32)ip6h->saddr.s6_addr32[3] <
- (__force u32)ip6h->daddr.s6_addr32[3]) {
- a = (__force u32) ip6h->saddr.s6_addr32[3];
- b = (__force u32) ip6h->daddr.s6_addr32[3];
- } else {
- b = (__force u32) ip6h->saddr.s6_addr32[3];
- a = (__force u32) ip6h->daddr.s6_addr32[3];
- }
-
- if ((__force u32)ip6h->saddr.s6_addr32[1] <
- (__force u32)ip6h->daddr.s6_addr32[1])
- c = (__force u32) ip6h->saddr.s6_addr32[1];
- else
- c = (__force u32) ip6h->daddr.s6_addr32[1];
-
- return jhash_3words(a, b, c, jhash_initval);
-}
-#endif
-
-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;
-
- if (par->family == NFPROTO_IPV4)
- queue += ((u64) hash_v4(skb) * info->queues_total) >> 32;
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
- else if (par->family == NFPROTO_IPV6)
- queue += ((u64) hash_v6(skb) * info->queues_total) >> 32;
-#endif
-
- return queue;
-}
-
static unsigned int
nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
@@ -99,7 +40,8 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
u32 queue = info->queuenum;
if (info->queues_total > 1)
- queue = nfqueue_hash(skb, par);
+ queue = nfqueue_hash(skb, queue,
+ info->queues_total, par->family);
return NF_QUEUE_NR(queue);
}
@@ -120,10 +62,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)
const struct xt_NFQ_info_v3 *info = par->targinfo;
u32 maxid;
- if (unlikely(!rnd_inited)) {
- get_random_bytes(&jhash_initval, sizeof(jhash_initval));
- rnd_inited = true;
- }
+ init_hashrandom();
+
if (info->queues_total == 0) {
pr_err("NFQUEUE: number of total queues is 0\n");
return -EINVAL;
@@ -155,7 +95,8 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
queue = info->queuenum + cpu % info->queues_total;
} else
- queue = nfqueue_hash(skb, par);
+ queue = nfqueue_hash(skb, queue,
+ info->queues_total, par->family);
}
ret = NF_QUEUE_NR(queue);
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCHv3 2/3] netfilter: xt_NFQUEUE: separate reusable code
2013-12-05 21:31 ` [PATCHv3 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
@ 2013-12-05 21:41 ` Pablo Neira Ayuso
2013-12-05 23:24 ` [PATCHv4 0/3] add nft_queue module Eric Leblond
0 siblings, 1 reply; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-05 21:41 UTC (permalink / raw)
To: Eric Leblond; +Cc: netfilter-devel, fw
On Thu, Dec 05, 2013 at 10:31:27PM +0100, Eric Leblond wrote:
> This patch prepares the adding of nft_queue module by putting
> reusable code into a header file.
>
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> net/netfilter/nf_queue.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++
> net/netfilter/xt_NFQUEUE.c | 75 +++++---------------------------------------
> 2 files changed, 85 insertions(+), 67 deletions(-)
> create mode 100644 net/netfilter/nf_queue.h
>
> diff --git a/net/netfilter/nf_queue.h b/net/netfilter/nf_queue.h
> new file mode 100644
> index 0000000..c8225a1
> --- /dev/null
> +++ b/net/netfilter/nf_queue.h
Ops, sorry I meant to point to the existing include/net/netfilter/nf_queue.h
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv4 0/3] add nft_queue module
2013-12-05 21:41 ` Pablo Neira Ayuso
@ 2013-12-05 23:24 ` Eric Leblond
2013-12-05 23:24 ` [PATCHv4 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
` (3 more replies)
0 siblings, 4 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 23:24 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw
Hello,
OK, here's a new version not adding a useless file when putting
reusable code in a header.
Sorry for missing that.
BR,
--
Eric
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv4 1/3] netfilter: nft: fix issue with verdict support
2013-12-05 23:24 ` [PATCHv4 0/3] add nft_queue module Eric Leblond
@ 2013-12-05 23:24 ` Eric Leblond
2013-12-05 23:24 ` [PATCHv4 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
` (2 subsequent siblings)
3 siblings, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 23:24 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
The test on verdict was simply done on the value of the verdict
which is not correct as far as queue is concern. In fact, the test
of verdict test must be done with respect to the verdict mask for
verdicts which are not internal to nftables.
Signed-off-by: Eric Leblond <eric@regit.org>
---
net/netfilter/nf_tables_core.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index cb9e685..e8fcc34 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -164,7 +164,7 @@ next_rule:
break;
}
- switch (data[NFT_REG_VERDICT].verdict) {
+ switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule:
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
return data[NFT_REG_VERDICT].verdict;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict) {
case NFT_JUMP:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCHv4 2/3] netfilter: xt_NFQUEUE: separate reusable code
2013-12-05 23:24 ` [PATCHv4 0/3] add nft_queue module Eric Leblond
2013-12-05 23:24 ` [PATCHv4 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
@ 2013-12-05 23:24 ` Eric Leblond
2013-12-07 22:56 ` Pablo Neira Ayuso
2013-12-05 23:24 ` [PATCHv4 3/3] netfilter: nft: add queue module Eric Leblond
2013-12-07 22:57 ` [PATCHv4 0/3] add nft_queue module Pablo Neira Ayuso
3 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 23:24 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
This patch prepares the adding of nft_queue module by putting
reusable code into a header file.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/net/netfilter/nf_queue.h | 63 +++++++++++++++++++++++++++++++++
net/netfilter/xt_NFQUEUE.c | 75 +++++-----------------------------------
2 files changed, 71 insertions(+), 67 deletions(-)
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index c1d5b3e..0a71ab0 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -1,6 +1,10 @@
#ifndef _NF_QUEUE_H
#define _NF_QUEUE_H
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
/* Each queued (to userspace) skbuff has one of these. */
struct nf_queue_entry {
struct list_head list;
@@ -33,4 +37,63 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
+static u32 jhash_initval __read_mostly;
+
+static inline void init_hashrandom(void)
+{
+ while (jhash_initval == 0)
+ jhash_initval = prandom_u32();
+}
+
+static inline u32 hash_v4(const struct sk_buff *skb)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+
+ /* packets in either direction go into same queue */
+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+ return jhash_3words((__force u32)iph->saddr,
+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+ return jhash_3words((__force u32)iph->daddr,
+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static inline u32 hash_v6(const struct sk_buff *skb)
+{
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ u32 a, b, c;
+
+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
+ (__force u32)ip6h->daddr.s6_addr32[3]) {
+ a = (__force u32) ip6h->saddr.s6_addr32[3];
+ b = (__force u32) ip6h->daddr.s6_addr32[3];
+ } else {
+ b = (__force u32) ip6h->saddr.s6_addr32[3];
+ a = (__force u32) ip6h->daddr.s6_addr32[3];
+ }
+
+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
+ (__force u32)ip6h->daddr.s6_addr32[1])
+ c = (__force u32) ip6h->saddr.s6_addr32[1];
+ else
+ c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+ return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static inline u32
+nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family)
+{
+ if (family == NFPROTO_IPV4)
+ queue += ((u64) hash_v4(skb) * queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+ else if (family == NFPROTO_IPV6)
+ queue += ((u64) hash_v6(skb) * queues_total) >> 32;
+#endif
+
+ return queue;
+}
+
#endif /* _NF_QUEUE_H */
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index ed00fef..20098f8 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -11,15 +11,13 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/jhash.h>
-
#include <linux/netfilter.h>
#include <linux/netfilter_arp.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFQUEUE.h>
+#include <net/netfilter/nf_queue.h>
+
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
MODULE_LICENSE("GPL");
@@ -27,9 +25,6 @@ MODULE_ALIAS("ipt_NFQUEUE");
MODULE_ALIAS("ip6t_NFQUEUE");
MODULE_ALIAS("arpt_NFQUEUE");
-static u32 jhash_initval __read_mostly;
-static bool rnd_inited __read_mostly;
-
static unsigned int
nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
@@ -38,60 +33,6 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
return NF_QUEUE_NR(tinfo->queuenum);
}
-static u32 hash_v4(const struct sk_buff *skb)
-{
- const struct iphdr *iph = ip_hdr(skb);
-
- /* packets in either direction go into same queue */
- if ((__force u32)iph->saddr < (__force u32)iph->daddr)
- return jhash_3words((__force u32)iph->saddr,
- (__force u32)iph->daddr, iph->protocol, jhash_initval);
-
- return jhash_3words((__force u32)iph->daddr,
- (__force u32)iph->saddr, iph->protocol, jhash_initval);
-}
-
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-static u32 hash_v6(const struct sk_buff *skb)
-{
- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
- u32 a, b, c;
-
- if ((__force u32)ip6h->saddr.s6_addr32[3] <
- (__force u32)ip6h->daddr.s6_addr32[3]) {
- a = (__force u32) ip6h->saddr.s6_addr32[3];
- b = (__force u32) ip6h->daddr.s6_addr32[3];
- } else {
- b = (__force u32) ip6h->saddr.s6_addr32[3];
- a = (__force u32) ip6h->daddr.s6_addr32[3];
- }
-
- if ((__force u32)ip6h->saddr.s6_addr32[1] <
- (__force u32)ip6h->daddr.s6_addr32[1])
- c = (__force u32) ip6h->saddr.s6_addr32[1];
- else
- c = (__force u32) ip6h->daddr.s6_addr32[1];
-
- return jhash_3words(a, b, c, jhash_initval);
-}
-#endif
-
-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;
-
- if (par->family == NFPROTO_IPV4)
- queue += ((u64) hash_v4(skb) * info->queues_total) >> 32;
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
- else if (par->family == NFPROTO_IPV6)
- queue += ((u64) hash_v6(skb) * info->queues_total) >> 32;
-#endif
-
- return queue;
-}
-
static unsigned int
nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
@@ -99,7 +40,8 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
u32 queue = info->queuenum;
if (info->queues_total > 1)
- queue = nfqueue_hash(skb, par);
+ queue = nfqueue_hash(skb, queue,
+ info->queues_total, par->family);
return NF_QUEUE_NR(queue);
}
@@ -120,10 +62,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)
const struct xt_NFQ_info_v3 *info = par->targinfo;
u32 maxid;
- if (unlikely(!rnd_inited)) {
- get_random_bytes(&jhash_initval, sizeof(jhash_initval));
- rnd_inited = true;
- }
+ init_hashrandom();
+
if (info->queues_total == 0) {
pr_err("NFQUEUE: number of total queues is 0\n");
return -EINVAL;
@@ -155,7 +95,8 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
queue = info->queuenum + cpu % info->queues_total;
} else
- queue = nfqueue_hash(skb, par);
+ queue = nfqueue_hash(skb, queue,
+ info->queues_total, par->family);
}
ret = NF_QUEUE_NR(queue);
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCHv4 2/3] netfilter: xt_NFQUEUE: separate reusable code
2013-12-05 23:24 ` [PATCHv4 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
@ 2013-12-07 22:56 ` Pablo Neira Ayuso
0 siblings, 0 replies; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-07 22:56 UTC (permalink / raw)
To: Eric Leblond; +Cc: netfilter-devel, fw
On Fri, Dec 06, 2013 at 12:24:12AM +0100, Eric Leblond wrote:
> This patch prepares the adding of nft_queue module by putting
> reusable code into a header file.
>
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> include/net/netfilter/nf_queue.h | 63 +++++++++++++++++++++++++++++++++
> net/netfilter/xt_NFQUEUE.c | 75 +++++-----------------------------------
> 2 files changed, 71 insertions(+), 67 deletions(-)
>
> diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
> index c1d5b3e..0a71ab0 100644
> --- a/include/net/netfilter/nf_queue.h
> +++ b/include/net/netfilter/nf_queue.h
This header file is also used by net/netfilter/nfnetlink_queue_core,
then...
> @@ -1,6 +1,10 @@
> #ifndef _NF_QUEUE_H
> #define _NF_QUEUE_H
>
> +#include <linux/ip.h>
> +#include <linux/ipv6.h>
> +#include <linux/jhash.h>
> +
> /* Each queued (to userspace) skbuff has one of these. */
> struct nf_queue_entry {
> struct list_head list;
> @@ -33,4 +37,63 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
> bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
> void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
>
> +static u32 jhash_initval __read_mostly;
This variable will be also reserved in that module as well. I have
fixed this by adding a jhash_initval parameter to init_hashrandom,
hash_v4, hash_v6 and nfqueue_hash.
Please, no need to send a new patchset, check my nftables tree and
tell if you find any issue, otherwise I'll pull these changes to
nf-next. Thanks.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv4 3/3] netfilter: nft: add queue module
2013-12-05 23:24 ` [PATCHv4 0/3] add nft_queue module Eric Leblond
2013-12-05 23:24 ` [PATCHv4 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
2013-12-05 23:24 ` [PATCHv4 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
@ 2013-12-05 23:24 ` Eric Leblond
2013-12-07 22:57 ` [PATCHv4 0/3] add nft_queue module Pablo Neira Ayuso
3 siblings, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 23:24 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
This patch adds a new nft module named "nft_queue" which is a
nftables target sending packet to nfnetlink_queue subsystem. It has
the same level of functionnality as is iptables ancestor and share
some code with it.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/uapi/linux/netfilter/nf_tables.h | 20 +++++
net/netfilter/Kconfig | 9 +++
net/netfilter/Makefile | 1 +
net/netfilter/nft_queue.c | 134 +++++++++++++++++++++++++++++++
4 files changed, 164 insertions(+)
create mode 100644 net/netfilter/nft_queue.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index fbfd229..256d36b 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -658,6 +658,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c3398cd..cf0872d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -456,6 +456,15 @@ config NFT_NAT
depends on NF_NAT
tristate "Netfilter nf_tables nat module"
+config NFT_QUEUE
+ depends on NF_TABLES
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_NETLINK_QUEUE
+ tristate "Netfilter nf_tables queue module"
+ help
+ This is required if you intend to use nfnetlink queue
+ on more than the default queue 0 or with the other features
+
config NFT_COMPAT
depends on NF_TABLES
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 394483b..e763746 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
obj-$(CONFIG_NFT_CT) += nft_ct.o
obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
obj-$(CONFIG_NFT_NAT) += nft_nat.o
+obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
#nf_tables-objs += nft_meta_target.o
obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
obj-$(CONFIG_NFT_HASH) += nft_hash.o
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644
index 0000000..56a88f4
--- /dev/null
+++ b/net/netfilter/nft_queue.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Development of this code partly funded by OISF
+ * (http://www.openinfosecfoundation.org/)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+
+#include <linux/jhash.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+#include <net/netfilter/nf_queue.h>
+
+struct nft_queue {
+ u16 queuenum;
+ u16 queues_total;
+ u16 flags;
+ u8 family;
+};
+
+static void nft_queue_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1],
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+ u32 queue = priv->queuenum;
+ u32 ret;
+
+ if (priv->queues_total > 1) {
+ if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ int cpu = smp_processor_id();
+
+ queue = priv->queuenum + cpu % priv->queues_total;
+ } else
+ queue = nfqueue_hash(pkt->skb, queue,
+ priv->queues_total, priv->family);
+ }
+
+ ret = NF_QUEUE_NR(queue);
+ if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
+ ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+ data[NFT_REG_VERDICT].verdict = ret;
+}
+
+static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+ [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
+ [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
+ [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
+};
+
+static int nft_queue_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+
+ init_hashrandom();
+
+ priv->family = ctx->afi->family;
+
+ if (tb[NFTA_QUEUE_NUM] == NULL)
+ return -EINVAL;
+ priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
+
+ if (tb[NFTA_QUEUE_TOTAL] != NULL)
+ priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
+ if (tb[NFTA_QUEUE_FLAGS] != NULL) {
+ priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
+ if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_queue *priv = nft_expr_priv(expr);
+
+ if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)) ||
+ nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)) ||
+ nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_queue_type;
+static const struct nft_expr_ops nft_queue_ops = {
+ .type = &nft_queue_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
+ .eval = nft_queue_eval,
+ .init = nft_queue_init,
+ .dump = nft_queue_dump,
+};
+
+static struct nft_expr_type nft_queue_type __read_mostly = {
+ .name = "queue",
+ .ops = &nft_queue_ops,
+ .policy = nft_queue_policy,
+ .maxattr = NFTA_QUEUE_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_queue_module_init(void)
+{
+ return nft_register_expr(&nft_queue_type);
+}
+
+static void __exit nft_queue_module_exit(void)
+{
+ nft_unregister_expr(&nft_queue_type);
+}
+
+module_init(nft_queue_module_init);
+module_exit(nft_queue_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
+MODULE_ALIAS_NFT_EXPR("queue");
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCHv4 0/3] add nft_queue module
2013-12-05 23:24 ` [PATCHv4 0/3] add nft_queue module Eric Leblond
` (2 preceding siblings ...)
2013-12-05 23:24 ` [PATCHv4 3/3] netfilter: nft: add queue module Eric Leblond
@ 2013-12-07 22:57 ` Pablo Neira Ayuso
2013-12-10 10:09 ` Eric Leblond
3 siblings, 1 reply; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-07 22:57 UTC (permalink / raw)
To: Eric Leblond; +Cc: netfilter-devel, fw
On Fri, Dec 06, 2013 at 12:24:10AM +0100, Eric Leblond wrote:
>
> Hello,
>
> OK, here's a new version not adding a useless file when putting
> reusable code in a header.
Applied with changes, please check:
http://git.kernel.org/cgit/linux/kernel/git/pablo/nftables.git
and let me know if you have any concern with my changes. Thanks.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCHv4 0/3] add nft_queue module
2013-12-07 22:57 ` [PATCHv4 0/3] add nft_queue module Pablo Neira Ayuso
@ 2013-12-10 10:09 ` Eric Leblond
0 siblings, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-10 10:09 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, fw
Hello,
On Sat, 2013-12-07 at 23:57 +0100, Pablo Neira Ayuso wrote:
> On Fri, Dec 06, 2013 at 12:24:10AM +0100, Eric Leblond wrote:
> >
> > Hello,
> >
> > OK, here's a new version not adding a useless file when putting
> > reusable code in a header.
>
> Applied with changes, please check:
>
> http://git.kernel.org/cgit/linux/kernel/git/pablo/nftables.git
>
> and let me know if you have any concern with my changes. Thanks.
Good for me. Thanks a lot for the review and fixes.
BR,
--
Eric Leblond <eric@regit.org>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHv3 3/3] netfilter: nft: add queue module
2013-12-05 21:31 ` [PATCHv3 0/3] add nft_queue module Eric Leblond
2013-12-05 21:31 ` [PATCHv3 1/3] netfilter: nft: fix issue with verdict support Eric Leblond
2013-12-05 21:31 ` [PATCHv3 2/3] netfilter: xt_NFQUEUE: separate reusable code Eric Leblond
@ 2013-12-05 21:31 ` Eric Leblond
2 siblings, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-12-05 21:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, fw, Eric Leblond
This patch adds a new nft module named "nft_queue" which is a
nftables target sending packet to nfnetlink_queue subsystem. It has
the same level of functionnality as is iptables ancestor and share
some code with it.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/uapi/linux/netfilter/nf_tables.h | 20 +++++
net/netfilter/Kconfig | 9 +++
net/netfilter/Makefile | 1 +
net/netfilter/nft_queue.c | 134 +++++++++++++++++++++++++++++++
4 files changed, 164 insertions(+)
create mode 100644 net/netfilter/nft_queue.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index fbfd229..256d36b 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -658,6 +658,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c3398cd..cf0872d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -456,6 +456,15 @@ config NFT_NAT
depends on NF_NAT
tristate "Netfilter nf_tables nat module"
+config NFT_QUEUE
+ depends on NF_TABLES
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_NETLINK_QUEUE
+ tristate "Netfilter nf_tables queue module"
+ help
+ This is required if you intend to use nfnetlink queue
+ on more than the default queue 0 or with the other features
+
config NFT_COMPAT
depends on NF_TABLES
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 394483b..e763746 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
obj-$(CONFIG_NFT_CT) += nft_ct.o
obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
obj-$(CONFIG_NFT_NAT) += nft_nat.o
+obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
#nf_tables-objs += nft_meta_target.o
obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
obj-$(CONFIG_NFT_HASH) += nft_hash.o
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644
index 0000000..416a765
--- /dev/null
+++ b/net/netfilter/nft_queue.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Development of this code partly funded by OISF
+ * (http://www.openinfosecfoundation.org/)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+
+#include <linux/jhash.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+#include "nf_queue.h"
+
+struct nft_queue {
+ u16 queuenum;
+ u16 queues_total;
+ u16 flags;
+ u8 family;
+};
+
+static void nft_queue_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1],
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+ u32 queue = priv->queuenum;
+ u32 ret;
+
+ if (priv->queues_total > 1) {
+ if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ int cpu = smp_processor_id();
+
+ queue = priv->queuenum + cpu % priv->queues_total;
+ } else
+ queue = nfqueue_hash(pkt->skb, queue,
+ priv->queues_total, priv->family);
+ }
+
+ ret = NF_QUEUE_NR(queue);
+ if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
+ ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+ data[NFT_REG_VERDICT].verdict = ret;
+}
+
+static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+ [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
+ [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
+ [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
+};
+
+static int nft_queue_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_queue *priv = nft_expr_priv(expr);
+
+ init_hashrandom();
+
+ priv->family = ctx->afi->family;
+
+ if (tb[NFTA_QUEUE_NUM] == NULL)
+ return -EINVAL;
+ priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
+
+ if (tb[NFTA_QUEUE_TOTAL] != NULL)
+ priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
+ if (tb[NFTA_QUEUE_FLAGS] != NULL) {
+ priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
+ if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_queue *priv = nft_expr_priv(expr);
+
+ if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)) ||
+ nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)) ||
+ nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_queue_type;
+static const struct nft_expr_ops nft_queue_ops = {
+ .type = &nft_queue_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
+ .eval = nft_queue_eval,
+ .init = nft_queue_init,
+ .dump = nft_queue_dump,
+};
+
+static struct nft_expr_type nft_queue_type __read_mostly = {
+ .name = "queue",
+ .ops = &nft_queue_ops,
+ .policy = nft_queue_policy,
+ .maxattr = NFTA_QUEUE_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_queue_module_init(void)
+{
+ return nft_register_expr(&nft_queue_type);
+}
+
+static void __exit nft_queue_module_exit(void)
+{
+ nft_unregister_expr(&nft_queue_type);
+}
+
+module_init(nft_queue_module_init);
+module_exit(nft_queue_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
+MODULE_ALIAS_NFT_EXPR("queue");
--
1.8.5
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 2/2] netfilter: nft: add queue module
2013-11-30 10:56 ` [PATCH 2/2] netfilter: nft: add queue module Eric Leblond
2013-11-30 12:26 ` Florian Westphal
@ 2013-12-02 6:39 ` Tomasz Bursztyka
2013-12-02 9:32 ` Eric Leblond
1 sibling, 1 reply; 32+ messages in thread
From: Tomasz Bursztyka @ 2013-12-02 6:39 UTC (permalink / raw)
To: Eric Leblond, pablo; +Cc: netfilter-devel
Hi Eric,
> +
> +#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
> +#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
> +#define NFT_QUEUE_FLAG_MASK 0x03
Why not declaring them in an enum, as for nft_rule_compat_flags,
nft_set_flags or nft_set_elem_flags?
Tomasz
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/2] netfilter: nft: add queue module
2013-12-02 6:39 ` [PATCH 2/2] " Tomasz Bursztyka
@ 2013-12-02 9:32 ` Eric Leblond
2013-12-02 11:03 ` Tomasz Bursztyka
0 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-02 9:32 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: pablo, netfilter-devel
Hello,
On Mon, 2013-12-02 at 08:39 +0200, Tomasz Bursztyka wrote:
> Hi Eric,
>
> > +
> > +#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
> > +#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
> > +#define NFT_QUEUE_FLAG_MASK 0x03
>
> Why not declaring them in an enum, as for nft_rule_compat_flags,
> nft_set_flags or nft_set_elem_flags?
Simple answer: It was not an enum in the original NFQUEUE code ;)
Real answer: We have only two values, third one is a mask. So it may be
a bit overkill to use an enum here.
BR,
--
Eric Leblond <eric@regit.org>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 2/2] netfilter: nft: add queue module
2013-12-02 9:32 ` Eric Leblond
@ 2013-12-02 11:03 ` Tomasz Bursztyka
0 siblings, 0 replies; 32+ messages in thread
From: Tomasz Bursztyka @ 2013-12-02 11:03 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
Hi Eric,
>> Why not declaring them in an enum, as for nft_rule_compat_flags,
>> >nft_set_flags or nft_set_elem_flags?
> Simple answer: It was not an enum in the original NFQUEUE code;)
>
> Real answer: We have only two values, third one is a mask. So it may be
> a bit overkill to use an enum here.
I understand, but this would be diverging from what has been the "rule"
so far.
It's a minor detail I agree.
Btw, nft_set_elem_flags owns only one value ^^
Tomasz
^ permalink raw reply [flat|nested] 32+ messages in thread
* [libnftables PATCH 1/2] expr: add support for nfnetlink queue
2013-11-30 10:52 [nft PATCH] add support for queue target Eric Leblond
2013-11-30 10:56 ` [PATCH 1/2] netfilter: nft: fix issue with verdict support Eric Leblond
@ 2013-11-30 10:57 ` Eric Leblond
2013-11-30 10:57 ` [libnftables PATCH 2/2] test: add tests for expr queue Eric Leblond
2013-12-10 10:03 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Pablo Neira Ayuso
2013-11-30 10:57 ` [nft PATCH] Add support for queue target Eric Leblond
2 siblings, 2 replies; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 10:57 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
This patch adds a support of the queue target.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/libnftables/expr.h | 5 +
include/linux/netfilter/nf_tables.h | 20 +++
src/Makefile.am | 1 +
src/expr/queue.c | 254 ++++++++++++++++++++++++++++++++++++
4 files changed, 280 insertions(+)
create mode 100644 src/expr/queue.c
diff --git a/include/libnftables/expr.h b/include/libnftables/expr.h
index 54de186..d292773 100644
--- a/include/libnftables/expr.h
+++ b/include/libnftables/expr.h
@@ -143,6 +143,11 @@ enum {
NFT_EXPR_REJECT_CODE,
};
+enum {
+ NFT_EXPR_QUEUE_NUM = NFT_RULE_EXPR_ATTR_BASE,
+ NFT_EXPR_QUEUE_TOTAL,
+ NFT_EXPR_QUEUE_FLAGS,
+};
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 4ec8187..b58990e 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -580,6 +580,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/src/Makefile.am b/src/Makefile.am
index 83ab658..441e96e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,7 @@ libnftables_la_SOURCES = utils.c \
expr/meta.c \
expr/nat.c \
expr/payload.c \
+ expr/queue.c \
expr/reject.c \
expr/target.c \
expr/data_reg.h \
diff --git a/src/expr/queue.c b/src/expr/queue.c
new file mode 100644
index 0000000..4c1c8a7
--- /dev/null
+++ b/src/expr/queue.c
@@ -0,0 +1,254 @@
+/*
+ * (C) 2013 by Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include "internal.h"
+#include <libmnl/libmnl.h>
+#include <libnftables/expr.h>
+#include <libnftables/rule.h>
+#include "expr_ops.h"
+
+struct nft_expr_queue {
+ uint16_t queuenum;
+ uint16_t queues_total;
+ uint16_t flags;
+};
+
+static int nft_rule_expr_queue_set(struct nft_rule_expr *e, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ struct nft_expr_queue *queue = nft_expr_data(e);
+
+ switch(type) {
+ case NFT_EXPR_QUEUE_NUM:
+ queue->queuenum = *((uint16_t *)data);
+ break;
+ case NFT_EXPR_QUEUE_TOTAL:
+ queue->queues_total = *((uint16_t *)data);
+ break;
+ case NFT_EXPR_QUEUE_FLAGS:
+ queue->flags = *((uint16_t *)data);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static const void *
+nft_rule_expr_queue_get(const struct nft_rule_expr *e, uint16_t type,
+ uint32_t *data_len)
+{
+ struct nft_expr_queue *queue = nft_expr_data(e);
+
+ switch(type) {
+ case NFT_EXPR_QUEUE_NUM:
+ *data_len = sizeof(queue->queuenum);
+ return &queue->queuenum;
+ case NFT_EXPR_QUEUE_TOTAL:
+ *data_len = sizeof(queue->queues_total);
+ return &queue->queues_total;
+ case NFT_EXPR_QUEUE_FLAGS:
+ *data_len = sizeof(queue->flags);
+ return &queue->flags;
+ }
+ return NULL;
+}
+
+static int nft_rule_expr_queue_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, NFTA_QUEUE_MAX) < 0)
+ return MNL_CB_OK;
+
+ switch(type) {
+ case NFTA_QUEUE_NUM:
+ case NFTA_QUEUE_TOTAL:
+ case NFTA_QUEUE_FLAGS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
+ perror("mnl_attr_validate");
+ return MNL_CB_ERROR;
+ }
+ break;
+ }
+
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static void
+nft_rule_expr_queue_build(struct nlmsghdr *nlh, struct nft_rule_expr *e)
+{
+ struct nft_expr_queue *queue = nft_expr_data(e);
+
+ if (e->flags & (1 << NFT_EXPR_QUEUE_NUM))
+ mnl_attr_put_u16(nlh, NFTA_QUEUE_NUM, htons(queue->queuenum));
+ if (e->flags & (1 << NFT_EXPR_QUEUE_TOTAL))
+ mnl_attr_put_u16(nlh, NFTA_QUEUE_TOTAL, htons(queue->queues_total));
+ if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS))
+ mnl_attr_put_u16(nlh, NFTA_QUEUE_FLAGS, htons(queue->flags));
+}
+
+static int
+nft_rule_expr_queue_parse(struct nft_rule_expr *e, struct nlattr *attr)
+{
+ struct nft_expr_queue *queue = nft_expr_data(e);
+ struct nlattr *tb[NFTA_QUEUE_MAX+1] = {};
+
+ if (mnl_attr_parse_nested(attr, nft_rule_expr_queue_cb, tb) < 0)
+ return -1;
+
+ if (tb[NFTA_QUEUE_NUM]) {
+ queue->queuenum = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_NUM]));
+ e->flags |= (1 << NFT_EXPR_QUEUE_NUM);
+ }
+ if (tb[NFTA_QUEUE_TOTAL]) {
+ queue->queues_total = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_TOTAL]));
+ e->flags |= (1 << NFT_EXPR_QUEUE_TOTAL);
+ }
+ if (tb[NFTA_QUEUE_FLAGS]) {
+ queue->flags = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_FLAGS]));
+ e->flags |= (1 << NFT_EXPR_QUEUE_FLAGS);
+ }
+
+ return 0;
+}
+
+static int
+nft_rule_expr_queue_json_parse(struct nft_rule_expr *e, json_t *root)
+{
+#ifdef JSON_PARSING
+ uint32_t type;
+ uint16_t code;
+
+ if (nft_jansson_parse_val(root, "num", NFT_TYPE_U16, &type) < 0)
+ return -1;
+
+ nft_rule_expr_set_u32(e, NFT_EXPR_QUEUE_NUM, type);
+
+ if (nft_jansson_parse_val(root, "total", NFT_TYPE_U16, &code) < 0)
+ return -1;
+
+ nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_TOTAL, code);
+
+ if (nft_jansson_parse_val(root, "flags", NFT_TYPE_U16, &code) < 0)
+ return -1;
+
+ nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_FLAGS, code);
+
+ return 0;
+#else
+ errno = EOPNOTSUPP;
+ return -1;
+#endif
+}
+
+static int
+nft_rule_expr_queue_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree)
+{
+#ifdef XML_PARSING
+ struct nft_expr_queue *queue = nft_expr_data(e);
+
+ if (nft_mxml_num_parse(tree, "num", MXML_DESCEND_FIRST, BASE_DEC,
+ &queue->queuenum, NFT_TYPE_U16, NFT_XML_MAND) != 0)
+ return -1;
+
+ e->flags |= (1 << NFT_EXPR_QUEUE_NUM);
+
+ if (nft_mxml_num_parse(tree, "total", MXML_DESCEND_FIRST, BASE_DEC,
+ &queue->queues_total, NFT_TYPE_U8, NFT_XML_MAND) != 0)
+ return -1;
+
+ e->flags |= (1 << NFT_EXPR_QUEUE_TOTAL);
+
+ if (nft_mxml_num_parse(tree, "flags", MXML_DESCEND_FIRST, BASE_DEC,
+ &queue->flags, NFT_TYPE_U8, NFT_XML_MAND) != 0)
+ return -1;
+
+ e->flags |= (1 << NFT_EXPR_QUEUE_FLAGS);
+
+ return 0;
+#else
+ errno = EOPNOTSUPP;
+ return -1;
+#endif
+}
+
+static int
+nft_rule_expr_queue_snprintf(char *buf, size_t len, uint32_t type,
+ uint32_t flags, struct nft_rule_expr *e)
+{
+ struct nft_expr_queue *queue = nft_expr_data(e);
+ int ret;
+ int one = 0;
+
+ switch(type) {
+ case NFT_OUTPUT_DEFAULT:
+ ret = snprintf(buf, len, "num %u total %u",
+ queue->queuenum, queue->queues_total);
+ if (queue->flags) {
+ ret += snprintf(buf + ret , len - ret, " options ");
+ if (queue->flags & NFT_QUEUE_FLAG_BYPASS) {
+ ret += snprintf(buf + ret ,
+ len - ret, "bypass");
+ one = 1;
+ }
+ if (queue->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ if (one)
+ ret += snprintf(buf + ret ,
+ len - ret, ",");
+ ret += snprintf(buf + ret ,
+ len - ret, "fanout");
+ }
+ }
+ return ret;
+ case NFT_OUTPUT_XML:
+ return snprintf(buf, len, "<num>%u</num>"
+ "<total>%u</total>"
+ "<flags>%u</flags>",
+ queue->queuenum, queue->queues_total,
+ queue->flags);
+ case NFT_OUTPUT_JSON:
+ return snprintf(buf, len, "\"num\":%u,"
+ "\"total\":%u,"
+ "\"flags\":%u,",
+ queue->queuenum, queue->queues_total,
+ queue->flags);
+ default:
+ break;
+ }
+ return -1;
+}
+
+struct expr_ops expr_ops_queue = {
+ .name = "queue",
+ .alloc_len = sizeof(struct nft_expr_queue),
+ .max_attr = NFTA_QUEUE_MAX,
+ .set = nft_rule_expr_queue_set,
+ .get = nft_rule_expr_queue_get,
+ .parse = nft_rule_expr_queue_parse,
+ .build = nft_rule_expr_queue_build,
+ .snprintf = nft_rule_expr_queue_snprintf,
+ .xml_parse = nft_rule_expr_queue_xml_parse,
+ .json_parse = nft_rule_expr_queue_json_parse,
+};
+
+static void __init expr_queue_init(void)
+{
+ nft_expr_ops_register(&expr_ops_queue);
+}
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [libnftables PATCH 2/2] test: add tests for expr queue
2013-11-30 10:57 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Eric Leblond
@ 2013-11-30 10:57 ` Eric Leblond
2013-12-10 10:03 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Pablo Neira Ayuso
1 sibling, 0 replies; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 10:57 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
tests/Makefile.am | 4 ++
tests/nft-expr_queue-test.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+)
create mode 100644 tests/nft-expr_queue-test.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 362eeac..576bf73 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -19,6 +19,7 @@ check_PROGRAMS = nft-parsing-test \
nft-expr_meta-test \
nft-expr_nat-test \
nft-expr_payload-test \
+ nft-expr_queue-test \
nft-expr_reject-test \
nft-expr_target-test
@@ -79,6 +80,9 @@ nft_expr_nat_test_LDADD = ../src/libnftables.la ${LIBMNL_LIBS}
nft_expr_payload_test_SOURCES = nft-expr_payload-test.c
nft_expr_payload_test_LDADD = ../src/libnftables.la ${LIBMNL_LIBS}
+nft_expr_queue_test_SOURCES = nft-expr_queue-test.c
+nft_expr_queue_test_LDADD = ../src/libnftables.la ${LIBMNL_LIBS}
+
nft_expr_reject_test_SOURCES = nft-expr_reject-test.c
nft_expr_reject_test_LDADD = ../src/libnftables.la ${LIBMNL_LIBS}
diff --git a/tests/nft-expr_queue-test.c b/tests/nft-expr_queue-test.c
new file mode 100644
index 0000000..eb741f4
--- /dev/null
+++ b/tests/nft-expr_queue-test.c
@@ -0,0 +1,99 @@
+/*
+ * (C) 2013 by Eric Leblond <eric@regit.org>
+ *
+ * Based on test framework by Ana Rey Botello <anarey@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter/xt_iprange.h>
+#include <libmnl/libmnl.h>
+#include <libnftables/rule.h>
+#include <libnftables/expr.h>
+
+static int test_ok = 1;
+
+static void print_err(const char *msg)
+{
+ test_ok = 0;
+ printf("\033[31mERROR:\e[0m %s\n", msg);
+}
+
+static void cmp_nft_rule_expr(struct nft_rule_expr *rule_a,
+ struct nft_rule_expr *rule_b)
+{
+ if (nft_rule_expr_get_u16(rule_a, NFT_EXPR_QUEUE_NUM) !=
+ nft_rule_expr_get_u16(rule_b, NFT_EXPR_QUEUE_NUM))
+ print_err("Expr NFT_EXPR_QUEUE_NUM mismatches");
+ if (nft_rule_expr_get_u16(rule_a, NFT_EXPR_QUEUE_TOTAL) !=
+ nft_rule_expr_get_u16(rule_b, NFT_EXPR_QUEUE_TOTAL))
+ print_err("Expr NFT_EXPR_QUEUE_TOTAL mismatches");
+}
+
+int main(int argc, char *argv[])
+{
+ struct nft_rule *a, *b;
+ struct nft_rule_expr *ex;
+ struct nlmsghdr *nlh;
+ char buf[4096];
+ struct nft_rule_expr_iter *iter_a, *iter_b;
+ struct nft_rule_expr *rule_a, *rule_b;
+
+ a = nft_rule_alloc();
+ b = nft_rule_alloc();
+ if (a == NULL || b == NULL)
+ print_err("OOM");
+ ex = nft_rule_expr_alloc("queue");
+ if (ex == NULL)
+ print_err("OOM");
+
+ nft_rule_expr_set_u16(ex, NFT_EXPR_QUEUE_NUM, 0x123);
+ nft_rule_expr_set_u16(ex, NFT_EXPR_QUEUE_TOTAL, 0x2);
+ nft_rule_expr_set_u16(ex, NFT_EXPR_QUEUE_FLAGS, 0x2);
+
+ nft_rule_add_expr(a, ex);
+
+ nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET, 0, 1234);
+ nft_rule_nlmsg_build_payload(nlh, a);
+
+ if (nft_rule_nlmsg_parse(nlh, b) < 0)
+ print_err("parsing problems");
+
+ iter_a = nft_rule_expr_iter_create(a);
+ iter_b = nft_rule_expr_iter_create(b);
+ if (iter_a == NULL || iter_b == NULL)
+ print_err("OOM");
+
+ rule_a = nft_rule_expr_iter_next(iter_a);
+ rule_b = nft_rule_expr_iter_next(iter_b);
+ if (rule_a == NULL || rule_b == NULL)
+ print_err("OOM");
+
+ cmp_nft_rule_expr(rule_a, rule_b);
+
+ if (nft_rule_expr_iter_next(iter_a) != NULL ||
+ nft_rule_expr_iter_next(iter_b) != NULL)
+ print_err("More 1 expr.");
+
+ nft_rule_expr_iter_destroy(iter_a);
+ nft_rule_expr_iter_destroy(iter_b);
+ nft_rule_free(a);
+ nft_rule_free(b);
+
+ if (!test_ok)
+ exit(EXIT_FAILURE);
+
+ printf("%s: \033[32mOK\e[0m\n", argv[0]);
+ return EXIT_SUCCESS;
+}
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [libnftables PATCH 1/2] expr: add support for nfnetlink queue
2013-11-30 10:57 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Eric Leblond
2013-11-30 10:57 ` [libnftables PATCH 2/2] test: add tests for expr queue Eric Leblond
@ 2013-12-10 10:03 ` Pablo Neira Ayuso
1 sibling, 0 replies; 32+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-10 10:03 UTC (permalink / raw)
To: Eric Leblond; +Cc: netfilter-devel
On Sat, Nov 30, 2013 at 11:57:21AM +0100, Eric Leblond wrote:
> This patch adds a support of the queue target.
Applied these two libnftables patches to the next-3.14 branch:
http://git.netfilter.org/libnftables/log/?h=next-3.14
Will merge this to master once 3.13 is out as this feature is
scheduled for 3.14.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [nft PATCH] Add support for queue target
2013-11-30 10:52 [nft PATCH] add support for queue target Eric Leblond
2013-11-30 10:56 ` [PATCH 1/2] netfilter: nft: fix issue with verdict support Eric Leblond
2013-11-30 10:57 ` [libnftables PATCH 1/2] expr: add support for nfnetlink queue Eric Leblond
@ 2013-11-30 10:57 ` Eric Leblond
2013-12-29 18:28 ` [nftables PATCHv2 0/1] Support " Eric Leblond
2 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-11-30 10:57 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
This patch adds support for the queue target. It is now possible
to specify rule sending packet to a given queue and using
load balancing:
nft add rule filter output queue num 3 total 2 options fanout
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/linux/netfilter/nf_tables.h | 20 ++++++++++++
include/statement.h | 11 +++++++
src/evaluate.c | 2 ++
src/netlink_delinearize.c | 15 +++++++++
src/netlink_linearize.c | 22 +++++++++++++
src/parser.y | 61 ++++++++++++++++++++++++++++++++++---
src/scanner.l | 8 ++++-
src/statement.c | 31 +++++++++++++++++++
8 files changed, 164 insertions(+), 6 deletions(-)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index a236cc3..1d5a925 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -587,6 +587,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink group to send messages to (NLA_U32)
+ * @NFTA_QUEUE_TOTAL: prefix to prepend to log messages (NLA_STRING)
+ * @NFTA_QUEUE_FLAGS: length of payload to include in netlink message (NLA_U32)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/include/statement.h b/include/statement.h
index 6ecbb18..14a66df 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -59,6 +59,14 @@ struct nat_stmt {
extern struct stmt *nat_stmt_alloc(const struct location *loc);
+struct queue_stmt {
+ uint16_t queuenum;
+ uint16_t queues_total;
+ uint16_t flags;
+};
+
+extern struct stmt *queue_stmt_alloc(const struct location *loc);
+
/**
* enum stmt_types - statement types
*
@@ -71,6 +79,7 @@ extern struct stmt *nat_stmt_alloc(const struct location *loc);
* @STMT_LOG: log statement
* @STMT_REJECT: REJECT statement
* @STMT_NAT: NAT statement
+ * @STMT_QUEUE: QUEUE statement
*/
enum stmt_types {
STMT_INVALID,
@@ -82,6 +91,7 @@ enum stmt_types {
STMT_LOG,
STMT_REJECT,
STMT_NAT,
+ STMT_QUEUE,
};
/**
@@ -127,6 +137,7 @@ struct stmt {
struct limit_stmt limit;
struct reject_stmt reject;
struct nat_stmt nat;
+ struct queue_stmt queue;
};
};
diff --git a/src/evaluate.c b/src/evaluate.c
index 94fee64..d4f8339 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1174,6 +1174,8 @@ static int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
return stmt_evaluate_reject(ctx, stmt);
case STMT_NAT:
return stmt_evaluate_nat(ctx, stmt);
+ case STMT_QUEUE:
+ return 0;
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 7e4e38c..8ae3a76 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -481,6 +481,20 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
+static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nft_rule_expr *nle)
+{
+ struct stmt *stmt;
+
+ stmt = queue_stmt_alloc(loc);
+ stmt->queue.queuenum = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_NUM);
+ stmt->queue.queues_total =
+ nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_TOTAL);
+ stmt->queue.flags = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_FLAGS);
+ list_add_tail(&stmt->list, &ctx->rule->stmts);
+}
+
static const struct {
const char *name;
void (*parse)(struct netlink_parse_ctx *ctx,
@@ -501,6 +515,7 @@ static const struct {
{ .name = "limit", .parse = netlink_parse_limit },
{ .name = "reject", .parse = netlink_parse_reject },
{ .name = "nat", .parse = netlink_parse_nat },
+ { .name = "queue", .parse = netlink_parse_queue },
};
static const struct input_descriptor indesc_netlink = {
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index e64e92a..2f1eba8 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -634,6 +634,26 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
nft_rule_add_expr(ctx->nlr, nle);
}
+static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx,
+ const struct stmt *stmt)
+{
+ struct nft_rule_expr *nle;
+
+ nle = alloc_nft_expr("queue");
+
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_NUM,
+ stmt->queue.queuenum);
+ if (stmt->queue.queues_total) {
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_TOTAL,
+ stmt->queue.queues_total);
+ }
+ if (stmt->queue.flags) {
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_FLAGS,
+ stmt->queue.flags);
+ }
+ nft_rule_add_expr(ctx->nlr, nle);
+}
+
static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
@@ -654,6 +674,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
return netlink_gen_reject_stmt(ctx, stmt);
case STMT_NAT:
return netlink_gen_nat_stmt(ctx, stmt);
+ case STMT_QUEUE:
+ return netlink_gen_queue_stmt(ctx, stmt);
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
diff --git a/src/parser.y b/src/parser.y
index a49e5c2..138c523 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -179,7 +179,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token JUMP "jump"
%token GOTO "goto"
%token RETURN "return"
-%token QUEUE "queue"
%token <val> NUM "number"
%token <string> STRING "string"
@@ -329,6 +328,13 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token SNAT "snat"
%token DNAT "dnat"
+%token QUEUE "queue"
+%token QUEUENUM "num"
+%token QUEUETOTAL "total"
+%token QUEUEBYPASS "bypass"
+%token QUEUECPUFANOUT "fanout"
+%token OPTIONS "options"
+
%token POSITION "position"
%type <string> identifier string
@@ -376,6 +382,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { stmt_free($$); } reject_stmt
%type <stmt> nat_stmt nat_stmt_alloc
%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc
+%type <stmt> queue_stmt queue_stmt_alloc
+%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
+%type <val> queue_flag
%type <expr> symbol_expr verdict_expr integer_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr
@@ -922,6 +931,7 @@ stmt : verdict_stmt
| limit_stmt
| reject_stmt
| nat_stmt
+ | queue_stmt
;
verdict_stmt : verdict_expr
@@ -1046,6 +1056,51 @@ nat_stmt_args : expr
}
;
+queue_stmt : queue_stmt_alloc
+ | queue_stmt_alloc queue_args
+ ;
+
+queue_stmt_alloc : QUEUE
+ {
+ $$ = queue_stmt_alloc(&@$);
+ }
+ ;
+
+queue_args : queue_arg
+ {
+ $<stmt>$ = $<stmt>0;
+ }
+ | queue_args queue_arg
+ ;
+
+queue_arg : QUEUENUM NUM
+ {
+ $<stmt>0->queue.queuenum = $2;
+ }
+ | QUEUETOTAL NUM
+ {
+ $<stmt>0->queue.queues_total = $2;
+ }
+ | OPTIONS queue_flag
+ {
+ $<stmt>0->queue.flags = $2;
+ }
+ ;
+
+queue_flag : queue_flag COMMA queue_flag
+ {
+ $$ |= $1 | $3;
+ }
+ | QUEUEBYPASS
+ {
+ $$ = NFT_QUEUE_FLAG_BYPASS;
+ }
+ | QUEUECPUFANOUT
+ {
+ $$ = NFT_QUEUE_FLAG_CPU_FANOUT;
+ }
+ ;
+
match_stmt : relational_expr
{
$$ = expr_stmt_alloc(&@$, $1);
@@ -1282,10 +1337,6 @@ verdict_expr : ACCEPT
{
$$ = verdict_expr_alloc(&@$, NF_DROP, NULL);
}
- | QUEUE
- {
- $$ = verdict_expr_alloc(&@$, NF_QUEUE, NULL);
- }
| CONTINUE
{
$$ = verdict_expr_alloc(&@$, NFT_CONTINUE, NULL);
diff --git a/src/scanner.l b/src/scanner.l
index cee6aa6..8c4f25d 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -234,7 +234,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"jump" { return JUMP; }
"goto" { return GOTO; }
"return" { return RETURN; }
-"queue" { return QUEUE; }
"add" { return ADD; }
"insert" { return INSERT; }
@@ -255,6 +254,13 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"snaplen" { return SNAPLEN; }
"queue-threshold" { return QUEUE_THRESHOLD; }
+"queue" { return QUEUE;}
+"num" { return QUEUENUM;}
+"total" { return QUEUETOTAL;}
+"bypass" { return QUEUEBYPASS;}
+"fanout" { return QUEUECPUFANOUT;}
+"options" { return OPTIONS;}
+
"limit" { return LIMIT; }
"rate" { return RATE; }
diff --git a/src/statement.c b/src/statement.c
index d18e034..3fdd9e2 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -172,6 +172,37 @@ struct stmt *limit_stmt_alloc(const struct location *loc)
return stmt_alloc(loc, &limit_stmt_ops);
}
+static void queue_stmt_print(const struct stmt *stmt)
+{
+ int one = 0;
+
+ printf("queue num %u total %u",
+ stmt->queue.queuenum, stmt->queue.queues_total);
+ if (stmt->queue.flags)
+ printf(" options ");
+ if (stmt->queue.flags & NFT_QUEUE_FLAG_BYPASS) {
+ printf("bypass");
+ one = 1;
+ }
+ if (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ if (one)
+ printf (",");
+ printf("fanout");
+ }
+
+}
+
+static const struct stmt_ops queue_stmt_ops = {
+ .type = STMT_QUEUE,
+ .name = "queue",
+ .print = queue_stmt_print,
+};
+
+struct stmt *queue_stmt_alloc(const struct location *loc)
+{
+ return stmt_alloc(loc, &queue_stmt_ops);
+}
+
static void reject_stmt_print(const struct stmt *stmt)
{
printf("reject");
--
1.8.4.4
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [nftables PATCHv2 0/1] Support for queue target
2013-11-30 10:57 ` [nft PATCH] Add support for queue target Eric Leblond
@ 2013-12-29 18:28 ` Eric Leblond
2013-12-29 18:28 ` [nftables PATCHv2] Add support " Eric Leblond
0 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-29 18:28 UTC (permalink / raw)
To: netfilter-devel, pablo
Hello,
Here's a small update of previous patch. Only change is the fix
of a warning in parser.y.
BR,
--
Eric
^ permalink raw reply [flat|nested] 32+ messages in thread
* [nftables PATCHv2] Add support for queue target
2013-12-29 18:28 ` [nftables PATCHv2 0/1] Support " Eric Leblond
@ 2013-12-29 18:28 ` Eric Leblond
2014-01-04 0:09 ` Pablo Neira Ayuso
0 siblings, 1 reply; 32+ messages in thread
From: Eric Leblond @ 2013-12-29 18:28 UTC (permalink / raw)
To: netfilter-devel, pablo; +Cc: Eric Leblond
This patch adds support for the queue target. It is now possible
to specify rule sending packet to a given queue and using
load balancing:
nft add rule filter output queue num 3 total 2 options fanout
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/linux/netfilter/nf_tables.h | 20 +++++++++++
include/statement.h | 11 ++++++
src/evaluate.c | 2 ++
src/netlink_delinearize.c | 15 +++++++++
src/netlink_linearize.c | 22 ++++++++++++
src/parser.y | 67 ++++++++++++++++++++++++++++++++++---
src/scanner.l | 8 ++++-
src/statement.c | 31 +++++++++++++++++
8 files changed, 170 insertions(+), 6 deletions(-)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index a236cc3..1d5a925 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -587,6 +587,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink group to send messages to (NLA_U32)
+ * @NFTA_QUEUE_TOTAL: prefix to prepend to log messages (NLA_STRING)
+ * @NFTA_QUEUE_FLAGS: length of payload to include in netlink message (NLA_U32)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/include/statement.h b/include/statement.h
index 6ecbb18..14a66df 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -59,6 +59,14 @@ struct nat_stmt {
extern struct stmt *nat_stmt_alloc(const struct location *loc);
+struct queue_stmt {
+ uint16_t queuenum;
+ uint16_t queues_total;
+ uint16_t flags;
+};
+
+extern struct stmt *queue_stmt_alloc(const struct location *loc);
+
/**
* enum stmt_types - statement types
*
@@ -71,6 +79,7 @@ extern struct stmt *nat_stmt_alloc(const struct location *loc);
* @STMT_LOG: log statement
* @STMT_REJECT: REJECT statement
* @STMT_NAT: NAT statement
+ * @STMT_QUEUE: QUEUE statement
*/
enum stmt_types {
STMT_INVALID,
@@ -82,6 +91,7 @@ enum stmt_types {
STMT_LOG,
STMT_REJECT,
STMT_NAT,
+ STMT_QUEUE,
};
/**
@@ -127,6 +137,7 @@ struct stmt {
struct limit_stmt limit;
struct reject_stmt reject;
struct nat_stmt nat;
+ struct queue_stmt queue;
};
};
diff --git a/src/evaluate.c b/src/evaluate.c
index 94fee64..d4f8339 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1174,6 +1174,8 @@ static int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
return stmt_evaluate_reject(ctx, stmt);
case STMT_NAT:
return stmt_evaluate_nat(ctx, stmt);
+ case STMT_QUEUE:
+ return 0;
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index d1d35f8..b771da5 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -508,6 +508,20 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
+static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nft_rule_expr *nle)
+{
+ struct stmt *stmt;
+
+ stmt = queue_stmt_alloc(loc);
+ stmt->queue.queuenum = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_NUM);
+ stmt->queue.queues_total =
+ nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_TOTAL);
+ stmt->queue.flags = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_FLAGS);
+ list_add_tail(&stmt->list, &ctx->rule->stmts);
+}
+
static const struct {
const char *name;
void (*parse)(struct netlink_parse_ctx *ctx,
@@ -528,6 +542,7 @@ static const struct {
{ .name = "limit", .parse = netlink_parse_limit },
{ .name = "reject", .parse = netlink_parse_reject },
{ .name = "nat", .parse = netlink_parse_nat },
+ { .name = "queue", .parse = netlink_parse_queue },
};
static const struct input_descriptor indesc_netlink = {
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 0ac0218..9ae9bb7 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -636,6 +636,26 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
nft_rule_add_expr(ctx->nlr, nle);
}
+static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx,
+ const struct stmt *stmt)
+{
+ struct nft_rule_expr *nle;
+
+ nle = alloc_nft_expr("queue");
+
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_NUM,
+ stmt->queue.queuenum);
+ if (stmt->queue.queues_total) {
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_TOTAL,
+ stmt->queue.queues_total);
+ }
+ if (stmt->queue.flags) {
+ nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_FLAGS,
+ stmt->queue.flags);
+ }
+ nft_rule_add_expr(ctx->nlr, nle);
+}
+
static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
@@ -656,6 +676,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
return netlink_gen_reject_stmt(ctx, stmt);
case STMT_NAT:
return netlink_gen_nat_stmt(ctx, stmt);
+ case STMT_QUEUE:
+ return netlink_gen_queue_stmt(ctx, stmt);
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
diff --git a/src/parser.y b/src/parser.y
index 26e71e3..9320f2d 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -180,7 +180,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token JUMP "jump"
%token GOTO "goto"
%token RETURN "return"
-%token QUEUE "queue"
%token <val> NUM "number"
%token <string> STRING "string"
@@ -330,6 +329,13 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token SNAT "snat"
%token DNAT "dnat"
+%token QUEUE "queue"
+%token QUEUENUM "num"
+%token QUEUETOTAL "total"
+%token QUEUEBYPASS "bypass"
+%token QUEUECPUFANOUT "fanout"
+%token OPTIONS "options"
+
%token POSITION "position"
%type <string> identifier string
@@ -377,6 +383,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { stmt_free($$); } reject_stmt
%type <stmt> nat_stmt nat_stmt_alloc
%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc
+%type <stmt> queue_stmt queue_stmt_alloc
+%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
+%type <val> queue_flags queue_flag
%type <expr> symbol_expr verdict_expr integer_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr
@@ -927,6 +936,7 @@ stmt : verdict_stmt
| limit_stmt
| reject_stmt
| nat_stmt
+ | queue_stmt
;
verdict_stmt : verdict_expr
@@ -1051,6 +1061,57 @@ nat_stmt_args : expr
}
;
+queue_stmt : queue_stmt_alloc
+ | queue_stmt_alloc queue_args
+ ;
+
+queue_stmt_alloc : QUEUE
+ {
+ $$ = queue_stmt_alloc(&@$);
+ }
+ ;
+
+queue_args : queue_arg
+ {
+ $<stmt>$ = $<stmt>0;
+ }
+ | queue_args queue_arg
+ ;
+
+queue_arg : QUEUENUM NUM
+ {
+ $<stmt>0->queue.queuenum = $2;
+ }
+ | QUEUETOTAL NUM
+ {
+ $<stmt>0->queue.queues_total = $2;
+ }
+ | OPTIONS queue_flags
+ {
+ $<stmt>0->queue.flags = $2;
+ }
+ ;
+
+queue_flags : queue_flag
+ {
+ $$ = $1;
+ }
+ | queue_flags COMMA queue_flag
+ {
+ $$ |= $1 | $3;
+ }
+ ;
+
+queue_flag : QUEUEBYPASS
+ {
+ $$ = NFT_QUEUE_FLAG_BYPASS;
+ }
+ | QUEUECPUFANOUT
+ {
+ $$ = NFT_QUEUE_FLAG_CPU_FANOUT;
+ }
+ ;
+
match_stmt : relational_expr
{
$$ = expr_stmt_alloc(&@$, $1);
@@ -1287,10 +1348,6 @@ verdict_expr : ACCEPT
{
$$ = verdict_expr_alloc(&@$, NF_DROP, NULL);
}
- | QUEUE
- {
- $$ = verdict_expr_alloc(&@$, NF_QUEUE, NULL);
- }
| CONTINUE
{
$$ = verdict_expr_alloc(&@$, NFT_CONTINUE, NULL);
diff --git a/src/scanner.l b/src/scanner.l
index cee6aa6..8c4f25d 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -234,7 +234,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"jump" { return JUMP; }
"goto" { return GOTO; }
"return" { return RETURN; }
-"queue" { return QUEUE; }
"add" { return ADD; }
"insert" { return INSERT; }
@@ -255,6 +254,13 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"snaplen" { return SNAPLEN; }
"queue-threshold" { return QUEUE_THRESHOLD; }
+"queue" { return QUEUE;}
+"num" { return QUEUENUM;}
+"total" { return QUEUETOTAL;}
+"bypass" { return QUEUEBYPASS;}
+"fanout" { return QUEUECPUFANOUT;}
+"options" { return OPTIONS;}
+
"limit" { return LIMIT; }
"rate" { return RATE; }
diff --git a/src/statement.c b/src/statement.c
index d18e034..3fdd9e2 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -172,6 +172,37 @@ struct stmt *limit_stmt_alloc(const struct location *loc)
return stmt_alloc(loc, &limit_stmt_ops);
}
+static void queue_stmt_print(const struct stmt *stmt)
+{
+ int one = 0;
+
+ printf("queue num %u total %u",
+ stmt->queue.queuenum, stmt->queue.queues_total);
+ if (stmt->queue.flags)
+ printf(" options ");
+ if (stmt->queue.flags & NFT_QUEUE_FLAG_BYPASS) {
+ printf("bypass");
+ one = 1;
+ }
+ if (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+ if (one)
+ printf (",");
+ printf("fanout");
+ }
+
+}
+
+static const struct stmt_ops queue_stmt_ops = {
+ .type = STMT_QUEUE,
+ .name = "queue",
+ .print = queue_stmt_print,
+};
+
+struct stmt *queue_stmt_alloc(const struct location *loc)
+{
+ return stmt_alloc(loc, &queue_stmt_ops);
+}
+
static void reject_stmt_print(const struct stmt *stmt)
{
printf("reject");
--
1.8.5.2
^ permalink raw reply related [flat|nested] 32+ messages in thread