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

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

 



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

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