From 59221eacafbae721c0e46b75c688f1cd0f251afc Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Apr 2015 14:45:40 +0200 Subject: netlink: pass expression to register allocation/release functions Prepare for taking the expression size into account. Signed-off-by: Patrick McHardy --- src/netlink_linearize.c | 54 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'src/netlink_linearize.c') diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index fbc6ae12..beeb0c22 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -30,14 +30,16 @@ static void netlink_put_register(struct nft_rule_expr *nle, nft_rule_expr_set_u32(nle, attr, reg); } -static enum nft_registers get_register(struct netlink_linearize_ctx *ctx) +static enum nft_registers get_register(struct netlink_linearize_ctx *ctx, + const struct expr *expr) { if (ctx->reg_low > NFT_REG_MAX) BUG("register reg_low %u invalid\n", ctx->reg_low); return ctx->reg_low++; } -static void release_register(struct netlink_linearize_ctx *ctx) +static void release_register(struct netlink_linearize_ctx *ctx, + const struct expr *expr) { ctx->reg_low--; } @@ -124,7 +126,7 @@ static void netlink_gen_map(struct netlink_linearize_ctx *ctx, assert(expr->mappings->ops->type == EXPR_SET_REF); if (dreg == NFT_REG_VERDICT) - sreg = get_register(ctx); + sreg = get_register(ctx, expr->map); else sreg = dreg; @@ -139,7 +141,7 @@ static void netlink_gen_map(struct netlink_linearize_ctx *ctx, expr->mappings->set->handle.set_id); if (dreg == NFT_REG_VERDICT) - release_register(ctx); + release_register(ctx, expr->map); nft_rule_add_expr(ctx->nlr, nle); } @@ -154,7 +156,7 @@ static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx, assert(expr->right->ops->type == EXPR_SET_REF); assert(dreg == NFT_REG_VERDICT); - sreg = get_register(ctx); + sreg = get_register(ctx, expr->left); netlink_gen_expr(ctx, expr->left, sreg); nle = alloc_nft_expr("lookup"); @@ -164,7 +166,7 @@ static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx, nft_rule_expr_set_u32(nle, NFT_EXPR_LOOKUP_SET_ID, expr->right->set->handle.set_id); - release_register(ctx); + release_register(ctx, expr->left); nft_rule_add_expr(ctx->nlr, nle); } @@ -206,7 +208,7 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx, if (expr->right->ops->type == EXPR_RANGE) return netlink_gen_range(ctx, expr, dreg); - sreg = get_register(ctx); + sreg = get_register(ctx, expr->left); netlink_gen_expr(ctx, expr->left, sreg); switch (expr->right->ops->type) { @@ -242,7 +244,7 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx, netlink_gen_cmp_op(expr->op)); netlink_gen_data(right, &nld); nft_rule_expr_set(nle, NFT_EXPR_CMP_DATA, nld.value, nld.len); - release_register(ctx); + release_register(ctx, expr->left); nft_rule_add_expr(ctx->nlr, nle); } @@ -258,7 +260,7 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx, assert(dreg == NFT_REG_VERDICT); - sreg = get_register(ctx); + sreg = get_register(ctx, expr->left); netlink_gen_expr(ctx, expr->left, sreg); nle = alloc_nft_expr("cmp"); @@ -301,7 +303,7 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx, nft_rule_expr_set(nle, NFT_EXPR_CMP_DATA, nld.value, nld.len); nft_rule_add_expr(ctx->nlr, nle); - release_register(ctx); + release_register(ctx, expr->left); } static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx, @@ -316,7 +318,7 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx, assert(dreg == NFT_REG_VERDICT); - sreg = get_register(ctx); + sreg = get_register(ctx, expr->left); netlink_gen_expr(ctx, expr->left, sreg); len = div_round_up(expr->left->len, BITS_PER_BYTE); @@ -340,7 +342,7 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx, nft_rule_add_expr(ctx->nlr, nle); mpz_clear(zero); - release_register(ctx); + release_register(ctx, expr->left); } static void netlink_gen_relational(struct netlink_linearize_ctx *ctx, @@ -565,9 +567,9 @@ static void netlink_gen_meta_stmt(struct netlink_linearize_ctx *ctx, struct nft_rule_expr *nle; enum nft_registers sreg; - sreg = get_register(ctx); + sreg = get_register(ctx, stmt->meta.expr); netlink_gen_expr(ctx, stmt->meta.expr, sreg); - release_register(ctx); + release_register(ctx, stmt->meta.expr); nle = alloc_nft_expr("meta"); netlink_put_register(nle, NFT_EXPR_META_SREG, sreg); @@ -647,11 +649,11 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx, nft_rule_expr_set_u32(nle, NFT_EXPR_NAT_FLAGS, stmt->nat.flags); if (stmt->nat.addr) { - amin_reg = get_register(ctx); + amin_reg = get_register(ctx, NULL); registers++; if (stmt->nat.addr->ops->type == EXPR_RANGE) { - amax_reg = get_register(ctx); + amax_reg = get_register(ctx, NULL); registers++; netlink_gen_expr(ctx, stmt->nat.addr->left, amin_reg); @@ -669,11 +671,11 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx, } if (stmt->nat.proto) { - pmin_reg = get_register(ctx); + pmin_reg = get_register(ctx, NULL); registers++; if (stmt->nat.proto->ops->type == EXPR_RANGE) { - pmax_reg = get_register(ctx); + pmax_reg = get_register(ctx, NULL); registers++; netlink_gen_expr(ctx, stmt->nat.proto->left, pmin_reg); @@ -690,7 +692,7 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx, } while (registers > 0) { - release_register(ctx); + release_register(ctx, NULL); registers--; } @@ -724,11 +726,11 @@ static void netlink_gen_redir_stmt(struct netlink_linearize_ctx *ctx, stmt->redir.flags); if (stmt->redir.proto) { - pmin_reg = get_register(ctx); + pmin_reg = get_register(ctx, NULL); registers++; if (stmt->redir.proto->ops->type == EXPR_RANGE) { - pmax_reg = get_register(ctx); + pmax_reg = get_register(ctx, NULL); registers++; netlink_gen_expr(ctx, stmt->redir.proto->left, @@ -750,7 +752,7 @@ static void netlink_gen_redir_stmt(struct netlink_linearize_ctx *ctx, } while (registers > 0) { - release_register(ctx); + release_register(ctx, NULL); registers--; } @@ -791,9 +793,9 @@ static void netlink_gen_ct_stmt(struct netlink_linearize_ctx *ctx, struct nft_rule_expr *nle; enum nft_registers sreg; - sreg = get_register(ctx); + sreg = get_register(ctx, stmt->ct.expr); netlink_gen_expr(ctx, stmt->ct.expr, sreg); - release_register(ctx); + release_register(ctx, stmt->ct.expr); nle = alloc_nft_expr("ct"); netlink_put_register(nle, NFT_EXPR_CT_SREG, sreg); @@ -807,9 +809,9 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, struct nft_rule_expr *nle; enum nft_registers sreg_key; - sreg_key = get_register(ctx); + sreg_key = get_register(ctx, stmt->set.key); netlink_gen_expr(ctx, stmt->set.key, sreg_key); - release_register(ctx); + release_register(ctx, stmt->set.key); nle = alloc_nft_expr("dynset"); netlink_put_register(nle, NFT_EXPR_DYNSET_SREG_KEY, sreg_key); -- cgit v1.2.3 From 9c286f2d689bbc19889d2f3b69923ad68831b3e7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 12 Apr 2015 21:10:41 +0100 Subject: netlink_linearize: use NFT_REG32 values internally Prepare netlink_linearize for 32 bit register usage: Switch to use 16 data registers of 32 bit each. A helper function takes care of mapping the registers to the NFT_REG32 values and, if the register refers to the beginning of an 128 bit area, the old NFT_REG_1-4 values for compatibility. New register reservation and release helper function take the size into account and reserve the required amount of registers. The reservation and release functions will so far still always allocate 128 bit. If no other expression in a rule uses a 32 bit register directly, these will be mapped to the old register values, meaning everything continues to work with old kernel versions. Signed-off-by: Patrick McHardy --- src/netlink_linearize.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'src/netlink_linearize.c') diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index beeb0c22..6930b39d 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -27,21 +27,54 @@ struct netlink_linearize_ctx { static void netlink_put_register(struct nft_rule_expr *nle, uint32_t attr, uint32_t reg) { + /* Convert to 128 bit register numbers if possible for compatibility */ + if (reg != NFT_REG_VERDICT) { + reg -= NFT_REG_1; + if (reg % (NFT_REG_SIZE / NFT_REG32_SIZE) == 0) + reg = NFT_REG_1 + reg / (NFT_REG_SIZE / NFT_REG32_SIZE); + else + reg += NFT_REG32_00; + } + nft_rule_expr_set_u32(nle, attr, reg); } +static enum nft_registers __get_register(struct netlink_linearize_ctx *ctx, + unsigned int size) +{ + unsigned int reg, n; + + n = netlink_register_space(size); + if (ctx->reg_low + n > NFT_REG_1 + NFT_REG32_15 - NFT_REG32_00 + 1) + BUG("register reg_low %u invalid\n", ctx->reg_low); + + reg = ctx->reg_low; + ctx->reg_low += n; + return reg; +} + +static void __release_register(struct netlink_linearize_ctx *ctx, + unsigned int size) +{ + unsigned int n; + + n = netlink_register_space(size); + if (ctx->reg_low < NFT_REG_1 + n) + BUG("register reg_low %u invalid\n", ctx->reg_low); + + ctx->reg_low -= n; +} + static enum nft_registers get_register(struct netlink_linearize_ctx *ctx, const struct expr *expr) { - if (ctx->reg_low > NFT_REG_MAX) - BUG("register reg_low %u invalid\n", ctx->reg_low); - return ctx->reg_low++; + return __get_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); } static void release_register(struct netlink_linearize_ctx *ctx, const struct expr *expr) { - ctx->reg_low--; + __release_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); } static void netlink_gen_expr(struct netlink_linearize_ctx *ctx, @@ -509,6 +542,8 @@ static void netlink_gen_expr(struct netlink_linearize_ctx *ctx, const struct expr *expr, enum nft_registers dreg) { + assert(dreg < ctx->reg_low); + switch (expr->ops->type) { case EXPR_VERDICT: case EXPR_VALUE: -- cgit v1.2.3 From 1e4bf9dbb9218030ce9a5ee0b30eb33f918ca6bf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 13 Apr 2015 12:19:12 +0100 Subject: netlink_linearize: generate concat expressions Use the real length for reserving/releasing registers when generating concat expressions. Signed-off-by: Patrick McHardy --- src/netlink_linearize.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/netlink_linearize.c') diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 6930b39d..bf1e56be 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -68,13 +68,19 @@ static void __release_register(struct netlink_linearize_ctx *ctx, static enum nft_registers get_register(struct netlink_linearize_ctx *ctx, const struct expr *expr) { - return __get_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); + if (expr && expr->ops->type == EXPR_CONCAT) + return __get_register(ctx, expr->len); + else + return __get_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); } static void release_register(struct netlink_linearize_ctx *ctx, const struct expr *expr) { - __release_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); + if (expr && expr->ops->type == EXPR_CONCAT) + __release_register(ctx, expr->len); + else + __release_register(ctx, NFT_REG_SIZE * BITS_PER_BYTE); } static void netlink_gen_expr(struct netlink_linearize_ctx *ctx, @@ -87,8 +93,10 @@ static void netlink_gen_concat(struct netlink_linearize_ctx *ctx, { const struct expr *i; - list_for_each_entry(i, &expr->expressions, list) + list_for_each_entry(i, &expr->expressions, list) { netlink_gen_expr(ctx, i, dreg); + dreg += netlink_register_space(i->len); + } } static void netlink_gen_payload(struct netlink_linearize_ctx *ctx, -- cgit v1.2.3