]> git.ipfire.org Git - thirdparty/nftables.git/commit
netlink_linearize: reduce register waste with non-constant binop expressions
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 10 Mar 2025 19:11:44 +0000 (20:11 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 10 Mar 2025 20:28:56 +0000 (21:28 +0100)
commit9a8b7abd0bf6c1ddf17145b6b96916ad05bdd6af
treeebfd8d733e99549dd116629e95822e2e84a9655d
parentf6d9610c86ce6f1b8618611e3c993970760bc03d
netlink_linearize: reduce register waste with non-constant binop expressions

Register use is not good with bitwise operations that involve three or
more selectors, eg.

 mark set ip dscp and 0x3 or ct mark or meta mark
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
  [ ct load mark => reg 2 ]
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta load mark => reg 3 ]   <--- this could use register 2 instead!
  [ bitwise reg 1 = ( reg 1 | reg 3 ) ]
  [ meta set mark with reg 1 ]

register 3 is used to store meta mark, however, register 2 can be
already use since register 1 already stores the partial result of the
bitwise operation for this expression.

After this fix:

  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
  [ ct load mark => reg 2 ]
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta load mark => reg 2 ]            <--- recycle register 2
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta set mark with reg 1 ]

Release source register in bitwise operation given destination register
already stores the partial result of the expression.

Extend tests/py to cover this.

Fixes: 54bfc38c522b ("src: allow binop expressions with variable right-hand operands")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink_linearize.c
tests/py/any/meta.t
tests/py/any/meta.t.json
tests/py/any/meta.t.payload