summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-01-11 16:30:23 +0100
committerFlorian Westphal <fw@strlen.de>2018-03-17 01:47:18 +0100
commit48632359f4dea5ee2484debba498ba069229e6d0 (patch)
treee47b6d1e6fbef60850855029dcf188c5770f3c32 /src
parentccf7c4fc9af2b982c24a7a3b40ecc5ebbe93ecef (diff)
src: evaluate: add preliminary binop transfer support for vmaps
nftables doesn't support vmap with bit-sized headers, such as flow label or dscp: nft add rule ip filter input ip dscp vmap \{ 4 : accept, 63 : continue \} BUG: invalid binary operation 5 Unlike plain "ip dscp { 4, 63 }", we don't have a relational operation in case of vmap. Binop fixups need to be done when evaluating map statements. This patch is incomplete. 'ip dscp' works, but this won't: nft add rule --debug=netlink ip6 test-ip6 input ip6 dscp vmap { 0x04 : accept, 0x3f : continue } The generated expressions look sane, however there is disagreement on the sets key size vs. the sizes of the individual elements in the set. This is because ip6 dscp spans a byte boundary. Key set size is still set to one byte (dscp type is 6bits). However, binop expansion requirements result in 2 byte loads, i.e. set members will be 2 bytes in size as well. This can hopefully get addressed in an incremental patch. Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 46ac9e43..8de5e48d 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1242,6 +1242,7 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
return 0;
}
+static int binop_transfer(struct eval_ctx *ctx, struct expr **expr);
static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
{
struct expr_ctx ectx = ctx->ectx;
@@ -1277,8 +1278,12 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
ctx->set = mappings->set;
if (expr_evaluate(ctx, &map->mappings->set->init) < 0)
return -1;
- ctx->set = NULL;
+ expr_set_context(&ctx->ectx, ctx->set->key->dtype, ctx->set->key->len);
+ if (binop_transfer(ctx, expr) < 0)
+ return -1;
+ map = *expr;
+ ctx->set = NULL;
map->mappings->set->flags |= map->mappings->set->init->set_flags;
break;
case EXPR_SYMBOL:
@@ -1408,6 +1413,8 @@ static int binop_can_transfer(struct eval_ctx *ctx,
switch (right->ops->type) {
case EXPR_VALUE:
break;
+ case EXPR_SET_ELEM:
+ return binop_can_transfer(ctx, left, right->key);
case EXPR_RANGE:
err = binop_can_transfer(ctx, left, right->left);
if (err <= 0)
@@ -1442,6 +1449,8 @@ static int binop_transfer_one(struct eval_ctx *ctx,
switch ((*right)->ops->type) {
case EXPR_VALUE:
break;
+ case EXPR_SET_ELEM:
+ return binop_transfer_one(ctx, left, &(*right)->key);
case EXPR_RANGE:
err = binop_transfer_one(ctx, left, &(*right)->left);
if (err < 0)
@@ -1516,6 +1525,7 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr)
switch (i->key->ops->type) {
case EXPR_VALUE:
case EXPR_RANGE:
+ case EXPR_SET_ELEM:
err = binop_can_transfer(ctx, left, i->key);
if (err <= 0)
return err;
@@ -1530,6 +1540,7 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr)
switch (i->key->ops->type) {
case EXPR_VALUE:
case EXPR_RANGE:
+ case EXPR_SET_ELEM:
if (binop_transfer_one(ctx, left, &i->key) < 0)
return -1;
break;