[PATCH nft 2/6] src: allow to turn off dependency removal

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

 



This allows to list a table without dependency removal:

nft -O no-remove-dependencies list ruleset
table inet filter {
        chain ssh {
                type filter hook input priority filter; policy accept;
                meta l4proto tcp tcp dport 22 accept
        }
}

The dependency "meta l4proto tcp" is retained.

Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 include/nftables.h        |  9 +++++
 include/proto.h           |  4 +++
 src/libnftables.c         |  1 +
 src/main.c                | 69 +++++++++++++++++++++++++++++++++++++++
 src/netlink_delinearize.c | 16 +++++++--
 5 files changed, 96 insertions(+), 3 deletions(-)

diff --git a/include/nftables.h b/include/nftables.h
index f239fcf0e1f4..bbf287e68a4c 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -108,6 +108,7 @@ struct nft_ctx {
 	unsigned int		num_include_paths;
 	unsigned int		parser_max_errors;
 	unsigned int		debug_mask;
+	unsigned int		optimization_flags;
 	struct output_ctx	output;
 	bool			check;
 	struct nft_cache	cache;
@@ -213,4 +214,12 @@ int nft_gmp_print(struct output_ctx *octx, const char *fmt, ...)
 
 #define __NFT_OUTPUT_NOTSUPP	UINT_MAX
 
+/* XXX: exposing this in libnftables limits public API
+ * to 32 optimization flags.
+ */
+enum nft_optimization_flags {
+	NFT_OPTIMIZATION_F_REMOVE_DEPS = 1 << 0,
+};
+#define DEFAULT_OPTIMIZATION_FLAGS NFT_OPTIMIZATION_F_REMOVE_DEPS
+
 #endif /* NFTABLES_NFTABLES_H */
diff --git a/include/proto.h b/include/proto.h
index 001b6f9436f7..019e12e1899d 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -168,6 +168,10 @@ extern const struct proto_desc *proto_dev_desc(uint16_t type);
 
 #define PROTO_CTX_NUM_PROTOS	16
 
+enum proto_ctx_flags {
+	PROTO_F_REMOVE_DEPS = 1 << 0,
+};
+
 /**
  * struct proto_ctx - protocol context
  *
diff --git a/src/libnftables.c b/src/libnftables.c
index e080eb032770..a1f822cbe2e6 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -166,6 +166,7 @@ struct nft_ctx *nft_ctx_new(uint32_t flags)
 
 	ctx->state = xzalloc(sizeof(struct parser_state));
 	nft_ctx_add_include_path(ctx, DEFAULT_INCLUDE_PATH);
+	ctx->optimization_flags = DEFAULT_OPTIMIZATION_FLAGS;
 	ctx->parser_max_errors	= 10;
 	cache_init(&ctx->cache.table_cache);
 	ctx->top_scope = scope_alloc();
diff --git a/src/main.c b/src/main.c
index 8c47064459ec..6e14a7f26b0f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 
 #include <nftables/libnftables.h>
+#include <nftables.h>
 #include <utils.h>
 #include <cli.h>
 
@@ -34,6 +35,7 @@ enum opt_indices {
 #define IDX_RULESET_INPUT_START	IDX_FILE
 	IDX_INTERACTIVE,
         IDX_INCLUDEPATH,
+	IDX_OPTIMIZE,
 	IDX_CHECK,
 #define IDX_RULESET_INPUT_END	IDX_CHECK
         /* Ruleset list formatting */
@@ -78,9 +80,15 @@ enum opt_vals {
 	OPT_NUMERIC_PROTO	= 'p',
 	OPT_NUMERIC_TIME	= 'T',
 	OPT_TERSE		= 't',
+	OPT_OPTIMIZE		= 'O',
 	OPT_INVALID		= '?',
 };
 
+enum optimization_feature {
+	OPTIMIZE_UNDEFINED,
+	OPTIMIZE_REMOVE_DEPENDENCIES,
+};
+
 struct nft_opt {
 	const char    *name;
 	enum opt_vals  val;
@@ -104,6 +112,8 @@ static const struct nft_opt nft_options[] = {
 				     "Read input from interactive CLI"),
 	[IDX_INCLUDEPATH]   = NFT_OPT("includepath",		OPT_INCLUDEPATH,	"<directory>",
 				     "Add <directory> to the paths searched for include files. Default is: " DEFAULT_INCLUDE_PATH),
+	[IDX_OPTIMIZE]	    = NFT_OPT("optimize",		OPT_OPTIMIZE,		"<name [,name..]>",
+				     "Specify optimization options"),
 	[IDX_CHECK]	    = NFT_OPT("check",			OPT_CHECK,		NULL,
 				     "Check commands validity without actually applying the changes."),
 	[IDX_HANDLE]	    = NFT_OPT("handle",			OPT_HANDLE_OUTPUT,	NULL,
@@ -303,6 +313,18 @@ static const struct {
 	},
 };
 
+static const struct {
+	const char		*name;
+	enum optimization_feature level;
+	enum nft_optimization_flags flag;
+} optimization_param[] = {
+	{
+		.name	= "remove-dependencies",
+		.level	= OPTIMIZE_REMOVE_DEPENDENCIES,
+		.flag	= NFT_OPTIMIZATION_F_REMOVE_DEPS,
+	},
+};
+
 static void nft_options_error(int argc, char * const argv[], int pos)
 {
 	int i;
@@ -331,9 +353,11 @@ static bool nft_options_check(int argc, char * const argv[])
 				return false;
 			} else if (argv[i][1] == 'd' ||
 				   argv[i][1] == 'I' ||
+				   argv[i][1] == 'O' ||
 				   argv[i][1] == 'f' ||
 				   !strcmp(argv[i], "--debug") ||
 				   !strcmp(argv[i], "--includepath") ||
+				   !strcmp(argv[i], "--optimize") ||
 				   !strcmp(argv[i], "--file")) {
 				skip = true;
 				continue;
@@ -346,6 +370,48 @@ static bool nft_options_check(int argc, char * const argv[])
 	return true;
 }
 
+static void optimize_settings_set_custom(struct nft_ctx *ctx, char *options)
+{
+	unsigned int i;
+	char *end;
+
+	do {
+		enum optimization_feature level = OPTIMIZE_UNDEFINED;
+		unsigned int flag = 0;
+		bool enable = true;
+
+		end = strchr(options, ',');
+		if (end)
+			*end = '\0';
+
+		if (strncmp(options, "no-", 3) == 0) {
+			options += 3;
+			enable = false;
+		}
+
+		for (i = 0; i < array_size(optimization_param); i++) {
+			if (strcmp(optimization_param[i].name, options))
+				continue;
+
+			level = optimization_param[i].level;
+			flag = optimization_param[i].flag;
+			break;
+		}
+
+		switch (level) {
+		case OPTIMIZE_UNDEFINED:
+			fprintf(stderr, "invalid optimization option `%s'\n", options);
+			exit(EXIT_FAILURE);
+		case OPTIMIZE_REMOVE_DEPENDENCIES:
+			break;
+		}
+		if (enable)
+			ctx->optimization_flags |= flag;
+		else
+			ctx->optimization_flags &= ~flag;
+	} while (end != NULL);
+}
+
 int main(int argc, char * const *argv)
 {
 	const struct option *options = get_options();
@@ -465,6 +531,9 @@ int main(int argc, char * const *argv)
 		case OPT_TERSE:
 			output_flags |= NFT_CTX_OUTPUT_TERSE;
 			break;
+		case OPT_OPTIMIZE:
+			optimize_settings_set_custom(nft, optarg);
+			break;
 		case OPT_INVALID:
 			exit(EXIT_FAILURE);
 		}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 6e907e95dbf1..9cd582211e78 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1847,6 +1847,9 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
 		assert(left->payload.base);
 		assert(base == left->payload.base);
 
+		if ((ctx->pctx.options & PROTO_F_REMOVE_DEPS) == 0)
+			continue;
+
 		stacked = payload_is_stacked(ctx->pctx.protocol[base].desc, nexpr);
 
 		/* Remember the first payload protocol expression to
@@ -1985,6 +1988,9 @@ static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
 
 		relational_expr_pctx_update(&ctx->pctx, expr);
 
+		if ((ctx->pctx.options & PROTO_F_REMOVE_DEPS) == 0)
+			break;
+
 		if (ctx->pdctx.pbase == PROTO_BASE_INVALID &&
 		    left->flags & EXPR_F_PROTOCOL) {
 			payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
@@ -2814,13 +2820,14 @@ rule_maybe_reset_payload_deps(struct payload_dep_ctx *pdctx, enum stmt_types t)
 	payload_dependency_reset(pdctx);
 }
 
-static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rule)
+static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rule,
+				   unsigned int options)
 {
 	struct rule_pp_ctx rctx;
 	struct stmt *stmt, *next;
 
 	memset(&rctx, 0, sizeof(rctx));
-	proto_ctx_init(&rctx.pctx, rule->handle.family, ctx->debug_mask, 0);
+	proto_ctx_init(&rctx.pctx, rule->handle.family, ctx->debug_mask, options);
 
 	list_for_each_entry_safe(stmt, next, &rule->stmts, list) {
 		enum stmt_types type = stmt->ops->type;
@@ -2947,11 +2954,14 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 				      struct nftnl_rule *nlr)
 {
 	struct netlink_parse_ctx _ctx, *pctx = &_ctx;
+	unsigned int proto_options = 0;
 	struct handle h;
 
 	memset(&_ctx, 0, sizeof(_ctx));
 	_ctx.msgs = ctx->msgs;
 	_ctx.debug_mask = ctx->nft->debug_mask;
+	if (ctx->nft->optimization_flags & NFT_OPTIMIZATION_F_REMOVE_DEPS)
+		proto_options |= PROTO_F_REMOVE_DEPS;
 
 	memset(&h, 0, sizeof(h));
 	h.family = nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY);
@@ -2971,7 +2981,7 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 
 	nftnl_expr_foreach(nlr, netlink_parse_rule_expr, pctx);
 
-	rule_parse_postprocess(pctx, pctx->rule);
+	rule_parse_postprocess(pctx, pctx->rule, proto_options);
 	netlink_release_registers(pctx);
 	return pctx->rule;
 }
-- 
2.26.3




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

  Powered by Linux