On 06/01/2019 23:05, Florian Westphal wrote: > Mikhail Morfikov <mmorfikov@xxxxxxxxx> wrote: >> # time nft list table raw-set > /dev/null >> nft list table raw-set > /dev/null 1.41s user 4.11s system 97% cpu 5.666 total >> >> Almost 5s for returning the following output? >> >> # nft list table raw >> table ip raw { >> chain PREROUTING { >> type filter hook prerouting priority -300; policy accept; >> jump notrack-in >> } >> >> chain OUTPUT { >> type filter hook output priority -300; policy accept; >> } >> >> chain notrack-in { >> iifname "lo" counter packets 1209 bytes 84124 notrack >> } >> } > > Agree, this is silly. > >> Is there something I could do to speed this up? > > Unfortunately not, right now nft dumps everything and filters in > userspace. We need to propagate "table name" to the cache init > function, but maybe more changes are needed to make this work > (caching infra is tricky). > > This patch is a starting point, but it doesn't work correctly > with libnftables/interactive mode (nft -i): > > nft -i > list table ip filter > list table ip raw # fails, as cache is deemed up to date, but > # first command only updated the filter table. > > diff --git a/include/mnl.h b/include/mnl.h > --- a/include/mnl.h > +++ b/include/mnl.h > @@ -49,6 +49,7 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, const struct cmd *cmd, > int mnl_nft_table_del(struct netlink_ctx *ctx, const struct cmd *cmd); > > struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx, > + const char *table, > int family); > > int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd, > diff --git a/include/rule.h b/include/rule.h > index dc5e5b87f933..e54346f0b097 100644 > --- a/include/rule.h > +++ b/include/rule.h > @@ -631,7 +631,7 @@ extern struct error_record *rule_postprocess(struct rule *rule); > struct netlink_ctx; > extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd); > > -extern int cache_update(struct nft_ctx *ctx, enum cmd_ops cmd, > +extern int cache_update(struct nft_ctx *ctx, const struct cmd *cmd, > struct list_head *msgs); > extern void cache_flush(struct nft_ctx *ctx, enum cmd_ops cmd, > struct list_head *msgs); > diff --git a/src/evaluate.c b/src/evaluate.c > index 0bda431d5a16..3af1194f341a 100644 > --- a/src/evaluate.c > +++ b/src/evaluate.c > @@ -236,7 +236,7 @@ static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) > } > break; > case SYMBOL_SET: > - ret = cache_update(ctx->nft, ctx->cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, ctx->cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3129,9 +3129,12 @@ static int rule_translate_index(struct eval_ctx *ctx, struct rule *rule) > uint64_t index = 0; > struct rule *r; > int ret; > + struct cmd c = { > + .op = CMD_LIST, > + }; > > /* update cache with CMD_LIST so that rules are fetched, too */ > - ret = cache_update(ctx->nft, CMD_LIST, ctx->msgs); > + ret = cache_update(ctx->nft, &c, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3353,13 +3356,13 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) > > switch (cmd->obj) { > case CMD_OBJ_SETELEM: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > return setelem_evaluate(ctx, &cmd->expr); > case CMD_OBJ_SET: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3369,7 +3372,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) > handle_merge(&cmd->rule->handle, &cmd->handle); > return rule_evaluate(ctx, cmd->rule); > case CMD_OBJ_CHAIN: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3377,7 +3380,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) > case CMD_OBJ_TABLE: > return table_evaluate(ctx, cmd->table); > case CMD_OBJ_FLOWTABLE: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3401,7 +3404,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd) > > switch (cmd->obj) { > case CMD_OBJ_SETELEM: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3429,7 +3432,7 @@ static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd) > struct set *set; > int ret; > > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3492,7 +3495,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) > struct set *set; > int ret; > > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3587,7 +3590,7 @@ static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd) > { > int ret; > > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3625,7 +3628,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) > /* Chains don't hold sets */ > break; > case CMD_OBJ_SET: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3640,7 +3643,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) > > return 0; > case CMD_OBJ_MAP: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3655,7 +3658,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd) > > return 0; > case CMD_OBJ_METER: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3682,7 +3685,7 @@ static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd) > > switch (cmd->obj) { > case CMD_OBJ_CHAIN: > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3779,7 +3782,7 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd) > uint32_t event; > int ret; > > - ret = cache_update(ctx->nft, cmd->op, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -3807,7 +3810,7 @@ static int cmd_evaluate_export(struct eval_ctx *ctx, struct cmd *cmd) > return cmd_error(ctx, &cmd->location, > "JSON export is no longer supported, use 'nft -j list ruleset' instead"); > > - return cache_update(ctx->nft, cmd->op, ctx->msgs); > + return cache_update(ctx->nft, cmd, ctx->msgs); > } > > static int cmd_evaluate_import(struct eval_ctx *ctx, struct cmd *cmd) > diff --git a/src/libnftables.c b/src/libnftables.c > index bd79cd6091d2..ed84c37d25cf 100644 > --- a/src/libnftables.c > +++ b/src/libnftables.c > @@ -420,11 +420,14 @@ err: > int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename) > { > struct cmd *cmd, *next; > + static const struct cmd invalid_cmd = { > + .op = CMD_INVALID, > + }; > LIST_HEAD(msgs); > LIST_HEAD(cmds); > int rc; > > - rc = cache_update(nft, CMD_INVALID, &msgs); > + rc = cache_update(nft, &invalid_cmd, &msgs); > if (rc < 0) > return -1; > > diff --git a/src/mnl.c b/src/mnl.c > index c3d16774f71f..e400f0838c4b 100644 > --- a/src/mnl.c > +++ b/src/mnl.c > @@ -704,19 +704,36 @@ err_free: > } > > struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx, > + const char *table, > int family) > { > char buf[MNL_SOCKET_BUFFER_SIZE]; > struct nftnl_table_list *nlt_list; > + struct nftnl_table *nlt; > struct nlmsghdr *nlh; > + uint16_t flags; > int ret; > > nlt_list = nftnl_table_list_alloc(); > if (nlt_list == NULL) > return NULL; > > + nlt = nftnl_table_alloc(); > + if (nlt == NULL) > + memory_allocation_error(); > + > + if (table) { > + nftnl_table_set_str(nlt, NFTNL_TABLE_NAME, table); > + flags = NLM_F_ACK; > + } else { > + flags = NLM_F_DUMP; > + } > + > nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family, > - NLM_F_DUMP, ctx->seqnum); > + flags, ctx->seqnum); > + > + nftnl_table_nlmsg_build_payload(nlh, nlt); > + nftnl_table_free(nlt); > > ret = nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, table_cb, nlt_list); > if (ret < 0) > diff --git a/src/netlink.c b/src/netlink.c > index f67f63907075..cdce70675a47 100644 > --- a/src/netlink.c > +++ b/src/netlink.c > @@ -463,7 +463,7 @@ int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h) > { > struct nftnl_table_list *table_cache; > > - table_cache = mnl_nft_table_dump(ctx, h->family); > + table_cache = mnl_nft_table_dump(ctx, h->table.name, h->family); > if (table_cache == NULL) { > if (errno == EINTR) > return -1; > diff --git a/src/rule.c b/src/rule.c > index e15a20b30bbd..f690df280306 100644 > --- a/src/rule.c > +++ b/src/rule.c > @@ -134,7 +134,8 @@ void handle_merge(struct handle *dst, const struct handle *src) > dst->index = src->index; > } > > -static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h, > +static int cache_init_tables(struct netlink_ctx *ctx, > + const struct handle *h, > struct nft_cache *cache) > { > int ret; > @@ -203,24 +204,21 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd) > return 0; > } > > -static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd) > +static int cache_init(struct netlink_ctx *ctx, const struct cmd *cmd) > { > - struct handle handle = { > - .family = NFPROTO_UNSPEC, > - }; > int ret; > > - ret = cache_init_tables(ctx, &handle, &ctx->nft->cache); > + ret = cache_init_tables(ctx, &cmd->handle, &ctx->nft->cache); > if (ret < 0) > return ret; > - ret = cache_init_objects(ctx, cmd); > + ret = cache_init_objects(ctx, cmd->op); > if (ret < 0) > return ret; > > return 0; > } > > -int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) > +int cache_update(struct nft_ctx *nft, const struct cmd *cmd, struct list_head *msgs) > { > uint16_t genid; > int ret; > @@ -1477,7 +1475,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl) > if (nft_output_echo(&ctx->nft->output)) { > int ret; > > - ret = cache_update(ctx->nft, cmd->obj, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > @@ -1528,7 +1526,7 @@ static int do_command_insert(struct netlink_ctx *ctx, struct cmd *cmd) > if (nft_output_echo(&ctx->nft->output)) { > int ret; > > - ret = cache_update(ctx->nft, cmd->obj, ctx->msgs); > + ret = cache_update(ctx->nft, cmd, ctx->msgs); > if (ret < 0) > return ret; > > It looks like this patch can't be applied anymore: < git:(master 01e5c6f0) > $ quilt push Applying patch patch patching file include/mnl.h Hunk #1 succeeded at 50 (offset 1 line). patching file include/rule.h Hunk #1 FAILED at 631. 1 out of 1 hunk FAILED -- rejects in file include/rule.h patching file src/evaluate.c Hunk #1 FAILED at 238. Hunk #2 FAILED at 3131. Hunk #3 FAILED at 3355. Hunk #4 FAILED at 3371. Hunk #5 FAILED at 3379. Hunk #6 FAILED at 3403. Hunk #7 FAILED at 3431. Hunk #8 FAILED at 3494. Hunk #9 FAILED at 3589. Hunk #10 FAILED at 3627. Hunk #11 FAILED at 3642. Hunk #12 FAILED at 3657. Hunk #13 FAILED at 3684. Hunk #14 FAILED at 3781. Hunk #15 FAILED at 3809. 15 out of 15 hunks FAILED -- rejects in file src/evaluate.c patching file src/libnftables.c Hunk #1 FAILED at 420. 1 out of 1 hunk FAILED -- rejects in file src/libnftables.c patching file src/mnl.c Hunk #1 succeeded at 749 (offset 49 lines). patching file src/netlink.c Hunk #1 succeeded at 471 (offset 8 lines). patching file src/rule.c Hunk #1 succeeded at 135 (offset 1 line). Hunk #2 FAILED at 204. Hunk #3 FAILED at 1480. Hunk #4 FAILED at 1531. 3 out of 4 hunks FAILED -- rejects in file src/rule.c Patch fix-speed.path does not apply (enforce with -f)
Attachment:
signature.asc
Description: OpenPGP digital signature