* [PATCH RFC nf-next] netfilter: nf_tables: add math expression support
@ 2025-09-23 15:24 Fernando Fernandez Mancera
2025-09-23 16:34 ` Florian Westphal
0 siblings, 1 reply; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2025-09-23 15:24 UTC (permalink / raw)
To: netfilter-devel; +Cc: coreteam, pablo, Fernando Fernandez Mancera
Historically, users have requested support for increasing and decreasing
TTL value in nftables in order to migrate from iptables.
Following the nftables spirit of flexible and multipurpose expressions,
this patch introduces "nft_math" expression. This expression allows to
increase and decrease u32, u16 and u8 values stored in the nftables
registers. In addition, it takes into account the byteorder of the value
stored in the source register, so there is no need to do a byteorder
conversion before and after the math expression.
The math expression intends to be flexible enough in case it needs to be
extended in the future, e.g implement bitfields operations. For this
reason, the length of the data is indicated in bits instead of bytes.
Payload set operations sometimes need 16 bits for checksum
recalculation. Even it is a 8 bit operation, 16 bits are loaded in the
source register. Handle such cases applying a bitmask when operating
with 8 bits length.
As a last detail, nft_math prevents overflow of the field. If the value
is already at its limit, do nothing.
This implementation comes with a libnftnl patch that allows the user to
generate the following example bytecodes:
- Bytecode to increase the TTL of a packet
table mangle inet flags 0 use 1 handle 5
inet mangle output use 1 type filter hook output prio 0 policy accept packets 0 bytes 0 flags 1
inet mangle output 2
[ payload load 2b @ network header + 8 => reg 1 ]
[ math math 8 bits host reg 1 + 1 => 1]
[ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
- Bytecode to decrease the TTL of a packet
table mangle inet flags 0 use 1 handle 7
inet mangle output use 1 type filter hook output prio 0 policy accept packets 0 bytes 0 flags 1
inet mangle output 2
[ payload load 2b @ network header + 8 => reg 1 ]
[ math math 8 bits host reg 1 - 1 => 1]
[ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
- Bytecode to increase the meta mark of a packet
table mangle inet flags 0 use 1 handle 6
inet mangle output use 1 type filter hook output prio 0 policy accept packets 0 bytes 0 flags 1
inet mangle output 2
[ meta load mark => reg 1 ]
[ math math 32 bits host reg 1 + 1 => 1]
[ meta set mark with reg 1 ]
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
include/uapi/linux/netfilter/nf_tables.h | 34 +++
net/netfilter/Kconfig | 7 +
net/netfilter/Makefile | 1 +
net/netfilter/nft_math.c | 267 +++++++++++++++++++++++
4 files changed, 309 insertions(+)
create mode 100644 net/netfilter/nft_math.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 7c0c915f0306..d5ec110ede81 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -2015,4 +2015,38 @@ enum nft_tunnel_attributes {
};
#define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1)
+/**
+ * enum nft_math_attributes - nftables math expression netlink attributes
+ *
+ * @NFTA_MATH_SREG: source register (NLA_U32: nft_registers)
+ * @NFTA_MATH_DREG: destination register (NLA_U32: nft_registers)
+ * @NFTA_MATH_OP: operation to be performed (NLA_U8)
+ * @NFTA_MATH_LEN: value length in bits (NLA_U8)
+ * @NFTA_MATH_BYTEORDER: byteorder of the value passed to the SREG (NLA_U8)
+ */
+enum nft_math_attributes {
+ NFTA_MATH_UNSPEC,
+ NFTA_MATH_SREG,
+ NFTA_MATH_DREG,
+ NFTA_MATH_OP,
+ NFTA_MATH_LEN,
+ NFTA_MATH_BYTEORDER,
+ __NFTA_MATH_MAX,
+};
+#define NFTA_MATH_MAX (__NFTA_MATH_MAX - 1)
+
+enum nft_math_op {
+ NFT_MATH_OP_INC,
+ NFT_MATH_OP_DEC,
+ __NFT_MATH_OP_MAX,
+};
+#define NFT_MATH_OP_MAX (__NFT_MATH_OP_MAX - 1)
+
+enum nft_math_byteorder {
+ NFT_MATH_BYTEORDER_HOST,
+ NFT_MATH_BYTEORDER_BIG,
+ __NFT_MATH_BYTEORDER_MAX,
+};
+#define NFT_MATH_BYTEORDER_MAX (__NFT_MATH_BYTEORDER_MAX - 1)
+
#endif /* _LINUX_NF_TABLES_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 6cdc994fdc8a..4cb4fdaedb49 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -671,6 +671,13 @@ config NFT_SYNPROXY
server. This allows to avoid conntrack and server resource usage
during SYN-flood attacks.
+config NFT_MATH
+ tristate "Netfilter nf_tables math expression support"
+ depends on NETFILTER_ADVANCED
+ help
+ The math expression allows performing mathematical operations like
+ increase, to packet fields.
+
if NF_TABLES_NETDEV
config NF_DUP_NETDEV
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index e43e20f529f8..bd560aa50ebf 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_NFT_OSF) += nft_osf.o
obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o
obj-$(CONFIG_NFT_XFRM) += nft_xfrm.o
obj-$(CONFIG_NFT_SYNPROXY) += nft_synproxy.o
+obj-$(CONFIG_NFT_MATH) += nft_math.o
obj-$(CONFIG_NFT_NAT) += nft_chain_nat.o
diff --git a/net/netfilter/nft_math.c b/net/netfilter/nft_math.c
new file mode 100644
index 000000000000..fe2d1c6a8fbf
--- /dev/null
+++ b/net/netfilter/nft_math.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <net/netlink.h>
+#include <net/netfilter/nf_tables.h>
+#include <linux/netfilter/nf_tables.h>
+
+struct nft_math {
+ u8 sreg;
+ u8 dreg;
+ u8 len;
+ enum nft_math_op op;
+ enum nft_math_byteorder byteorder;
+};
+
+static const struct nla_policy nft_math_policy[NFTA_MATH_MAX + 1] = {
+ [NFTA_MATH_SREG] = { .type = NLA_U32 },
+ [NFTA_MATH_DREG] = { .type = NLA_U32 },
+ [NFTA_MATH_OP] = { .type = NLA_U8 },
+ [NFTA_MATH_LEN] = NLA_POLICY_MIN(NLA_U8, 8),
+ [NFTA_MATH_BYTEORDER] = { .type = NLA_U8 },
+};
+
+static void nft_math_eval_u8(uint32_t *src, uint32_t *dst,
+ const struct nft_math *priv)
+{
+ u8 tmp;
+
+ /* For payload set if checksum needs to be adjusted 16 bits are stored
+ * in the source register instead of 8. Therefore, use a bitmask to
+ * operate with the less significant byte. */
+ switch (priv->op) {
+ case NFT_MATH_OP_INC:
+ tmp = *src & 0xff;
+ if (tmp != U8_MAX) {
+ tmp++;
+ *dst = (*src & ~0xff) | tmp;
+ } else {
+ *dst = *src;
+ }
+ break;
+ case NFT_MATH_OP_DEC:
+ tmp = *src & 0xff;
+ if (tmp != 0) {
+ tmp--;
+ *dst = (*src & ~0xff) | tmp;
+ } else {
+ *dst = *src;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void nft_math_eval_u16(uint32_t *src, uint32_t *dst,
+ const struct nft_math *priv)
+{
+ u16 tmp;
+
+ switch (priv->op) {
+ case NFT_MATH_OP_INC:
+ switch (priv->byteorder) {
+ case NFT_MATH_BYTEORDER_HOST:
+ tmp = nft_reg_load16(src);
+ if (tmp != U16_MAX)
+ tmp++;
+ nft_reg_store16(dst, tmp);
+ break;
+ case NFT_MATH_BYTEORDER_BIG:
+ tmp = ntohs(nft_reg_load_be16(src));
+ if (tmp != U16_MAX)
+ tmp++;
+ nft_reg_store_be16(dst, htons(tmp));
+ break;
+ default:
+ break;
+ }
+ break;
+ case NFT_MATH_OP_DEC:
+ switch (priv->byteorder) {
+ case NFT_MATH_BYTEORDER_HOST:
+ tmp = nft_reg_load16(src);
+ if (tmp != 0)
+ tmp--;
+ nft_reg_store16(dst, tmp);
+ break;
+ case NFT_MATH_BYTEORDER_BIG:
+ tmp = ntohs(nft_reg_load_be16(src));
+ if (tmp != 0)
+ tmp--;
+ nft_reg_store_be16(dst, htons(tmp));
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void nft_math_eval_u32(uint32_t *src, uint32_t *dst,
+ const struct nft_math *priv)
+{
+ u32 tmp;
+
+ switch (priv->op) {
+ case NFT_MATH_OP_INC:
+ switch (priv->byteorder) {
+ case NFT_MATH_BYTEORDER_HOST:
+ if (*src != U32_MAX)
+ *dst = *src + 1;
+ else
+ *dst = *src;
+ break;
+ case NFT_MATH_BYTEORDER_BIG:
+ tmp = ntohl(*src);
+ if (tmp != U32_MAX)
+ tmp++;
+ *dst = (__force __u32)htonl(tmp);
+ break;
+ default:
+ break;
+ }
+ break;
+ case NFT_MATH_OP_DEC:
+ switch (priv->byteorder) {
+ case NFT_MATH_BYTEORDER_HOST:
+ if (*src != 0)
+ *dst = *src - 1;
+ break;
+ case NFT_MATH_BYTEORDER_BIG:
+ tmp = ntohl(*src);
+ if (tmp != 0)
+ tmp--;
+ *dst = (__force __u32)htonl(tmp);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void nft_math_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_math *priv = nft_expr_priv(expr);
+ u32 *src = ®s->data[priv->sreg];
+ u32 *dst = ®s->data[priv->dreg];
+
+ switch (priv->len) {
+ case 8:
+ nft_math_eval_u8(src, dst, priv);
+ break;
+ case 16:
+ nft_math_eval_u16(src, dst, priv);
+ break;
+ case 32:
+ nft_math_eval_u32(src, dst, priv);
+ break;
+ default:
+ break;
+ }
+}
+
+static int nft_math_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_math *priv = nft_expr_priv(expr);
+ int err;
+
+ if (tb[NFTA_MATH_SREG] == NULL ||
+ tb[NFTA_MATH_DREG] == NULL ||
+ tb[NFTA_MATH_LEN] == NULL ||
+ tb[NFTA_MATH_OP] == NULL ||
+ tb[NFTA_MATH_BYTEORDER] == NULL)
+ return -EINVAL;
+
+ priv->op = nla_get_u8(tb[NFTA_MATH_OP]);
+ priv->byteorder = nla_get_u8(tb[NFTA_MATH_BYTEORDER]);
+ priv->len = nla_get_u8(tb[NFTA_MATH_LEN]);
+
+ if (priv->byteorder > NFT_MATH_BYTEORDER_MAX)
+ return -EINVAL;
+
+ if (priv->op > NFT_MATH_OP_MAX)
+ return -EOPNOTSUPP;
+
+ switch (priv->len) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = nft_parse_register_load(ctx, tb[NFTA_MATH_SREG], &priv->sreg,
+ priv->len / BITS_PER_BYTE);
+ if (err < 0)
+ return err;
+
+ return nft_parse_register_store(ctx, tb[NFTA_MATH_DREG],
+ &priv->dreg, NULL, NFT_DATA_VALUE,
+ priv->len / BITS_PER_BYTE);
+}
+
+static int nft_math_dump(struct sk_buff *skb,
+ const struct nft_expr *expr, bool reset)
+{
+ const struct nft_math *priv = nft_expr_priv(expr);
+
+ if (nft_dump_register(skb, NFTA_MATH_SREG, priv->sreg))
+ goto nla_put_failure;
+ if (nft_dump_register(skb, NFTA_MATH_DREG, priv->dreg))
+ goto nla_put_failure;
+ if (nla_put_u8(skb, NFTA_MATH_LEN, priv->len))
+ goto nla_put_failure;
+ if (nla_put_u8(skb, NFTA_MATH_OP, priv->op))
+ goto nla_put_failure;
+ if (nla_put_u8(skb, NFTA_MATH_BYTEORDER, priv->byteorder))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_math_type;
+static const struct nft_expr_ops nft_math_op = {
+ .eval = nft_math_eval,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_math)),
+ .init = nft_math_init,
+ .dump = nft_math_dump,
+ .type = &nft_math_type,
+};
+
+static struct nft_expr_type nft_math_type __read_mostly = {
+ .ops = &nft_math_op,
+ .name = "math",
+ .owner = THIS_MODULE,
+ .policy = nft_math_policy,
+ .maxattr = NFTA_MATH_MAX,
+};
+
+static int __init nft_math_module_init(void)
+{
+ return nft_register_expr(&nft_math_type);
+}
+
+static void __exit nft_math_module_exit(void)
+{
+ return nft_unregister_expr(&nft_math_type);
+}
+
+module_init(nft_math_module_init);
+module_exit(nft_math_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fernando Fernandez Mancera <fmancera@suse.de>");
+MODULE_ALIAS_NFT_EXPR("math");
+MODULE_DESCRIPTION("nftables math support to operate with values");
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH RFC nf-next] netfilter: nf_tables: add math expression support
2025-09-23 15:24 [PATCH RFC nf-next] netfilter: nf_tables: add math expression support Fernando Fernandez Mancera
@ 2025-09-23 16:34 ` Florian Westphal
2025-09-23 17:39 ` Fernando Fernandez Mancera
0 siblings, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2025-09-23 16:34 UTC (permalink / raw)
To: Fernando Fernandez Mancera; +Cc: netfilter-devel, coreteam, pablo
Fernando Fernandez Mancera <fmancera@suse.de> wrote:
> Historically, users have requested support for increasing and decreasing
> TTL value in nftables in order to migrate from iptables.
Right.
> In addition, it takes into account the byteorder of the value
> stored in the source register, so there is no need to do a byteorder
> conversion before and after the math expression.
Why? Any particular reason for this?
I would have expected to have ntf insert the needed byteorder
conversions.
> The math expression intends to be flexible enough in case it needs to be
> extended in the future, e.g implement bitfields operations. For this
> reason, the length of the data is indicated in bits instead of bytes.
Not so sure. We already have nft_bitwise. Or what bitfield operations
are you considering?
You mean 'add' to a non-byte part, like e.g. as in iph->ihl?
> Payload set operations sometimes need 16 bits for checksum
> recalculation. Even it is a 8 bit operation, 16 bits are loaded in the
> source register. Handle such cases applying a bitmask when operating
> with 8 bits length.
>
> As a last detail, nft_math prevents overflow of the field. If the value
> is already at its limit, do nothing.
Should it set NFT_BREAK?
> table mangle inet flags 0 use 1 handle 5
> inet mangle output use 1 type filter hook output prio 0 policy accept packets 0 bytes 0 flags 1
> inet mangle output 2
> [ payload load 2b @ network header + 8 => reg 1 ]
> [ math math 8 bits host reg 1 + 1 => 1]
> [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
Thanks for including these examples.
You can drop the 'math' from the snprintf callback in libnftnl to avoid
this 'math math'.
I assume this says 'host' because its limited to 8 bits?
> + /* For payload set if checksum needs to be adjusted 16 bits are stored
> + * in the source register instead of 8. Therefore, use a bitmask to
> + * operate with the less significant byte. */
I don't think this works. You don't know if the add should be done
on the less significant byte order the MSB one.
(If you do... how?)
AFAICS you need to add support for a displacement
offset inside the register to support this (or I should write:
work-around-align-fetch-mangling ...)
> +static int nft_math_init(const struct nft_ctx *ctx,
> + const struct nft_expr *expr,
> + const struct nlattr * const tb[])
> +{
> + struct nft_math *priv = nft_expr_priv(expr);
> + int err;
> +
> + if (tb[NFTA_MATH_SREG] == NULL ||
> + tb[NFTA_MATH_DREG] == NULL ||
> + tb[NFTA_MATH_LEN] == NULL ||
> + tb[NFTA_MATH_OP] == NULL ||
> + tb[NFTA_MATH_BYTEORDER] == NULL)
> + return -EINVAL;
> + priv->op = nla_get_u8(tb[NFTA_MATH_OP]);
Can you make it NLA_U32? NLA_U8 doesn't buy anything except
limiting us to 255 supported options (i don't see a use case
for ever having so many, but if we ever have we don't need new OP32
attribute).
I wonder if we really want this as a module, it seems rather small.
I would also be open to just extending bitwise expression with this
inc/dec, both bitwise & math expr do register manipulations.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH RFC nf-next] netfilter: nf_tables: add math expression support
2025-09-23 16:34 ` Florian Westphal
@ 2025-09-23 17:39 ` Fernando Fernandez Mancera
2025-09-23 17:58 ` Florian Westphal
0 siblings, 1 reply; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2025-09-23 17:39 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel, coreteam, pablo
On 9/23/25 6:34 PM, Florian Westphal wrote:
> Fernando Fernandez Mancera <fmancera@suse.de> wrote:
>> Historically, users have requested support for increasing and decreasing
>> TTL value in nftables in order to migrate from iptables.
>
> Right.
>
>> In addition, it takes into account the byteorder of the value
>> stored in the source register, so there is no need to do a byteorder
>> conversion before and after the math expression.
>
> Why? Any particular reason for this?
>
It is for simplicity reasons. Just to avoid a big payload with byteorder
conversions per math expression.
> I would have expected to have ntf insert the needed byteorder
> conversions.
>
>> The math expression intends to be flexible enough in case it needs to be
>> extended in the future, e.g implement bitfields operations. For this
>> reason, the length of the data is indicated in bits instead of bytes.
>
> Not so sure. We already have nft_bitwise. Or what bitfield operations
> are you considering?
>
> You mean 'add' to a non-byte part, like e.g. as in iph->ihl?
>
Yes, I do not have a clear use-case for it right now, but I just wanted
to keep it as flexible as possible.
>> Payload set operations sometimes need 16 bits for checksum
>> recalculation. Even it is a 8 bit operation, 16 bits are loaded in the
>> source register. Handle such cases applying a bitmask when operating
>> with 8 bits length.
>>
>> As a last detail, nft_math prevents overflow of the field. If the value
>> is already at its limit, do nothing.
>
> Should it set NFT_BREAK?
>
I don't think so. If the user wants to increase or decrease a field but
it already reached the limit IMO it shouldn't do anything but continue
with the next expression instead of setting NFT_BREAK. Anyway, not a
deal breaker for me..
>> table mangle inet flags 0 use 1 handle 5
>> inet mangle output use 1 type filter hook output prio 0 policy accept packets 0 bytes 0 flags 1
>> inet mangle output 2
>> [ payload load 2b @ network header + 8 => reg 1 ]
>> [ math math 8 bits host reg 1 + 1 => 1]
>> [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
>
> Thanks for including these examples.
> You can drop the 'math' from the snprintf callback in libnftnl to avoid
> this 'math math'.
>
Ugh, sorry I missed that detail.
> I assume this says 'host' because its limited to 8 bits?
>
Yes, well it says "host" because I used NFT_MATH_BYTEORDER_HOST to
generate it, anyway it doesn't matter as it is 8 bits. Would it be
better to hide byteorder if it doesn't matter?
>> + /* For payload set if checksum needs to be adjusted 16 bits are stored
>> + * in the source register instead of 8. Therefore, use a bitmask to
>> + * operate with the less significant byte. */
>
> I don't think this works. You don't know if the add should be done
> on the less significant byte order the MSB one.
>
> (If you do... how?)
>
> AFAICS you need to add support for a displacement
> offset inside the register to support this (or I should write:
> work-around-align-fetch-mangling ...)
>
So I was aware of this. But after reading nft_payload.c expression I
thought the desired value was always stored in the less significant
byte. Anyway, this assumption was wrong and you are right.
What would be the best way to implement this? A pure bit offset
(NFT_MATH_OFFSET) or a bitmask (NFT_MATH_BITMASK)?
>> +static int nft_math_init(const struct nft_ctx *ctx,
>> + const struct nft_expr *expr,
>> + const struct nlattr * const tb[])
>> +{
>> + struct nft_math *priv = nft_expr_priv(expr);
>> + int err;
>> +
>> + if (tb[NFTA_MATH_SREG] == NULL ||
>> + tb[NFTA_MATH_DREG] == NULL ||
>> + tb[NFTA_MATH_LEN] == NULL ||
>> + tb[NFTA_MATH_OP] == NULL ||
>> + tb[NFTA_MATH_BYTEORDER] == NULL)
>> + return -EINVAL;
>
>> + priv->op = nla_get_u8(tb[NFTA_MATH_OP]);
>
> Can you make it NLA_U32? NLA_U8 doesn't buy anything except
> limiting us to 255 supported options (i don't see a use case
> for ever having so many, but if we ever have we don't need new OP32
> attribute).
Sure, no problems about that. Also NFTA_MATH_LEN? I do not see a U32
bits operation happening in the future tho.
>
> I wonder if we really want this as a module, it seems rather small.
>
By default I thought that a module made sense.. but it is true it is
"general" purpose code and small. I don't really mind.
> I would also be open to just extending bitwise expression with this
> inc/dec, both bitwise & math expr do register manipulations.
While both do register manipulation, I do not think they fit together
from a user perspective. Especially if we extend the number of math
operations in the future.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH RFC nf-next] netfilter: nf_tables: add math expression support
2025-09-23 17:39 ` Fernando Fernandez Mancera
@ 2025-09-23 17:58 ` Florian Westphal
2025-09-24 9:17 ` Fernando Fernandez Mancera
0 siblings, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2025-09-23 17:58 UTC (permalink / raw)
To: Fernando Fernandez Mancera; +Cc: netfilter-devel, coreteam, pablo
Fernando Fernandez Mancera <fmancera@suse.de> wrote:
> > Why? Any particular reason for this?
> >
>
> It is for simplicity reasons. Just to avoid a big payload with byteorder
> conversions per math expression.
Not sold yet. I'd like to hear Pablos opinion.
> > Should it set NFT_BREAK?
> >
> I don't think so. If the user wants to increase or decrease a field but
> it already reached the limit IMO it shouldn't do anything but continue
> with the next expression instead of setting NFT_BREAK. Anyway, not a
> deal breaker for me..
I was just curious. No objections from me.
> > I assume this says 'host' because its limited to 8 bits?
>
> Yes, well it says "host" because I used NFT_MATH_BYTEORDER_HOST to
> generate it, anyway it doesn't matter as it is 8 bits. Would it be
> better to hide byteorder if it doesn't matter?
No, I would prefer simpler code, no need to special case this IMO.
> > AFAICS you need to add support for a displacement
> > offset inside the register to support this (or I should write:
> > work-around-align-fetch-mangling ...)
[..]
> What would be the best way to implement this? A pure bit offset
> (NFT_MATH_OFFSET) or a bitmask (NFT_MATH_BITMASK)?
Bitmask would allow to remove MATH_LEN, correct?
Users that want pure U8 increment can do 0xff000000
resp. 0x000000ff.
Same for U16. So I'd say a mask would be better.
> > Can you make it NLA_U32? NLA_U8 doesn't buy anything except
> > limiting us to 255 supported options (i don't see a use case
> > for ever having so many, but if we ever have we don't need new OP32
> > attribute).
>
> Sure, no problems about that. Also NFTA_MATH_LEN? I do not see a U32
> bits operation happening in the future tho.
Yes, good question. Due to netlink padding neither u8 nor u16 saves
space in the message encoding. I'll leave it up to you, I don't see
2**32 math len making any sense.
> By default I thought that a module made sense.. but it is true it is
> "general" purpose code and small. I don't really mind.
>
> > I would also be open to just extending bitwise expression with this
> > inc/dec, both bitwise & math expr do register manipulations.
>
> While both do register manipulation, I do not think they fit together
> from a user perspective. Especially if we extend the number of math
> operations in the future.
Users don't interact with the expressions directly.
But I understand your point.
Pablo, whats your take?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH RFC nf-next] netfilter: nf_tables: add math expression support
2025-09-23 17:58 ` Florian Westphal
@ 2025-09-24 9:17 ` Fernando Fernandez Mancera
0 siblings, 0 replies; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2025-09-24 9:17 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel, coreteam, pablo
On 9/23/25 7:58 PM, Florian Westphal wrote:
> [..]
>>> AFAICS you need to add support for a displacement
>>> offset inside the register to support this (or I should write:
>>> work-around-align-fetch-mangling ...)
>
> [..]
>
>> What would be the best way to implement this? A pure bit offset
>> (NFT_MATH_OFFSET) or a bitmask (NFT_MATH_BITMASK)?
>
> Bitmask would allow to remove MATH_LEN, correct?
>
> Users that want pure U8 increment can do 0xff000000
> resp. 0x000000ff.
>
> Same for U16. So I'd say a mask would be better.
>
Well, I would prefer to keep the MATH_LEN in order to keep this flexible
in the future for bitfield math operations unless we discard them
completely.
Anyway, I also prefer the bitmask approach.
>>> Can you make it NLA_U32? NLA_U8 doesn't buy anything except
>>> limiting us to 255 supported options (i don't see a use case
>>> for ever having so many, but if we ever have we don't need new OP32
>>> attribute).
>>
>> Sure, no problems about that. Also NFTA_MATH_LEN? I do not see a U32
>> bits operation happening in the future tho.
>
> Yes, good question. Due to netlink padding neither u8 nor u16 saves
> space in the message encoding. I'll leave it up to you, I don't see
> 2**32 math len making any sense.
>
>> By default I thought that a module made sense.. but it is true it is
>> "general" purpose code and small. I don't really mind.
>>
>>> I would also be open to just extending bitwise expression with this
>>> inc/dec, both bitwise & math expr do register manipulations.
>>
>> While both do register manipulation, I do not think they fit together
>> from a user perspective. Especially if we extend the number of math
>> operations in the future.
>
> Users don't interact with the expressions directly.
> But I understand your point.
>
Nft command line tool users do not interact with the expression directly
but libnftnl users do. I have found some users using custom C programs
to configure rules with libnftnl.
It is not common of course, but I think it is good to keep them on mind.
Thanks for all this feedback Florian!
> Pablo, whats your take?
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-09-24 9:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23 15:24 [PATCH RFC nf-next] netfilter: nf_tables: add math expression support Fernando Fernandez Mancera
2025-09-23 16:34 ` Florian Westphal
2025-09-23 17:39 ` Fernando Fernandez Mancera
2025-09-23 17:58 ` Florian Westphal
2025-09-24 9:17 ` Fernando Fernandez Mancera
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.