@@ -128,6 +128,7 @@ enum {
NFTNL_EXPR_BITWISE_XOR,
NFTNL_EXPR_BITWISE_OP,
NFTNL_EXPR_BITWISE_DATA,
+ NFTNL_EXPR_BITWISE_NBITS,
};
enum {
@@ -29,6 +29,7 @@ struct nftnl_expr_bitwise {
union nftnl_data_reg mask;
union nftnl_data_reg xor;
union nftnl_data_reg data;
+ unsigned int nbits;
};
static int
@@ -62,6 +63,9 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type,
memcpy(&bitwise->data.val, data, data_len);
bitwise->data.len = data_len;
break;
+ case NFTNL_EXPR_BITWISE_NBITS:
+ memcpy(&bitwise->nbits, data, sizeof(bitwise->nbits));
+ break;
default:
return -1;
}
@@ -96,6 +100,9 @@ nftnl_expr_bitwise_get(const struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_BITWISE_DATA:
*data_len = bitwise->data.len;
return &bitwise->data.val;
+ case NFTNL_EXPR_BITWISE_NBITS:
+ *data_len = sizeof(bitwise->nbits);
+ return &bitwise->nbits;
}
return NULL;
}
@@ -113,6 +120,7 @@ static int nftnl_expr_bitwise_cb(const struct nlattr *attr, void *data)
case NFTA_BITWISE_DREG:
case NFTA_BITWISE_OP:
case NFTA_BITWISE_LEN:
+ case NFTA_BITWISE_NBITS:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -141,6 +149,9 @@ nftnl_expr_bitwise_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
mnl_attr_put_u32(nlh, NFTA_BITWISE_OP, htonl(bitwise->op));
if (e->flags & (1 << NFTNL_EXPR_BITWISE_LEN))
mnl_attr_put_u32(nlh, NFTA_BITWISE_LEN, htonl(bitwise->len));
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_NBITS))
+ mnl_attr_put_u32(nlh, NFTA_BITWISE_NBITS,
+ htonl(bitwise->nbits));
if (e->flags & (1 << NFTNL_EXPR_BITWISE_MASK)) {
struct nlattr *nest;
@@ -205,6 +216,10 @@ nftnl_expr_bitwise_parse(struct nftnl_expr *e, struct nlattr *attr)
ret = nftnl_parse_data(&bitwise->data, tb[NFTA_BITWISE_DATA], NULL);
e->flags |= (1 << NFTNL_EXPR_BITWISE_DATA);
}
+ if (tb[NFTA_BITWISE_NBITS]) {
+ bitwise->nbits = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_NBITS]));
+ e->flags |= (1 << NFTNL_EXPR_BITWISE_NBITS);
+ }
return ret;
}
@@ -45,6 +45,9 @@ static void cmp_nftnl_expr_bool(struct nftnl_expr *rule_a,
if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
print_err("bool", "Expr BITWISE_LEN mismatches");
+ if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_NBITS) !=
+ nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_NBITS))
+ print_err("bool", "Expr BITWISE_NBITS mismatches");
nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_MASK, &maska);
nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_MASK, &maskb);
if (maska != maskb)
@@ -72,6 +75,9 @@ static void cmp_nftnl_expr_lshift(struct nftnl_expr *rule_a,
if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
print_err("lshift", "Expr BITWISE_LEN mismatches");
+ if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_NBITS) !=
+ nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_NBITS))
+ print_err("lshift", "Expr BITWISE_NBITS mismatches");
nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_DATA, &data_a);
nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_DATA, &data_b);
if (data_a != data_b)
@@ -95,6 +101,9 @@ static void cmp_nftnl_expr_rshift(struct nftnl_expr *rule_a,
if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_LEN) !=
nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_LEN))
print_err("rshift", "Expr BITWISE_LEN mismatches");
+ if (nftnl_expr_get_u16(rule_a, NFTNL_EXPR_BITWISE_NBITS) !=
+ nftnl_expr_get_u16(rule_b, NFTNL_EXPR_BITWISE_NBITS))
+ print_err("rshift", "Expr BITWISE_NBITS mismatches");
nftnl_expr_get(rule_a, NFTNL_EXPR_BITWISE_DATA, &data_a);
nftnl_expr_get(rule_b, NFTNL_EXPR_BITWISE_DATA, &data_b);
if (data_a != data_b)
@@ -124,6 +133,7 @@ static void test_bool(void)
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_OP, NFT_BITWISE_BOOL);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_LEN, 0x56781234);
+ nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_NBITS, 0x11223344);
nftnl_expr_set(ex, NFTNL_EXPR_BITWISE_MASK, &mask, sizeof(mask));
nftnl_expr_set(ex, NFTNL_EXPR_BITWISE_XOR, &xor, sizeof(xor));
@@ -179,6 +189,7 @@ static void test_lshift(void)
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_OP, NFT_BITWISE_LSHIFT);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_LEN, 0x56781234);
+ nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_NBITS, 0x11223344);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DATA, 13);
nftnl_rule_add_expr(a, ex);
@@ -233,6 +244,7 @@ static void test_rshift(void)
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DREG, 0x78123456);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_OP, NFT_BITWISE_RSHIFT);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_LEN, 0x56781234);
+ nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_NBITS, 0x11223344);
nftnl_expr_set_u32(ex, NFTNL_EXPR_BITWISE_DATA, 17);
nftnl_rule_add_expr(a, ex);
The kernel can now keep track of the bit-length of bitwise operations in order to help user space eliminate generated operations during delinearization. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> --- include/libnftnl/expr.h | 1 + src/expr/bitwise.c | 15 +++++++++++++++ tests/nft-expr_bitwise-test.c | 12 ++++++++++++ 3 files changed, 28 insertions(+)