From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Elise Lennion <elise.lennion@gmail.com>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [PATCH nft v2 1/2] src: Allow reset single stateful object
Date: Tue, 24 Jan 2017 19:54:08 +0100 [thread overview]
Message-ID: <20170124185408.GA9531@salvia> (raw)
In-Reply-To: <20170124134117.GA1673@lennorien.com>
Hi Elise,
comments below.
On Tue, Jan 24, 2017 at 11:41:17AM -0200, Elise Lennion wrote:
> Currently the stateful objects can only be reseted in groups. With this
> patch reseting a single object is allowed:
>
> $ nft reset counter filter https-traffic
> table ip filter {
> counter https-traffic {
> packets 8774 bytes 542668
> }
> }
>
> $ nft list counter filter https-traffic
> table ip filter {
> counter https-traffic {
> packets 0 bytes 0
> }
> }
>
> Only the tables with reseted objects will be listed. Same goes for the
> command list, i.e. tables without quota objects aren't printed on
> 'list quotas', same for counters.
>
> Heavily based on work from Pablo Neira Ayuso <pablo@netfilter.org>.
>
> Signed-off-by: Elise Lennion <elise.lennion@gmail.com>
> ---
>
> v2: Only list tables with counters and quotas that are reseted, on v1
> tables without stateful object were listed.
>
> include/mnl.h | 4 ++--
> include/netlink.h | 3 ++-
> src/evaluate.c | 28 +++++++++++++++++++++++++++-
> src/mnl.c | 9 ++++++---
> src/netlink.c | 9 +++++----
> src/parser_bison.y | 8 ++++++++
> src/rule.c | 21 ++++++++++++++++-----
> 7 files changed, 66 insertions(+), 16 deletions(-)
>
> diff --git a/include/mnl.h b/include/mnl.h
> index 4a99972..69dd0b7 100644
> --- a/include/mnl.h
> +++ b/include/mnl.h
> @@ -87,8 +87,8 @@ int mnl_nft_setelem_batch_flush(struct nftnl_set *nls, unsigned int flags,
> int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls);
>
> struct nftnl_obj_list *mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family,
> - const char *table, uint32_t type,
> - bool reset);
> + const char *table, const char *name,
> + uint32_t type, bool dump, bool reset);
> int mnl_nft_obj_batch_add(struct nftnl_obj *nln, unsigned int flags,
> uint32_t seqnum);
> int mnl_nft_obj_batch_del(struct nftnl_obj *nln, unsigned int flags,
> diff --git a/include/netlink.h b/include/netlink.h
> index 450aba5..d3fb8c5 100644
> --- a/include/netlink.h
> +++ b/include/netlink.h
> @@ -172,7 +172,8 @@ extern int netlink_flush_setelems(struct netlink_ctx *ctx, const struct handle *
> extern int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h,
> const struct location *loc);
> extern int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h,
> - const struct location *loc, uint32_t type);
> + const struct location *loc, uint32_t type,
> + bool dump);
> extern int netlink_add_obj(struct netlink_ctx *ctx, const struct handle *h,
> struct obj *obj, bool excl);
> extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h,
> diff --git a/src/evaluate.c b/src/evaluate.c
> index bcbced1..9a9927b 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -2949,6 +2949,31 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
> }
> }
>
> +static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
> +{
> + struct table *table;
> + int ret;
> +
> + ret = cache_update(cmd->op, ctx->msgs);
> + if (ret < 0)
> + return ret;
I think we only need the cache_update() in the _COUNTERS, _QUOTAS
case.
> +
> + switch (cmd->obj) {
> + case CMD_OBJ_COUNTER:
> + case CMD_OBJ_QUOTA:
> + table = table_lookup(&cmd->handle);
> + if (table == NULL)
> + return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
> + cmd->handle.table);
> + return 0;
> + case CMD_OBJ_COUNTERS:
> + case CMD_OBJ_QUOTAS:
> + return 0;
> + default:
> + BUG("invalid command object type %u\n", cmd->obj);
> + }
> +}
> +
> static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
> {
> int ret;
> @@ -3140,8 +3165,9 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
> case CMD_DELETE:
> return cmd_evaluate_delete(ctx, cmd);
> case CMD_LIST:
> - case CMD_RESET:
> return cmd_evaluate_list(ctx, cmd);
> + case CMD_RESET:
> + return cmd_evaluate_reset(ctx, cmd);
> case CMD_FLUSH:
> return cmd_evaluate_flush(ctx, cmd);
> case CMD_RENAME:
> diff --git a/src/mnl.c b/src/mnl.c
> index 1c4b070..295dd84 100644
> --- a/src/mnl.c
> +++ b/src/mnl.c
> @@ -849,8 +849,9 @@ err_free:
>
> struct nftnl_obj_list *
> mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table,
> - uint32_t type, bool reset)
> + const char *name, uint32_t type, bool dump, bool reset)
> {
> + uint16_t nl_flags = dump ? NLM_F_DUMP : 0;
> struct nftnl_obj_list *nln_list;
> char buf[MNL_SOCKET_BUFFER_SIZE];
> struct nftnl_obj *n;
> @@ -867,9 +868,11 @@ mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table,
> memory_allocation_error();
>
> nlh = nftnl_nlmsg_build_hdr(buf, msg_type, family,
> - NLM_F_DUMP | NLM_F_ACK, seq);
> + nl_flags | NLM_F_ACK, seq);
> if (table != NULL)
> - nftnl_obj_set(n, NFTNL_OBJ_TABLE, table);
> + nftnl_obj_set_str(n, NFTNL_OBJ_TABLE, table);
> + if (name != NULL)
> + nftnl_obj_set_str(n, NFTNL_OBJ_NAME, name);
> if (type != NFT_OBJECT_UNSPEC)
> nftnl_obj_set_u32(n, NFTNL_OBJ_TYPE, type);
> nftnl_obj_nlmsg_build_payload(nlh, n);
> diff --git a/src/netlink.c b/src/netlink.c
> index 73ee5c9..0cc3a51 100644
> --- a/src/netlink.c
> +++ b/src/netlink.c
> @@ -1775,8 +1775,8 @@ int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h,
> struct nftnl_obj_list *obj_cache;
> int err;
>
> - obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table,
> - NFT_OBJECT_UNSPEC, false);
> + obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, NULL,
> + 0, true, false);
> if (obj_cache == NULL) {
> if (errno == EINTR)
> return -1;
> @@ -1790,12 +1790,13 @@ int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h,
> }
>
> int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h,
> - const struct location *loc, uint32_t type)
> + const struct location *loc, uint32_t type, bool dump)
> {
> struct nftnl_obj_list *obj_cache;
> int err;
>
> - obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, type, true);
> + obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, h->obj,
> + type, dump, true);
> if (obj_cache == NULL) {
> if (errno == EINTR)
> return -1;
> diff --git a/src/parser_bison.y b/src/parser_bison.y
> index 4749c9f..a1b8b08 100644
> --- a/src/parser_bison.y
> +++ b/src/parser_bison.y
> @@ -974,6 +974,10 @@ reset_cmd : COUNTERS ruleset_spec
> {
> $$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$3, &@$, NULL);
> }
> + | COUNTER obj_spec
> + {
> + $$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTER, &$2,&@$, NULL);
> + }
> | QUOTAS ruleset_spec
> {
> $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$2, &@$, NULL);
> @@ -982,6 +986,10 @@ reset_cmd : COUNTERS ruleset_spec
> {
> $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$3, &@$, NULL);
> }
> + | QUOTA obj_spec
> + {
> + $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTA, &$2, &@$, NULL);
> + }
> ;
>
> flush_cmd : TABLE table_spec
> diff --git a/src/rule.c b/src/rule.c
> index b5181a9..cd76983 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -1266,24 +1266,30 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type)
> };
> struct table *table;
> struct obj *obj;
> + bool print_table;
>
> list_for_each_entry(table, &table_list, list) {
> if (cmd->handle.family != NFPROTO_UNSPEC &&
> cmd->handle.family != table->handle.family)
> continue;
>
> - printf("table %s %s {\n",
> - family2str(table->handle.family),
> - table->handle.table);
> + print_table = false;
>
> list_for_each_entry(obj, &table->objs, list) {
> if (obj->type != type)
> continue;
>
> + if (!print_table) {
> + printf("table %s %s {\n",
> + family2str(table->handle.family),
> + table->handle.table);
> + print_table = true;
> + }
We always print the table, this information is useful so we reload
partial listings via nft -f. Moreover, if the listing is exported to
file, the upper table that acts as container is also included.
Simplify this by printing the table, inconditionally.
> obj_print_declaration(obj, &opts);
> }
>
> - printf("}\n");
> + if (print_table)
> + printf("}\n");
> }
> return 0;
> }
> @@ -1435,21 +1441,26 @@ static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd)
> {
> struct obj *obj, *next;
> struct table *table;
> + bool dump = false;
> uint32_t type;
> int ret;
>
> switch (cmd->obj) {
> case CMD_OBJ_COUNTERS:
> + dump = true;
> + case CMD_OBJ_COUNTER:
> type = NFT_OBJECT_COUNTER;
> break;
> case CMD_OBJ_QUOTAS:
> + dump = true;
> + case CMD_OBJ_QUOTA:
> type = NFT_OBJECT_QUOTA;
> break;
> default:
> BUG("invalid command object type %u\n", cmd->obj);
> }
>
> - ret = netlink_reset_objs(ctx, &cmd->handle, &cmd->location, type);
> + ret = netlink_reset_objs(ctx, &cmd->handle, &cmd->location, type, dump);
> list_for_each_entry_safe(obj, next, &ctx->list, list) {
> table = table_lookup(&obj->handle);
> list_move(&obj->list, &table->objs);
> --
> 2.7.4
>
next prev parent reply other threads:[~2017-01-24 18:54 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-24 13:41 [PATCH nft v2 1/2] src: Allow reset single stateful object Elise Lennion
2017-01-24 18:54 ` Pablo Neira Ayuso [this message]
2017-01-25 19:08 ` Elise Lennion
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=20170124185408.GA9531@salvia \
--to=pablo@netfilter.org \
--cc=elise.lennion@gmail.com \
--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).