* [PATCH nf-next v3] netfilter: nf_tables: add math expression support
@ 2026-02-04 15:23 Fernando Fernandez Mancera
2026-02-04 16:07 ` Phil Sutter
0 siblings, 1 reply; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2026-02-04 15:23 UTC (permalink / raw)
To: netfilter-devel; +Cc: coreteam, fw, pablo, phil, 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.
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.
When loading a u8 or u16 payload into a register we don't know if the
value is stored at least significant byte or most significant byte. In
order to handle such cases, introduce a bitmask indicating what is the
target bit and also use it to handle limits to prevent overflow.
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 filter inet flags 0 use 1 handle 3
inet filter input use 1 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1
inet filter input 4
[ payload load 2b @ network header + 8 => reg 1 ]
[ math 8 bits mask 0x000000ff 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 filter inet flags 0 use 1 handle 3
inet filter input use 1 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1
inet filter input 4
[ payload load 2b @ network header + 8 => reg 1 ]
[ math 8 bits mask 0x000000ff 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 32 bits reg 1 + 1 => 1]
[ meta set mark with reg 1 ]
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
v2: dropped the byteorder netlink attribute, added bitmask to handle
LSB/MSB when dealing with u8 and u16, simplified eval logic. I've kept
nft_math as module, IMHO it would be too much to make it built-in.
v3: fixed checkpatch warnings, improved Kconfig description and fixed a
wrong EINVAL return.
---
include/uapi/linux/netfilter/nf_tables.h | 27 +++
net/netfilter/Kconfig | 9 +
net/netfilter/Makefile | 1 +
net/netfilter/nft_math.c | 201 +++++++++++++++++++++++
4 files changed, 238 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 45c71f7d21c2..e0a0c7cae1b5 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -2015,4 +2015,31 @@ 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_U32)
+ * @NFTA_MATH_BITMASK: bitmask to be applied on the operation (NLA_U32)
+ * @NFTA_MATH_LEN: value length in bits (NLA_U32)
+ */
+enum nft_math_attributes {
+ NFTA_MATH_UNSPEC,
+ NFTA_MATH_SREG,
+ NFTA_MATH_DREG,
+ NFTA_MATH_OP,
+ NFTA_MATH_BITMASK,
+ NFTA_MATH_LEN,
+ __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)
+
#endif /* _LINUX_NF_TABLES_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 6cdc994fdc8a..4a0f6e037c61 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -671,6 +671,15 @@ 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
+ This option enables support for the nftables math expression.
+ It allows arithmetic operation to be performed on nft registers,
+ such as incrementing or decrementing values. Math expressions
+ can be used in nftables rules to modify packet fields.
+
if NF_TABLES_NETDEV
config NF_DUP_NETDEV
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 6bfc250e474f..fe25b1d1ce0a 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..dd0022dc5f56
--- /dev/null
+++ b/net/netfilter/nft_math.c
@@ -0,0 +1,201 @@
+// 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;
+ u32 len;
+ u32 bitmask;
+ enum nft_math_op op;
+};
+
+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_U32 },
+ [NFTA_MATH_BITMASK] = { .type = NLA_U32 },
+ [NFTA_MATH_LEN] = NLA_POLICY_MIN(NLA_U32, 8),
+};
+
+static void nft_math_eval_bitmask(u32 *src, u32 *dst,
+ const struct nft_math *priv)
+{
+ u32 target, keep, bit_unit;
+
+ target = *src & priv->bitmask;
+ keep = *src & ~priv->bitmask;
+ bit_unit = priv->bitmask & -priv->bitmask;
+
+ switch (priv->op) {
+ case NFT_MATH_OP_INC:
+ if (target == priv->bitmask) {
+ *dst = *src;
+ break;
+ }
+
+ target = target + bit_unit;
+ *dst = target | keep;
+ break;
+ case NFT_MATH_OP_DEC:
+ if (!target) {
+ *dst = *src;
+ break;
+ }
+
+ target = target - bit_unit;
+ *dst = target | keep;
+ break;
+ default:
+ break;
+ }
+}
+
+static void nft_math_eval_u32(uint32_t *src, uint32_t *dst,
+ const struct nft_math *priv)
+{
+ switch (priv->op) {
+ case NFT_MATH_OP_INC:
+ if (*src != U32_MAX)
+ *dst = *src + 1;
+ else
+ *dst = *src;
+ break;
+ case NFT_MATH_OP_DEC:
+ if (*src != 0)
+ *dst = *src - 1;
+ else
+ *dst = *src;
+ 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 32:
+ nft_math_eval_u32(src, dst, priv);
+ break;
+ default:
+ nft_math_eval_bitmask(src, dst, priv);
+ 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)
+ return -EINVAL;
+
+ priv->op = ntohl(nla_get_u32(tb[NFTA_MATH_OP]));
+ priv->len = ntohl(nla_get_u32(tb[NFTA_MATH_LEN]));
+
+ if (tb[NFTA_MATH_BITMASK])
+ priv->bitmask = ntohl(nla_get_u32(tb[NFTA_MATH_BITMASK]));
+
+ if (priv->op > NFT_MATH_OP_MAX)
+ return -EOPNOTSUPP;
+
+ switch (priv->len) {
+ case 8:
+ if (!priv->bitmask)
+ priv->bitmask = 0xff;
+ if (priv->bitmask != 0xff && priv->bitmask != 0xff000000)
+ return -EINVAL;
+ break;
+ case 16:
+ if (!priv->bitmask)
+ priv->bitmask = 0xffff;
+ if (priv->bitmask != 0xffff && priv->bitmask != 0xffff0000)
+ return -EINVAL;
+ break;
+ 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 (priv->bitmask &&
+ nla_put_u32(skb, NFTA_MATH_BITMASK, htonl(priv->bitmask)))
+ goto nla_put_failure;
+ if (nla_put_u32(skb, NFTA_MATH_OP, htonl(priv->op)))
+ goto nla_put_failure;
+ if (nla_put_u32(skb, NFTA_MATH_LEN, htonl(priv->len)))
+ 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.52.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH nf-next v3] netfilter: nf_tables: add math expression support
2026-02-04 15:23 [PATCH nf-next v3] netfilter: nf_tables: add math expression support Fernando Fernandez Mancera
@ 2026-02-04 16:07 ` Phil Sutter
2026-02-04 16:44 ` Fernando Fernandez Mancera
0 siblings, 1 reply; 5+ messages in thread
From: Phil Sutter @ 2026-02-04 16:07 UTC (permalink / raw)
To: Fernando Fernandez Mancera; +Cc: netfilter-devel, coreteam, fw, pablo
Hi Fernando,
On Wed, Feb 04, 2026 at 04:23:58PM +0100, Fernando Fernandez Mancera wrote:
> 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.
>
> 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.
>
> When loading a u8 or u16 payload into a register we don't know if the
> value is stored at least significant byte or most significant byte. In
> order to handle such cases, introduce a bitmask indicating what is the
> target bit and also use it to handle limits to prevent overflow.
This part puzzles me. IMO byteorder conversion is needed for arithmetic
on multi-byte values in non-host byte order.
Since nftables only knows host byte order and network byte order, the
only case to consider is Little Endian host with NBO data. Registers are
filled "from left to right", so (u16)0x1337 and (u32)0xfeedbabe look
like this when stored in Network Byte Order in registers:
{ 0x13, 0x37, 0x00, 0x00 }
{ 0xfe, 0xed, 0xba, 0xbe }
Interpreting those buffers as u16/u32 on Little Endian results in values
0x3713 and 0xbebaedfe. Any increment/decrement on those values leads to
wrong results.
Maybe there's a hidden secret in 'bit_unit', but even if you calculate
the right value to add/subtract from the right byte (0x100 and 0x1000000
in our examples), a possible carry-over bumps the wrong byte.
Assuming that I didn't entirely miss the point you might want to have a
look at recent libnftnl/nftables commits informing libnftnl of payload
byteorder for host byteorder independent debug output (with correct
values). Particularly interesting are nftnl_*_set_imm() functions. Maybe
this allows you to annotate math expression with data byteorder so it
may perform byteorder conversion as needed.
Cheers, Phil
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH nf-next v3] netfilter: nf_tables: add math expression support
2026-02-04 16:07 ` Phil Sutter
@ 2026-02-04 16:44 ` Fernando Fernandez Mancera
2026-02-04 17:23 ` Phil Sutter
0 siblings, 1 reply; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2026-02-04 16:44 UTC (permalink / raw)
To: Phil Sutter, netfilter-devel, coreteam, fw, pablo
On 2/4/26 5:07 PM, Phil Sutter wrote:
> Hi Fernando,
>
> On Wed, Feb 04, 2026 at 04:23:58PM +0100, Fernando Fernandez Mancera wrote:
>> 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.
>>
>> 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.
>>
>> When loading a u8 or u16 payload into a register we don't know if the
>> value is stored at least significant byte or most significant byte. In
>> order to handle such cases, introduce a bitmask indicating what is the
>> target bit and also use it to handle limits to prevent overflow.
>
> This part puzzles me. IMO byteorder conversion is needed for arithmetic
> on multi-byte values in non-host byte order.
>
> Since nftables only knows host byte order and network byte order, the
> only case to consider is Little Endian host with NBO data. Registers are
> filled "from left to right", so (u16)0x1337 and (u32)0xfeedbabe look
> like this when stored in Network Byte Order in registers:
>
> { 0x13, 0x37, 0x00, 0x00 }
> { 0xfe, 0xed, 0xba, 0xbe }
>
> Interpreting those buffers as u16/u32 on Little Endian results in values
> 0x3713 and 0xbebaedfe. Any increment/decrement on those values leads to
> wrong results.
>
> Maybe there's a hidden secret in 'bit_unit', but even if you calculate
> the right value to add/subtract from the right byte (0x100 and 0x1000000
> in our examples), a possible carry-over bumps the wrong byte.
>
Hi!
This is correct. In the initial implementation [1] I included a
NFTA_MATH_BYTEORDER attribute but after discussing with Florian we
decided to drop it. Of course, in order to make this work correctly, nft
byteorder expression must be used to perform the conversion when needed.
I believe that nft command line tool can figure out when a byteorder
conversion is needed as I noticed this is already done for other
expressions.
My initial idea was to keep the bytecode as smaller as possible but it
is true that it makes sense to use the existing byteorder operations.
Does this make sense or am I missing something?
Thanks for the feedback!
[1]
https://lore.kernel.org/netfilter-devel/20250923152452.3618-1-fmancera@suse.de/
> Assuming that I didn't entirely miss the point you might want to have a
> look at recent libnftnl/nftables commits informing libnftnl of payload
> byteorder for host byteorder independent debug output (with correct
> values). Particularly interesting are nftnl_*_set_imm() functions. Maybe
> this allows you to annotate math expression with data byteorder so it
> may perform byteorder conversion as needed.
>
> Cheers, Phil
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH nf-next v3] netfilter: nf_tables: add math expression support
2026-02-04 16:44 ` Fernando Fernandez Mancera
@ 2026-02-04 17:23 ` Phil Sutter
2026-02-09 12:14 ` Fernando Fernandez Mancera
0 siblings, 1 reply; 5+ messages in thread
From: Phil Sutter @ 2026-02-04 17:23 UTC (permalink / raw)
To: Fernando Fernandez Mancera; +Cc: netfilter-devel, coreteam, fw, pablo
On Wed, Feb 04, 2026 at 05:44:14PM +0100, Fernando Fernandez Mancera wrote:
> On 2/4/26 5:07 PM, Phil Sutter wrote:
> > Hi Fernando,
> >
> > On Wed, Feb 04, 2026 at 04:23:58PM +0100, Fernando Fernandez Mancera wrote:
> >> 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.
> >>
> >> 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.
> >>
> >> When loading a u8 or u16 payload into a register we don't know if the
> >> value is stored at least significant byte or most significant byte. In
> >> order to handle such cases, introduce a bitmask indicating what is the
> >> target bit and also use it to handle limits to prevent overflow.
> >
> > This part puzzles me. IMO byteorder conversion is needed for arithmetic
> > on multi-byte values in non-host byte order.
> >
> > Since nftables only knows host byte order and network byte order, the
> > only case to consider is Little Endian host with NBO data. Registers are
> > filled "from left to right", so (u16)0x1337 and (u32)0xfeedbabe look
> > like this when stored in Network Byte Order in registers:
> >
> > { 0x13, 0x37, 0x00, 0x00 }
> > { 0xfe, 0xed, 0xba, 0xbe }
> >
> > Interpreting those buffers as u16/u32 on Little Endian results in values
> > 0x3713 and 0xbebaedfe. Any increment/decrement on those values leads to
> > wrong results.
> >
> > Maybe there's a hidden secret in 'bit_unit', but even if you calculate
> > the right value to add/subtract from the right byte (0x100 and 0x1000000
> > in our examples), a possible carry-over bumps the wrong byte.
> >
>
> Hi!
>
> This is correct. In the initial implementation [1] I included a
> NFTA_MATH_BYTEORDER attribute but after discussing with Florian we
> decided to drop it. Of course, in order to make this work correctly, nft
> byteorder expression must be used to perform the conversion when needed.
>
> I believe that nft command line tool can figure out when a byteorder
> conversion is needed as I noticed this is already done for other
> expressions.
>
> My initial idea was to keep the bytecode as smaller as possible but it
> is true that it makes sense to use the existing byteorder operations.
>
> Does this make sense or am I missing something?
Ah, got it! So nft_math simply assumes sreg and dreg are in host byte
order and nftables is supposed to add nft_byteorder expressions as
needed. That should do and is indeed easier than dealing with data
byteorder within nft_math itself!
The only odd thing that remains is the combined use of mask and length.
Typically one would either use length and offset or mask alone because
the former two values may be extracted from the latter. Also, why does
nft_math_init() restrict masks to align at start or end of register?
Thanks, Phil
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH nf-next v3] netfilter: nf_tables: add math expression support
2026-02-04 17:23 ` Phil Sutter
@ 2026-02-09 12:14 ` Fernando Fernandez Mancera
0 siblings, 0 replies; 5+ messages in thread
From: Fernando Fernandez Mancera @ 2026-02-09 12:14 UTC (permalink / raw)
To: Phil Sutter, netfilter-devel, coreteam, fw, pablo
On 2/4/26 6:23 PM, Phil Sutter wrote:
> On Wed, Feb 04, 2026 at 05:44:14PM +0100, Fernando Fernandez Mancera wrote:
>> On 2/4/26 5:07 PM, Phil Sutter wrote:
>>> Hi Fernando,
>>>
>>> On Wed, Feb 04, 2026 at 04:23:58PM +0100, Fernando Fernandez Mancera wrote:
>>>> 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.
>>>>
>>>> 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.
>>>>
>>>> When loading a u8 or u16 payload into a register we don't know if the
>>>> value is stored at least significant byte or most significant byte. In
>>>> order to handle such cases, introduce a bitmask indicating what is the
>>>> target bit and also use it to handle limits to prevent overflow.
>>>
>>> This part puzzles me. IMO byteorder conversion is needed for arithmetic
>>> on multi-byte values in non-host byte order.
>>>
>>> Since nftables only knows host byte order and network byte order, the
>>> only case to consider is Little Endian host with NBO data. Registers are
>>> filled "from left to right", so (u16)0x1337 and (u32)0xfeedbabe look
>>> like this when stored in Network Byte Order in registers:
>>>
>>> { 0x13, 0x37, 0x00, 0x00 }
>>> { 0xfe, 0xed, 0xba, 0xbe }
>>>
>>> Interpreting those buffers as u16/u32 on Little Endian results in values
>>> 0x3713 and 0xbebaedfe. Any increment/decrement on those values leads to
>>> wrong results.
>>>
>>> Maybe there's a hidden secret in 'bit_unit', but even if you calculate
>>> the right value to add/subtract from the right byte (0x100 and 0x1000000
>>> in our examples), a possible carry-over bumps the wrong byte.
>>>
>>
>> Hi!
>>
>> This is correct. In the initial implementation [1] I included a
>> NFTA_MATH_BYTEORDER attribute but after discussing with Florian we
>> decided to drop it. Of course, in order to make this work correctly, nft
>> byteorder expression must be used to perform the conversion when needed.
>>
>> I believe that nft command line tool can figure out when a byteorder
>> conversion is needed as I noticed this is already done for other
>> expressions.
>>
>> My initial idea was to keep the bytecode as smaller as possible but it
>> is true that it makes sense to use the existing byteorder operations.
>>
>> Does this make sense or am I missing something?
>
> Ah, got it! So nft_math simply assumes sreg and dreg are in host byte
> order and nftables is supposed to add nft_byteorder expressions as
> needed. That should do and is indeed easier than dealing with data
> byteorder within nft_math itself!
>
> The only odd thing that remains is the combined use of mask and length.
> Typically one would either use length and offset or mask alone because
> the former two values may be extracted from the latter. Also, why does
> nft_math_init() restrict masks to align at start or end of register?
>
Hm. I have been thinking about this. So the initial reason for this was
to simplify everything so if u32 length is used we don't need to use a
bitmask. But tbh, it doesn't make much sense.
I will get rid of the length attribute on the v4. Thank you Phil! :)
> Thanks, Phil
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-09 12:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 15:23 [PATCH nf-next v3] netfilter: nf_tables: add math expression support Fernando Fernandez Mancera
2026-02-04 16:07 ` Phil Sutter
2026-02-04 16:44 ` Fernando Fernandez Mancera
2026-02-04 17:23 ` Phil Sutter
2026-02-09 12:14 ` 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.