All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft v2 1/2] src: Allow reset single stateful object
@ 2017-01-24 13:41 Elise Lennion
  2017-01-24 18:54 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 3+ messages in thread
From: Elise Lennion @ 2017-01-24 13:41 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel

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;
+
+	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;
+			}
 			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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH nft v2 1/2] src: Allow reset single stateful object
  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
  2017-01-25 19:08   ` Elise Lennion
  0 siblings, 1 reply; 3+ messages in thread
From: Pablo Neira Ayuso @ 2017-01-24 18:54 UTC (permalink / raw)
  To: Elise Lennion; +Cc: netfilter-devel

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
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH nft v2 1/2] src: Allow reset single stateful object
  2017-01-24 18:54 ` Pablo Neira Ayuso
@ 2017-01-25 19:08   ` Elise Lennion
  0 siblings, 0 replies; 3+ messages in thread
From: Elise Lennion @ 2017-01-25 19:08 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

On Tue, Jan 24, 2017 at 07:54:08PM +0100, Pablo Neira Ayuso wrote:
> Hi Elise,
> 
Hi Pablo,

> 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.
> 

Without cache_update() the mnl_nft_obj_dump() returns NULL.

In this case obj_cb() returns an error on check_genid(), because
netlink_genid_get() wasn't called previously, it's called in
cache_update().

Also, the tables in cache are used to print the object after reset. A
few workarounds are needed, to print after reset, without the cache.
It seems simpler to keep it for all cases, am I overlooking something?

> > +
> > +	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.
> 

Ok, will change it on v3.

> >  			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
> > 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-01-25 19:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
2017-01-25 19:08   ` Elise Lennion

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.