[PATCH nft 4/5] parser_json: defer command allocation to nft_cmd_expand

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

 



Place new chains, flowtables, and sets and objects in struct table
and let nft_cmd_expand() allocate the commands instead.

Likewise new rules get appended to chain->rules.

This makes sure chains are created before set elements that reference
them, and rules get created after sets that are referenced by rules.

Instead of allocating a new command, search for the table/chain in the
existing transaction queue and append the object there.

Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 src/parser_json.c | 129 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 123 insertions(+), 6 deletions(-)

diff --git a/src/parser_json.c b/src/parser_json.c
index 91c1e01cee52..a557e3ee81a3 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -55,6 +55,7 @@ struct json_ctx {
 	struct list_head *msgs;
 	struct list_head *cmds;
 	uint32_t flags;
+	bool in_ruleset;
 };
 
 #define is_RHS(ctx)	(ctx->flags & CTX_F_RHS)
@@ -2977,6 +2978,55 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root)
 	return NULL;
 }
 
+static bool table_eq(const struct handle *th, const struct handle *handle)
+{
+	return th->family == handle->family &&
+		strcmp(th->table.name, handle->table.name) == 0;
+}
+
+static struct table *json_cmd_get_table(struct json_ctx *ctx,
+					const struct handle *handle)
+{
+	struct cmd *cmd;
+
+	if (!ctx->in_ruleset)
+		return NULL;
+
+	list_for_each_entry(cmd, ctx->cmds, list) {
+		if (cmd->op != CMD_ADD)
+			continue;
+		if (cmd->obj != CMD_OBJ_TABLE)
+			continue;
+		if (table_eq(&cmd->handle, handle)) {
+			if (cmd->table)
+				return cmd->table;
+
+			cmd->table = table_alloc();
+			handle_merge(&cmd->table->handle, &cmd->handle);
+			return cmd->table;
+		}
+	}
+
+	return NULL;
+}
+
+static struct chain *json_cmd_get_chain(struct json_ctx *ctx,
+					const struct handle *handle)
+{
+	struct table *table =json_cmd_get_table(ctx, handle);
+	struct chain *chain;
+
+	if (!table)
+		return NULL;
+
+	list_for_each_entry(chain, &table->chains, list) {
+		if (strcmp(chain->handle.chain.name, handle->chain.name) == 0)
+			return chain;
+	}
+
+	return NULL;
+}
+
 static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root,
 					    enum cmd_ops op, enum cmd_obj obj)
 {
@@ -3114,8 +3164,23 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root,
 	    op == CMD_LIST ||
 	    op == CMD_FLUSH ||
 	    json_unpack(root, "{s:s, s:s, s:i}",
-			"type", &type, "hook", &hookstr, "prio", &prio))
+			"type", &type, "hook", &hookstr, "prio", &prio)) {
+		struct table *table = json_cmd_get_table(ctx, &h);
+
+		if (table) {
+			assert(op == CMD_ADD);
+
+			if (!chain)
+				chain = chain_alloc();
+
+			handle_merge(&chain->handle, &h);
+			list_add_tail(&chain->list, &table->chains);
+			handle_free(&h);
+			return NULL;
+		}
+
 		return cmd_alloc(op, obj, &h, int_loc, chain);
+	}
 
 	if (!chain)
 		chain = chain_alloc();
@@ -3153,10 +3218,20 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root,
 		}
 	}
 
-	if (op == CMD_ADD)
+	handle_merge(&chain->handle, &h);
+
+	if (op == CMD_ADD) {
+		struct table *table = json_cmd_get_table(ctx, &h);
+
 		json_object_del(root, "handle");
 
-	handle_merge(&chain->handle, &h);
+		if (table) {
+			list_add_tail(&chain->list, &table->chains);
+			handle_free(&h);
+			return NULL;
+		}
+	}
+
 	return cmd_alloc(op, obj, &h, int_loc, chain);
 }
 
@@ -3231,9 +3306,17 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root,
 		rule_stmt_append(rule, stmt);
 	}
 
-	if (op == CMD_ADD)
+	if (op == CMD_ADD) {
+		struct chain *chain = json_cmd_get_chain(ctx, &h);
+
 		json_object_del(root, "handle");
 
+		if (chain) {
+			list_add_tail(&rule->list, &chain->rules);
+			handle_free(&h);
+			return NULL;
+		}
+	}
 	return cmd_alloc(op, obj, &h, int_loc, rule);
 }
 
@@ -3399,9 +3482,18 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
 
 	handle_merge(&set->handle, &h);
 
-	if (op == CMD_ADD)
+	if (op == CMD_ADD) {
+		struct table *table = json_cmd_get_table(ctx, &h);
+
 		json_object_del(root, "handle");
 
+		if (table) {
+			list_add_tail(&set->list, &table->sets);
+			handle_free(&h);
+			return NULL;
+		}
+	}
+
 	return cmd_alloc(op, obj, &h, int_loc, set);
 }
 
@@ -3505,6 +3597,18 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
 			return CMD_ERR_PTR(-1);
 		}
 	}
+
+	if (op == CMD_ADD) {
+		struct table *table = json_cmd_get_table(ctx, &h);
+
+		if (table) {
+			handle_merge(&flowtable->handle, &h);
+			list_add_tail(&flowtable->list, &table->flowtables);
+			handle_free(&h);
+			return NULL;
+		}
+	}
+
 	return cmd_alloc(op, cmd_obj, &h, int_loc, flowtable);
 }
 
@@ -3754,9 +3858,19 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 		BUG("Invalid CMD '%d'", cmd_obj);
 	}
 
-	if (op == CMD_ADD)
+	if (op == CMD_ADD) {
+		struct table *table = json_cmd_get_table(ctx, &h);
+
 		json_object_del(root, "handle");
 
+		if (table) {
+			handle_merge(&obj->handle, &h);
+			list_add_tail(&obj->list, &table->objs);
+			handle_free(&h);
+			return NULL;
+		}
+	}
+
 	return cmd_alloc(op, cmd_obj, &h, int_loc, obj);
 }
 
@@ -4160,10 +4274,13 @@ static int json_parse_cmd(struct json_ctx *ctx, json_t *root)
 		return -1;
 	}
 
+	assert(!ctx->in_ruleset);
+	ctx->in_ruleset = true;
 	/* to accept 'list ruleset' output 1:1, try add command */
 	cmd = json_parse_cmd_add(ctx, root, CMD_ADD);
 	if (CMD_IS_ERR(cmd))
 		return -1;
+	ctx->in_ruleset = false;
 
 out:
 	if (cmd) {
-- 
2.43.0





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux