diff options
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r-- | src/netlink_delinearize.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 9e3ed53d..43d7ff82 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -27,6 +27,7 @@ #include <erec.h> #include <sys/socket.h> #include <libnftnl/udata.h> +#include <cache.h> #include <xt.h> static int netlink_parse_expr(const struct nftnl_expr *nle, @@ -1627,12 +1628,14 @@ static void netlink_parse_objref(struct netlink_parse_ctx *ctx, ctx->stmt = stmt; } -static const struct { +struct expr_handler { const char *name; void (*parse)(struct netlink_parse_ctx *ctx, const struct location *loc, const struct nftnl_expr *nle); -} netlink_parsers[] = { +}; + +static const struct expr_handler netlink_parsers[] = { { .name = "immediate", .parse = netlink_parse_immediate }, { .name = "cmp", .parse = netlink_parse_cmp }, { .name = "lookup", .parse = netlink_parse_lookup }, @@ -1673,25 +1676,48 @@ static const struct { { .name = "synproxy", .parse = netlink_parse_synproxy }, }; +static const struct expr_handler **expr_handle_ht; + +#define NFT_EXPR_HSIZE 4096 + +void expr_handler_init(void) +{ + unsigned int i; + uint32_t hash; + + expr_handle_ht = calloc(NFT_EXPR_HSIZE, sizeof(expr_handle_ht)); + if (!expr_handle_ht) + memory_allocation_error(); + + for (i = 0; i < array_size(netlink_parsers); i++) { + hash = djb_hash(netlink_parsers[i].name) % NFT_EXPR_HSIZE; + assert(expr_handle_ht[hash] == NULL); + expr_handle_ht[hash] = &netlink_parsers[i]; + } +} + +void expr_handler_exit(void) +{ + xfree(expr_handle_ht); +} + static int netlink_parse_expr(const struct nftnl_expr *nle, struct netlink_parse_ctx *ctx) { const char *type = nftnl_expr_get_str(nle, NFTNL_EXPR_NAME); struct location loc; - unsigned int i; + uint32_t hash; memset(&loc, 0, sizeof(loc)); loc.indesc = &indesc_netlink; loc.nle = nle; - for (i = 0; i < array_size(netlink_parsers); i++) { - if (strcmp(type, netlink_parsers[i].name)) - continue; - netlink_parsers[i].parse(ctx, &loc, nle); - return 0; - } + hash = djb_hash(type) % NFT_EXPR_HSIZE; + if (expr_handle_ht[hash]) + expr_handle_ht[hash]->parse(ctx, &loc, nle); + else + netlink_error(ctx, &loc, "unknown expression type '%s'", type); - netlink_error(ctx, &loc, "unknown expression type '%s'", type); return 0; } |