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>
sreg2 = get_register(ctx, expr->right);
netlink_gen_expr(ctx, expr->right, sreg2);
netlink_put_register(nle, NFTNL_EXPR_BITWISE_SREG2, sreg2);
+ release_register(ctx, expr->right);
len = div_round_up(expr->len, BITS_PER_BYTE);
nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 };ok
!map1 typeof vlan id : meta mark;ok
meta mark set vlan id map @map1;ok
+
+meta mark set meta mark | iif | meta cpu;ok
}
]
+# meta mark set meta mark | iif | meta cpu
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ {
+ "meta": {
+ "key": "iif"
+ }
+ },
+ {
+ "meta": {
+ "key": "cpu"
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
[ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
[ lookup reg 1 set map1 dreg 1 ]
[ meta set mark with reg 1 ]
+
+# meta mark set meta mark | iif | meta cpu
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ meta load iif => reg 2 ]
+ [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
+ [ meta load cpu => reg 2 ]
+ [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
+ [ meta set mark with reg 1 ]