From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Liping Zhang <zlpnobody@163.com>
Cc: netfilter-devel@vger.kernel.org,
Liping Zhang <liping.zhang@spreadtrum.com>
Subject: Re: [PATCH nf-next] netfilter: nft_queue: add _SREG_FROM and _SRGE_TO to select the queue numbers
Date: Tue, 13 Sep 2016 11:19:17 +0200 [thread overview]
Message-ID: <20160913091917.GA4051@salvia> (raw)
In-Reply-To: <1473602728-33502-2-git-send-email-zlpnobody@163.com>
Hi Liping,
A bit more comments on top of Florian's suggestion to use one single
_SREG.
On Sun, Sep 11, 2016 at 10:05:28PM +0800, Liping Zhang wrote:
> diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
> index d16d599..6557118 100644
> --- a/net/netfilter/nft_queue.c
> +++ b/net/netfilter/nft_queue.c
> @@ -22,9 +22,11 @@
> static u32 jhash_initval __read_mostly;
>
> struct nft_queue {
> - u16 queuenum;
> - u16 queues_total;
> - u16 flags;
> + enum nft_registers sreg_from:8;
> + enum nft_registers sreg_to:8;
> + u16 queuenum;
> + u16 queues_total;
> + u16 flags;
> };
>
> static void nft_queue_eval(const struct nft_expr *expr,
> @@ -32,17 +34,30 @@ static void nft_queue_eval(const struct nft_expr *expr,
> const struct nft_pktinfo *pkt)
> {
> struct nft_queue *priv = nft_expr_priv(expr);
> - u32 queue = priv->queuenum;
> + u32 queue, queues_total, queue_end;
> u32 ret;
>
> - if (priv->queues_total > 1) {
> + if (priv->sreg_from) {
> + queue = (u16)regs->data[priv->sreg_from];
> + queue_end = (u16)regs->data[priv->sreg_to];
> +
> + if (queue_end > queue)
> + queues_total = queue_end - queue + 1;
> + else
> + queues_total = 1;
> + } else {
> + queue = priv->queuenum;
> + queues_total = priv->queues_total;
> + }
I suggest you use .select_ops to use a specific _eval function if
_SREG is set. This would disentangle this code a bit.
> +
> + if (queues_total > 1) {
> if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
> int cpu = smp_processor_id();
>
> - queue = priv->queuenum + cpu % priv->queues_total;
> + queue += cpu % queues_total;
> } else {
> queue = nfqueue_hash(pkt->skb, queue,
> - priv->queues_total, pkt->pf,
> + queues_total, pkt->pf,
> jhash_initval);
> }
> }
> @@ -58,6 +73,8 @@ 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 },
> + [NFTA_QUEUE_SREG_FROM] = { .type = NLA_U32 },
> + [NFTA_QUEUE_SREG_TO] = { .type = NLA_U32 },
> };
>
> static int nft_queue_init(const struct nft_ctx *ctx,
> @@ -66,30 +83,58 @@ static int nft_queue_init(const struct nft_ctx *ctx,
> {
> struct nft_queue *priv = nft_expr_priv(expr);
> u32 maxid;
> + int err;
>
> - if (tb[NFTA_QUEUE_NUM] == NULL)
> + if (!tb[NFTA_QUEUE_NUM] && !tb[NFTA_QUEUE_SREG_FROM])
> return -EINVAL;
>
> init_hashrandom(&jhash_initval);
> - 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]));
> - else
> - priv->queues_total = 1;
> + /* nftables has no idea whether the kernel supports _SREG_FROM or not,
> + * so for compatibility reason, it may specify the _SREG_FROM and
> + * _QUEUE_NUM attributes at the same time. We prefer to use _SREG_FROM,
> + * it is more flexible and has less restriction, for example, queue
> + * range 0-65535 is ok when use _SREG_FROM and _SREG_TO.
> + */
No need for this large comment, look.
>From userspace, we have to modify the nft parser to take an expression
as 'num'. Then, from the netlink_linearize path, we can check the
expression type:
* If it's a value expression, we can simply use NFTA_QUEUE_NUM.
* If it's a range expression, we have to set up NFTA_QUEUE_NUM and
NFTA_QUEUE_TOTAL.
* If it's a mapping, then we only use _SREG.
Old kernels will bail out if the mapping is used, as this is not
supported, which is what we expect. This should be fine by now, until
I finish the patchset to provide a VM description that userspace can
use to generate bytecode depending on the features available in the
kernel.
> + if (tb[NFTA_QUEUE_SREG_FROM]) {
> + priv->sreg_from = nft_parse_register(tb[NFTA_QUEUE_SREG_FROM]);
> + err = nft_validate_register_load(priv->sreg_from, sizeof(u16));
> + if (err < 0)
> + return err;
> +
> + if (tb[NFTA_QUEUE_SREG_TO]) {
> + priv->sreg_to =
> + nft_parse_register(tb[NFTA_QUEUE_SREG_TO]);
> + err = nft_validate_register_load(priv->sreg_to,
> + sizeof(u16));
> + if (err < 0)
> + return err;
> + } else {
> + priv->sreg_to = priv->sreg_from;
> + }
> + } else if (tb[NFTA_QUEUE_NUM]) {
> + priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
>
> - if (priv->queues_total == 0)
> - return -EINVAL;
> + if (tb[NFTA_QUEUE_TOTAL])
> + priv->queues_total =
> + ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
> + else
> + priv->queues_total = 1;
>
> - maxid = priv->queues_total - 1 + priv->queuenum;
> - if (maxid > U16_MAX)
> - return -ERANGE;
> + if (priv->queues_total == 0)
> + return -EINVAL;
> +
> + maxid = priv->queues_total - 1 + priv->queuenum;
> + if (maxid > U16_MAX)
> + return -ERANGE;
> + }
>
> 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;
> }
>
> @@ -97,9 +142,21 @@ 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)))
> + if (priv->sreg_from) {
> + if (nft_dump_register(skb, NFTA_QUEUE_SREG_FROM,
> + priv->sreg_from))
> + goto nla_put_failure;
> + if (nft_dump_register(skb, NFTA_QUEUE_SREG_TO,
> + priv->sreg_to))
> + goto nla_put_failure;
> + } else {
> + if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)) ||
> + nla_put_be16(skb, NFTA_QUEUE_TOTAL,
> + htons(priv->queues_total)))
> + goto nla_put_failure;
> + }
Looking at this, the code will look better if we should use
.select_ops indeed.
Thanks for resolving existing nft_queue limitations!
next prev parent reply other threads:[~2016-09-13 9:19 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-11 14:05 [PATCH nf-next] netfilter: nf_queue: get rid of dependency on IP6_NF_IPTABLES Liping Zhang
2016-09-11 14:05 ` [PATCH nf-next] netfilter: nft_queue: add _SREG_FROM and _SRGE_TO to select the queue numbers Liping Zhang
2016-09-11 21:12 ` Florian Westphal
2016-09-12 2:19 ` Liping Zhang
2016-09-12 10:53 ` Laura Garcia
2016-09-12 12:28 ` Florian Westphal
2016-09-12 12:39 ` Pablo Neira Ayuso
2016-09-12 12:09 ` Pablo Neira Ayuso
2016-09-12 12:22 ` Florian Westphal
2016-09-12 12:32 ` Pablo Neira Ayuso
2016-09-12 13:18 ` Florian Westphal
2016-09-13 9:19 ` Pablo Neira Ayuso [this message]
2016-09-13 12:19 ` Liping Zhang
2016-09-12 17:50 ` [PATCH nf-next] netfilter: nf_queue: get rid of dependency on IP6_NF_IPTABLES Pablo Neira Ayuso
2016-09-13 5:45 ` Liping Zhang
2016-09-13 9:10 ` Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160913091917.GA4051@salvia \
--to=pablo@netfilter.org \
--cc=liping.zhang@spreadtrum.com \
--cc=netfilter-devel@vger.kernel.org \
--cc=zlpnobody@163.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).