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@xxxxxxxxxx> --- include/libnftnl/expr.h | 1 + src/expr/bitwise.c | 15 +++++++++++++++ tests/nft-expr_bitwise-test.c | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h index 00c63ab9d19b..6adad4c222a6 100644 --- a/include/libnftnl/expr.h +++ b/include/libnftnl/expr.h @@ -128,6 +128,7 @@ enum { NFTNL_EXPR_BITWISE_XOR, NFTNL_EXPR_BITWISE_OP, NFTNL_EXPR_BITWISE_DATA, + NFTNL_EXPR_BITWISE_NBITS, }; enum { diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c index d0c7827eacec..3fa627d7905d 100644 --- a/src/expr/bitwise.c +++ b/src/expr/bitwise.c @@ -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; } diff --git a/tests/nft-expr_bitwise-test.c b/tests/nft-expr_bitwise-test.c index f134728fdd86..9d01376a69bd 100644 --- a/tests/nft-expr_bitwise-test.c +++ b/tests/nft-expr_bitwise-test.c @@ -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); -- 2.35.1