From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH nft 2/6] src: allow to turn off dependency removal
Date: Thu, 27 May 2021 17:43:19 +0200 [thread overview]
Message-ID: <20210527154323.4003-3-fw@strlen.de> (raw)
In-Reply-To: <20210527154323.4003-1-fw@strlen.de>
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@strlen.de>
---
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
next prev parent reply other threads:[~2021-05-27 15:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-27 15:43 [PATCH nft 0/6] nftables: add --optimize support Florian Westphal
2021-05-27 15:43 ` [PATCH nft 1/6] src: add proto ctx options Florian Westphal
2021-05-27 15:43 ` Florian Westphal [this message]
2021-05-27 15:43 ` [PATCH nft 3/6] main: add -O help to dump list of supported optimzation flags Florian Westphal
2021-05-27 15:43 ` [PATCH nft 4/6] evaluate: optionally kill anon sets with one element Florian Westphal
2021-05-27 15:43 ` [PATCH nft 5/6] tests: add test case for -O no-remove-dependencies Florian Westphal
2021-05-27 15:43 ` [PATCH nft 6/6] tests: add test case for removal of anon sets with only a single element Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210527154323.4003-3-fw@strlen.de \
--to=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).