summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-07-16 19:03:55 +0200
committerFlorian Westphal <fw@strlen.de>2019-12-16 17:06:18 +0100
commit343a51702656a6476e37cfb84609a82155c7fc5e (patch)
tree10ce1fa0bf256982709d8a89c4a52cb1a8f9cfe3 /src/evaluate.c
parent10f114806ccd9d64f9d72eaa813babb04d719688 (diff)
src: store expr, not dtype to track data in sets
This will be needed once we add support for the 'typeof' keyword to handle maps that could e.g. store 'ct helper' "type" values. Instead of: set foo { type ipv4_addr . mark; this would allow set foo { typeof(ip saddr) . typeof(ct mark); (exact syntax TBD). This would be needed to allow sets that store variable-sized data types (string, integer and the like) that can't be used at at the moment. Adding special data types for everything is problematic due to the large amount of different types needed. For anonymous sets, e.g. "string" can be used because the needed size can be inferred from the statement, e.g. 'osf name { "Windows", "Linux }', but in case of named sets that won't work because 'type string' lacks the context needed to derive the size information. With 'typeof(osf name)' the context is there, but at the moment it won't help because the expression is discarded instantly and only the data type is retained. Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index a865902c..91d6b254 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1367,6 +1367,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
{
struct expr_ctx ectx = ctx->ectx;
struct expr *map = *expr, *mappings;
+ const struct datatype *dtype;
struct expr *key;
expr_set_context(&ctx->ectx, NULL, 0);
@@ -1389,10 +1390,14 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
mappings = implicit_set_declaration(ctx, "__map%d",
key,
mappings);
- mappings->set->datatype =
- datatype_get(set_datatype_alloc(ectx.dtype,
- ectx.byteorder));
- mappings->set->datalen = ectx.len;
+
+ dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ dtype, dtype->byteorder,
+ ectx.len, NULL);
+ if (ectx.len && mappings->set->data->len != ectx.len)
+ BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
map->mappings = mappings;
@@ -1428,7 +1433,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
@@ -1458,7 +1463,12 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
"Key must be a constant");
mapping->flags |= mapping->left->flags & EXPR_F_SINGLETON;
- expr_set_context(&ctx->ectx, set->datatype, set->datalen);
+ if (set->data) {
+ expr_set_context(&ctx->ectx, set->data->dtype, set->data->len);
+ } else {
+ assert((set->flags & NFT_SET_MAP) == 0);
+ }
+
if (expr_evaluate(ctx, &mapping->right) < 0)
return -1;
if (!expr_is_constant(mapping->right))
@@ -2103,7 +2113,7 @@ static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
(*expr)->len);
else if ((*expr)->dtype->type != TYPE_INTEGER &&
!datatype_equal((*expr)->dtype, dtype))
- return stmt_binary_error(ctx, *expr, stmt,
+ return stmt_binary_error(ctx, *expr, stmt, /* verdict vs invalid? */
"datatype mismatch: expected %s, "
"expression has type %s",
dtype->desc, (*expr)->dtype->desc);
@@ -3097,9 +3107,9 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
"Key expression comments are not supported");
if (stmt_evaluate_arg(ctx, stmt,
- stmt->map.set->set->datatype,
- stmt->map.set->set->datalen,
- stmt->map.set->set->datatype->byteorder,
+ stmt->map.set->set->data->dtype,
+ stmt->map.set->set->data->len,
+ stmt->map.set->set->data->byteorder,
&stmt->map.data->key) < 0)
return -1;
if (expr_is_constant(stmt->map.data))
@@ -3145,8 +3155,12 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
mappings = implicit_set_declaration(ctx, "__objmap%d",
key, mappings);
- mappings->set->datatype = &string_type;
- mappings->set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+
+ mappings->set->data = constant_expr_alloc(&netlink_location,
+ &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
mappings->set->objtype = stmt->objref.type;
map->mappings = mappings;
@@ -3181,7 +3195,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
map->mappings->set->key->dtype->desc,
map->map->dtype->desc);
- datatype_set(map, map->mappings->set->datatype);
+ datatype_set(map, map->mappings->set->data->dtype);
map->flags |= EXPR_F_CONSTANT;
/* Data for range lookups needs to be in big endian order */
@@ -3326,17 +3340,25 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
return set_error(ctx, set, "concatenated types not supported in interval sets");
if (set_is_datamap(set->flags)) {
- if (set->datatype == NULL)
+ if (set->data == NULL)
return set_error(ctx, set, "map definition does not "
"specify mapping data type");
- set->datalen = set->datatype->size;
- if (set->datalen == 0 && set->datatype->type != TYPE_VERDICT)
+ if (set->data->len == 0 && set->data->dtype->type != TYPE_VERDICT)
return set_error(ctx, set, "unqualified mapping data "
"type specified in map definition");
} else if (set_is_objmap(set->flags)) {
- set->datatype = &string_type;
- set->datalen = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
+ if (set->data) {
+ assert(set->data->etype == EXPR_VALUE);
+ assert(set->data->dtype == &string_type);
+ }
+
+ assert(set->data == NULL);
+ set->data = constant_expr_alloc(&netlink_location, &string_type,
+ BYTEORDER_HOST_ENDIAN,
+ NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
+ NULL);
+
}
ctx->set = set;