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 <[email protected]>.
> > 
> > Signed-off-by: Elise Lennion <[email protected]>
> > ---
> > 
> >  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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to