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@xxxxxxxxxxxxx>. > > Signed-off-by: Elise Lennion <elise.lennion@xxxxxxxxx> > --- > > 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 > -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html