Re: Moving from ipset to nftables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
 



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux