Re: [PATCH nft v2 1/2] src: Allow reset single stateful object

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

 



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



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux