size of struct expr changes from 144 to 128 bytes on x86_64. This doesn't look like much, but large rulesets can have tens of thousands of expressions (each set element is represented by an expression). Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- include/expression.h | 9 ++-- src/ct.c | 4 +- src/expression.c | 108 ++++++++++++++++++++++++++++++------------- src/exthdr.c | 2 +- src/fib.c | 4 +- src/hash.c | 4 +- src/meta.c | 4 +- src/numgen.c | 4 +- src/osf.c | 4 +- src/parser_bison.y | 2 +- src/parser_json.c | 2 +- src/payload.c | 4 +- src/rt.c | 6 +-- src/socket.c | 4 +- src/tcpopt.c | 2 +- src/xfrm.c | 4 +- 16 files changed, 106 insertions(+), 61 deletions(-) diff --git a/include/expression.h b/include/expression.h index 2450bc90ec99..18563325012f 100644 --- a/include/expression.h +++ b/include/expression.h @@ -219,12 +219,11 @@ struct expr { unsigned int flags; const struct datatype *dtype; - enum byteorder byteorder; + enum byteorder byteorder:8; enum expr_types etype:8; + enum ops op:8; unsigned int len; - const struct expr_ops *ops; - enum ops op; union { struct { /* EXPR_SYMBOL */ @@ -354,7 +353,7 @@ struct expr { }; extern struct expr *expr_alloc(const struct location *loc, - const struct expr_ops *ops, + enum expr_types etype, const struct datatype *dtype, enum byteorder byteorder, unsigned int len); extern struct expr *expr_clone(const struct expr *expr); @@ -441,7 +440,7 @@ extern struct expr *range_expr_alloc(const struct location *loc, struct expr *low, struct expr *high); extern struct expr *compound_expr_alloc(const struct location *loc, - const struct expr_ops *ops); + enum expr_types etypes); extern void compound_expr_add(struct expr *compound, struct expr *expr); extern void compound_expr_remove(struct expr *compound, struct expr *expr); extern void list_expr_sort(struct list_head *head); diff --git a/src/ct.c b/src/ct.c index 1d50382bab8b..e77c3201eb5d 100644 --- a/src/ct.c +++ b/src/ct.c @@ -357,7 +357,7 @@ static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr) proto_ctx_update(ctx, left->ct.base + 1, &expr->location, desc); } -static const struct expr_ops ct_expr_ops = { +const struct expr_ops ct_expr_ops = { .type = EXPR_CT, .name = "ct", .print = ct_expr_print, @@ -373,7 +373,7 @@ struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key, const struct ct_template *tmpl = &ct_templates[key]; struct expr *expr; - expr = expr_alloc(loc, &ct_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_CT, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->ct.key = key; expr->ct.direction = direction; diff --git a/src/expression.c b/src/expression.c index 8a7e0e7ab669..42a6800ff088 100644 --- a/src/expression.c +++ b/src/expression.c @@ -25,12 +25,20 @@ #include <erec.h> #include <json.h> -static const struct expr_ops *expr_ops(const struct expr *e) -{ - return e->ops; -} - -struct expr *expr_alloc(const struct location *loc, const struct expr_ops *ops, +extern const struct expr_ops ct_expr_ops; +extern const struct expr_ops fib_expr_ops; +extern const struct expr_ops hash_expr_ops; +extern const struct expr_ops meta_expr_ops; +extern const struct expr_ops numgen_expr_ops; +extern const struct expr_ops osf_expr_ops; +extern const struct expr_ops payload_expr_ops; +extern const struct expr_ops rt_expr_ops; +extern const struct expr_ops socket_expr_ops; +extern const struct expr_ops xfrm_expr_ops; + +static const struct expr_ops *expr_ops(const struct expr *e); + +struct expr *expr_alloc(const struct location *loc, enum expr_types etype, const struct datatype *dtype, enum byteorder byteorder, unsigned int len) { @@ -38,9 +46,8 @@ struct expr *expr_alloc(const struct location *loc, const struct expr_ops *ops, expr = xzalloc(sizeof(*expr)); expr->location = *loc; - expr->ops = ops; expr->dtype = dtype; - expr->etype = ops->type; + expr->etype = etype; expr->byteorder = byteorder; expr->len = len; expr->refcnt = 1; @@ -52,11 +59,11 @@ struct expr *expr_clone(const struct expr *expr) { struct expr *new; - new = expr_alloc(&expr->location, expr->ops, expr->dtype, + new = expr_alloc(&expr->location, expr->etype, expr->dtype, expr->byteorder, expr->len); new->flags = expr->flags; new->op = expr->op; - expr->ops->clone(new, expr); + expr_ops(expr)->clone(new, expr); return new; } @@ -70,7 +77,7 @@ static void expr_destroy(struct expr *e) { const struct expr_ops *ops = expr_ops(e); - if (ops && ops->destroy) + if (ops->destroy) ops->destroy(e); } @@ -81,7 +88,8 @@ void expr_free(struct expr *expr) if (--expr->refcnt > 0) return; - expr_destroy(expr); + if (expr->etype != EXPR_INVALID) + expr_destroy(expr); xfree(expr); } @@ -106,7 +114,7 @@ bool expr_cmp(const struct expr *e1, const struct expr *e2) const char *expr_name(const struct expr *e) { - return e->ops->name; + return expr_ops(e)->name; } void expr_describe(const struct expr *expr, struct output_ctx *octx) @@ -231,7 +239,7 @@ struct expr *verdict_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &verdict_expr_ops, &verdict_type, + expr = expr_alloc(loc, EXPR_VERDICT, &verdict_type, BYTEORDER_INVALID, 0); expr->verdict = verdict; if (chain != NULL) @@ -272,7 +280,7 @@ struct expr *symbol_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &symbol_expr_ops, &invalid_type, + expr = expr_alloc(loc, EXPR_SYMBOL, &invalid_type, BYTEORDER_INVALID, 0); expr->symtype = type; expr->scope = scope; @@ -312,7 +320,7 @@ struct expr *variable_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &variable_expr_ops, &invalid_type, + expr = expr_alloc(loc, EXPR_VARIABLE, &invalid_type, BYTEORDER_INVALID, 0); expr->scope = scope; expr->sym = sym; @@ -358,7 +366,7 @@ struct expr *constant_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &constant_expr_ops, dtype, byteorder, len); + expr = expr_alloc(loc, EXPR_VALUE, dtype, byteorder, len); expr->flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON; mpz_init2(expr->value, len); @@ -502,7 +510,7 @@ struct expr *prefix_expr_alloc(const struct location *loc, { struct expr *prefix; - prefix = expr_alloc(loc, &prefix_expr_ops, &invalid_type, + prefix = expr_alloc(loc, EXPR_PREFIX, &invalid_type, BYTEORDER_INVALID, 0); prefix->prefix = expr; prefix->prefix_len = prefix_len; @@ -555,7 +563,7 @@ struct expr *unary_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &unary_expr_ops, &invalid_type, + expr = expr_alloc(loc, EXPR_UNARY, &invalid_type, BYTEORDER_INVALID, 0); expr->op = op; expr->arg = arg; @@ -636,7 +644,7 @@ struct expr *binop_expr_alloc(const struct location *loc, enum ops op, { struct expr *expr; - expr = expr_alloc(loc, &binop_expr_ops, left->dtype, + expr = expr_alloc(loc, EXPR_BINOP, left->dtype, left->byteorder, 0); expr->left = left; expr->op = op; @@ -657,7 +665,7 @@ struct expr *relational_expr_alloc(const struct location *loc, enum ops op, { struct expr *expr; - expr = expr_alloc(loc, &relational_expr_ops, &verdict_type, + expr = expr_alloc(loc, EXPR_RELATIONAL, &verdict_type, BYTEORDER_INVALID, 0); expr->left = left; expr->op = op; @@ -733,7 +741,7 @@ struct expr *range_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &range_expr_ops, &invalid_type, + expr = expr_alloc(loc, EXPR_RANGE, &invalid_type, BYTEORDER_INVALID, 0); expr->left = left; expr->right = right; @@ -741,11 +749,11 @@ struct expr *range_expr_alloc(const struct location *loc, } struct expr *compound_expr_alloc(const struct location *loc, - const struct expr_ops *ops) + enum expr_types etype) { struct expr *expr; - expr = expr_alloc(loc, ops, &invalid_type, BYTEORDER_INVALID, 0); + expr = expr_alloc(loc, etype, &invalid_type, BYTEORDER_INVALID, 0); init_list_head(&expr->expressions); return expr; } @@ -814,7 +822,7 @@ static const struct expr_ops concat_expr_ops = { struct expr *concat_expr_alloc(const struct location *loc) { - return compound_expr_alloc(loc, &concat_expr_ops); + return compound_expr_alloc(loc, EXPR_CONCAT); } static void list_expr_print(const struct expr *expr, struct output_ctx *octx) @@ -833,7 +841,7 @@ static const struct expr_ops list_expr_ops = { struct expr *list_expr_alloc(const struct location *loc) { - return compound_expr_alloc(loc, &list_expr_ops); + return compound_expr_alloc(loc, EXPR_LIST); } static const char *calculate_delim(const struct expr *expr, int *count) @@ -921,7 +929,7 @@ static const struct expr_ops set_expr_ops = { struct expr *set_expr_alloc(const struct location *loc, const struct set *set) { - struct expr *set_expr = compound_expr_alloc(loc, &set_expr_ops); + struct expr *set_expr = compound_expr_alloc(loc, EXPR_SET); if (!set) return set_expr; @@ -973,7 +981,7 @@ struct expr *mapping_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &mapping_expr_ops, from->dtype, + expr = expr_alloc(loc, EXPR_MAPPING, from->dtype, from->byteorder, 0); expr->left = from; expr->right = to; @@ -1017,7 +1025,7 @@ struct expr *map_expr_alloc(const struct location *loc, struct expr *arg, { struct expr *expr; - expr = expr_alloc(loc, &map_expr_ops, &invalid_type, BYTEORDER_INVALID, 0); + expr = expr_alloc(loc, EXPR_MAP, &invalid_type, BYTEORDER_INVALID, 0); expr->map = arg; expr->mappings = mappings; return expr; @@ -1058,7 +1066,7 @@ struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set) { struct expr *expr; - expr = expr_alloc(loc, &set_ref_expr_ops, set->key->dtype, 0, 0); + expr = expr_alloc(loc, EXPR_SET_REF, set->key->dtype, 0, 0); expr->set = set_get(set); expr->flags |= EXPR_F_CONSTANT; return expr; @@ -1112,7 +1120,7 @@ struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key) { struct expr *expr; - expr = expr_alloc(loc, &set_elem_expr_ops, key->dtype, + expr = expr_alloc(loc, EXPR_SET_ELEM, key->dtype, key->byteorder, key->len); expr->key = key; return expr; @@ -1159,3 +1167,41 @@ void range_expr_value_high(mpz_t rop, const struct expr *expr) BUG("invalid range expression type %s\n", expr_name(expr)); } } + +static const struct expr_ops *expr_ops(const struct expr *e) +{ + switch (e->etype) { + case EXPR_INVALID: + BUG("Invalid expression ops requested"); + break; + case EXPR_VERDICT: return &verdict_expr_ops; + case EXPR_SYMBOL: return &symbol_expr_ops; + case EXPR_VARIABLE: return &variable_expr_ops; + case EXPR_VALUE: return &constant_expr_ops; + case EXPR_PREFIX: return &prefix_expr_ops; + case EXPR_RANGE: return &range_expr_ops; + case EXPR_PAYLOAD: return &payload_expr_ops; + case EXPR_EXTHDR: return &exthdr_expr_ops; + case EXPR_META: return &meta_expr_ops; + case EXPR_SOCKET: return &socket_expr_ops; + case EXPR_OSF: return &osf_expr_ops; + case EXPR_CT: return &ct_expr_ops; + case EXPR_CONCAT: return &concat_expr_ops; + case EXPR_LIST: return &list_expr_ops; + case EXPR_SET: return &set_expr_ops; + case EXPR_SET_REF: return &set_ref_expr_ops; + case EXPR_SET_ELEM: return &set_elem_expr_ops; + case EXPR_MAPPING: return &mapping_expr_ops; + case EXPR_MAP: return &map_expr_ops; + case EXPR_UNARY: return &unary_expr_ops; + case EXPR_BINOP: return &binop_expr_ops; + case EXPR_RELATIONAL: return &relational_expr_ops; + case EXPR_NUMGEN: return &numgen_expr_ops; + case EXPR_HASH: return &hash_expr_ops; + case EXPR_RT: return &rt_expr_ops; + case EXPR_FIB: return &fib_expr_ops; + case EXPR_XFRM: return &xfrm_expr_ops; + } + + BUG("Unknown expression type %d\n", e->etype); +} diff --git a/src/exthdr.c b/src/exthdr.c index 8f803be6fc4a..91d2430ab123 100644 --- a/src/exthdr.c +++ b/src/exthdr.c @@ -90,7 +90,7 @@ struct expr *exthdr_expr_alloc(const struct location *loc, else tmpl = &exthdr_unknown_template; - expr = expr_alloc(loc, &exthdr_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype, BYTEORDER_BIG_ENDIAN, tmpl->len); expr->exthdr.desc = desc; expr->exthdr.tmpl = tmpl; diff --git a/src/fib.c b/src/fib.c index 9a19cc348a3d..f2bfef1deda1 100644 --- a/src/fib.c +++ b/src/fib.c @@ -101,7 +101,7 @@ static void fib_expr_clone(struct expr *new, const struct expr *expr) new->fib.flags= expr->fib.flags; } -static const struct expr_ops fib_expr_ops = { +const struct expr_ops fib_expr_ops = { .type = EXPR_FIB, .name = "fib", .print = fib_expr_print, @@ -135,7 +135,7 @@ struct expr *fib_expr_alloc(const struct location *loc, if (flags & NFTA_FIB_F_PRESENT) type = &boolean_type; - expr = expr_alloc(loc, &fib_expr_ops, type, + expr = expr_alloc(loc, EXPR_FIB, type, BYTEORDER_HOST_ENDIAN, len); expr->fib.result = result; diff --git a/src/hash.c b/src/hash.c index a2d2314baa54..208f4b6b6779 100644 --- a/src/hash.c +++ b/src/hash.c @@ -56,7 +56,7 @@ static void hash_expr_clone(struct expr *new, const struct expr *expr) new->hash.type = expr->hash.type; } -static const struct expr_ops hash_expr_ops = { +const struct expr_ops hash_expr_ops = { .type = EXPR_HASH, .name = "hash", .print = hash_expr_print, @@ -73,7 +73,7 @@ struct expr *hash_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &hash_expr_ops, &integer_type, + expr = expr_alloc(loc, EXPR_HASH, &integer_type, BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE); expr->hash.mod = mod; expr->hash.seed_set = seed_set; diff --git a/src/meta.c b/src/meta.c index 4cb91773b71d..7e44a2a3545c 100644 --- a/src/meta.c +++ b/src/meta.c @@ -553,7 +553,7 @@ static void meta_expr_pctx_update(struct proto_ctx *ctx, } } -static const struct expr_ops meta_expr_ops = { +const struct expr_ops meta_expr_ops = { .type = EXPR_META, .name = "meta", .print = meta_expr_print, @@ -568,7 +568,7 @@ struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key) const struct meta_template *tmpl = &meta_templates[key]; struct expr *expr; - expr = expr_alloc(loc, &meta_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_META, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->meta.key = key; diff --git a/src/numgen.c b/src/numgen.c index b7751b0727c2..8318d0a2a796 100644 --- a/src/numgen.c +++ b/src/numgen.c @@ -51,7 +51,7 @@ static void numgen_expr_clone(struct expr *new, const struct expr *expr) new->numgen.offset = expr->numgen.offset; } -static const struct expr_ops numgen_expr_ops = { +const struct expr_ops numgen_expr_ops = { .type = EXPR_NUMGEN, .name = "numgen", .print = numgen_expr_print, @@ -66,7 +66,7 @@ struct expr *numgen_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &numgen_expr_ops, &integer_type, + expr = expr_alloc(loc, EXPR_NUMGEN, &integer_type, BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE); expr->numgen.type = type; expr->numgen.mod = mod; diff --git a/src/osf.c b/src/osf.c index b98d16508d00..9252934dbcfa 100644 --- a/src/osf.c +++ b/src/osf.c @@ -32,7 +32,7 @@ static bool osf_expr_cmp(const struct expr *e1, const struct expr *e2) return e1->osf.ttl == e2->osf.ttl; } -static const struct expr_ops osf_expr_ops = { +const struct expr_ops osf_expr_ops = { .type = EXPR_OSF, .name = "osf", .print = osf_expr_print, @@ -47,7 +47,7 @@ struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl) const struct datatype *type = &string_type; struct expr *expr; - expr = expr_alloc(loc, &osf_expr_ops, type, + expr = expr_alloc(loc, EXPR_OSF, type, BYTEORDER_HOST_ENDIAN, len); expr->osf.ttl = ttl; diff --git a/src/parser_bison.y b/src/parser_bison.y index 0f4d2df8c85f..b20be3a896b0 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1771,7 +1771,7 @@ flowtable_expr : '{' flowtable_list_expr '}' flowtable_list_expr : flowtable_expr_member { - $$ = compound_expr_alloc(&@$, NULL); + $$ = compound_expr_alloc(&@$, EXPR_INVALID); compound_expr_add($$, $1); } | flowtable_list_expr COMMA flowtable_expr_member diff --git a/src/parser_json.c b/src/parser_json.c index 3a9a3798aedc..d00cf422c314 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -2683,7 +2683,7 @@ static struct cmd *json_parse_cmd_add_element(struct json_ctx *ctx, static struct expr *json_parse_flowtable_devs(struct json_ctx *ctx, json_t *root) { - struct expr *tmp, *expr = compound_expr_alloc(int_loc, NULL); + struct expr *tmp, *expr = compound_expr_alloc(int_loc, EXPR_INVALID); const char *dev; json_t *value; size_t index; diff --git a/src/payload.c b/src/payload.c index b459b1bfb1ac..abe9315da389 100644 --- a/src/payload.c +++ b/src/payload.c @@ -104,7 +104,7 @@ static void payload_expr_pctx_update(struct proto_ctx *ctx, proto_ctx_update(ctx, desc->base, &expr->location, desc); } -static const struct expr_ops payload_expr_ops = { +const struct expr_ops payload_expr_ops = { .type = EXPR_PAYLOAD, .name = "payload", .print = payload_expr_print, @@ -156,7 +156,7 @@ struct expr *payload_expr_alloc(const struct location *loc, desc = &proto_unknown; } - expr = expr_alloc(loc, &payload_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_PAYLOAD, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->flags |= flags; diff --git a/src/rt.c b/src/rt.c index b63284fbcd9a..090831fe42a9 100644 --- a/src/rt.c +++ b/src/rt.c @@ -114,7 +114,7 @@ static void rt_expr_clone(struct expr *new, const struct expr *expr) new->rt.key = expr->rt.key; } -static const struct expr_ops rt_expr_ops = { +const struct expr_ops rt_expr_ops = { .type = EXPR_RT, .name = "rt", .print = rt_expr_print, @@ -130,10 +130,10 @@ struct expr *rt_expr_alloc(const struct location *loc, enum nft_rt_keys key, struct expr *expr; if (invalid && tmpl->invalid) - expr = expr_alloc(loc, &rt_expr_ops, &invalid_type, + expr = expr_alloc(loc, EXPR_RT, &invalid_type, tmpl->byteorder, 0); else - expr = expr_alloc(loc, &rt_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_RT, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->rt.key = key; diff --git a/src/socket.c b/src/socket.c index d90b0416e62c..e10b32267762 100644 --- a/src/socket.c +++ b/src/socket.c @@ -43,7 +43,7 @@ static void socket_expr_clone(struct expr *new, const struct expr *expr) new->socket.key = expr->socket.key; } -static const struct expr_ops socket_expr_ops = { +const struct expr_ops socket_expr_ops = { .type = EXPR_SOCKET, .name = "socket", .print = socket_expr_print, @@ -57,7 +57,7 @@ struct expr *socket_expr_alloc(const struct location *loc, enum nft_socket_keys const struct socket_template *tmpl = &socket_templates[key]; struct expr *expr; - expr = expr_alloc(loc, &socket_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_SOCKET, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->socket.key = key; diff --git a/src/tcpopt.c b/src/tcpopt.c index 52c8c07cdd47..6920ff945590 100644 --- a/src/tcpopt.c +++ b/src/tcpopt.c @@ -181,7 +181,7 @@ struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type, optnum = tcpopt_find_optnum(type); - expr = expr_alloc(loc, &exthdr_expr_ops, tmpl->dtype, + expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype, BYTEORDER_BIG_ENDIAN, tmpl->len); expr->exthdr.desc = desc; expr->exthdr.tmpl = tmpl; diff --git a/src/xfrm.c b/src/xfrm.c index 0f5818c568fa..4dd53c3213f6 100644 --- a/src/xfrm.c +++ b/src/xfrm.c @@ -91,7 +91,7 @@ static void xfrm_expr_clone(struct expr *new, const struct expr *expr) memcpy(&new->xfrm, &expr->xfrm, sizeof(new->xfrm)); } -static const struct expr_ops xfrm_expr_ops = { +const struct expr_ops xfrm_expr_ops = { .type = EXPR_XFRM, .name = "xfrm", .print = xfrm_expr_print, @@ -107,7 +107,7 @@ struct expr *xfrm_expr_alloc(const struct location *loc, { struct expr *expr; - expr = expr_alloc(loc, &xfrm_expr_ops, + expr = expr_alloc(loc, EXPR_XFRM, xfrm_templates[key].dtype, xfrm_templates[key].byteorder, xfrm_templates[key].len); -- 2.19.2