diff mbox series

[nft,v2,2/4] libnftables: Introduce nft_ctx_flush_cache()

Message ID 20171023153319.13415-3-phil@nwl.cc
State Accepted
Delegated to: Pablo Neira
Headers show
Series libnftables preparations | expand

Commit Message

Phil Sutter Oct. 23, 2017, 3:33 p.m. UTC
This allows an application to explicitly flush caches associated with a
given nft context, as seen in cli_complete().

Note that this is a bit inconsistent in that it releases the global
interface cache, but nft_ctx_free() does the same so at least it's not a
regression.

Note that there is no need for explicit cache update routine since cache
is populated during command execution depending on whether it is needed
or not.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/nftables/nftables.h | 1 +
 src/cli.c                   | 3 +--
 src/libnftables.c           | 9 +++++++--
 3 files changed, 9 insertions(+), 4 deletions(-)

Comments

Pablo Neira Ayuso Oct. 24, 2017, 3:52 p.m. UTC | #1
On Mon, Oct 23, 2017 at 05:33:17PM +0200, Phil Sutter wrote:
> This allows an application to explicitly flush caches associated with a
> given nft context, as seen in cli_complete().
> 
> Note that this is a bit inconsistent in that it releases the global
> interface cache, but nft_ctx_free() does the same so at least it's not a
> regression.
> 
> Note that there is no need for explicit cache update routine since cache
> is populated during command execution depending on whether it is needed
> or not.
> 
> Signed-off-by: Phil Sutter <phil@nwl.cc>
> ---
>  include/nftables/nftables.h | 1 +
>  src/cli.c                   | 3 +--
>  src/libnftables.c           | 9 +++++++--
>  3 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
> index 44d3e95d399e6..1207f10cd2457 100644
> --- a/include/nftables/nftables.h
> +++ b/include/nftables/nftables.h
> @@ -51,6 +51,7 @@ enum nftables_exit_codes {
>  struct nft_ctx *nft_ctx_new(uint32_t flags);
>  void nft_ctx_free(struct nft_ctx *ctx);
>  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);
> +void nft_ctx_flush_cache(struct nft_ctx *ctx);

I would prefer we rename this to nft_ctx_flush_cache().

Now, let's make an exercise of abstraction: You're not Phil Sutter,
you're developer Vlamidir.

Vladimir wants to make a third party application based on libnftables
that is going to rock the world.

He knows nothing about internals, but he looks at the API and say:
"Hey, I can flush the cache, what is this cache concept?".

I'm telling this story because we're leaking an internal detail
implementation. So I would just rename this to nft_ctx_reset(). This
magic call just cleans up the context for you.

Vladimir will be just need to know that he needs to reset context if
he want to make incremental updates based on current.

I agree with you that we cannot allocate 'cache' from nft_ctx_alloc(),
it's good you reminded me this :-).

But I would say, we can just hide these details behind the curtain.

Let me know, thanks

P.S: I still has pushed out your patchset, it's just that I'm
providing feedback so we speed up libnftables release :-).
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Phil Sutter Oct. 24, 2017, 5:40 p.m. UTC | #2
Hi,

On Tue, Oct 24, 2017 at 05:52:59PM +0200, Pablo Neira Ayuso wrote:
> On Mon, Oct 23, 2017 at 05:33:17PM +0200, Phil Sutter wrote:
[...]
> > diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
> > index 44d3e95d399e6..1207f10cd2457 100644
> > --- a/include/nftables/nftables.h
> > +++ b/include/nftables/nftables.h
> > @@ -51,6 +51,7 @@ enum nftables_exit_codes {
> >  struct nft_ctx *nft_ctx_new(uint32_t flags);
> >  void nft_ctx_free(struct nft_ctx *ctx);
> >  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);
> > +void nft_ctx_flush_cache(struct nft_ctx *ctx);
> 
> I would prefer we rename this to nft_ctx_flush_cache().
> 
> Now, let's make an exercise of abstraction: You're not Phil Sutter,
> you're developer Vlamidir.
> 
> Vladimir wants to make a third party application based on libnftables
> that is going to rock the world.
> 
> He knows nothing about internals, but he looks at the API and say:
> "Hey, I can flush the cache, what is this cache concept?".
> 
> I'm telling this story because we're leaking an internal detail
> implementation. So I would just rename this to nft_ctx_reset(). This
> magic call just cleans up the context for you.

Hmm. Without further information, I would guess for nft_ctx_reset() to
reset all the context data which was previously modified using those
setters I defined. A possible cache to reset didn't come to mind since I
wasn't aware that there is a cache at all!

> Vladimir will be just need to know that he needs to reset context if
> he want to make incremental updates based on current.

I wonder whether we need to reset the cache at all: We could make
cache_update() ignore cache->initialized and instead check whether
nft_genid did change after calling netlink_genid_get() - if not, cache
is up to date, otherwise call cache_init(). When we discussed possible
performance implications of cache updates, I suggested just that as a
first counter-measure.

Could this work? Or am I missing something?

Cheers, Phil
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso Oct. 25, 2017, 9:25 a.m. UTC | #3
Hi Phil,

On Tue, Oct 24, 2017 at 07:40:21PM +0200, Phil Sutter wrote:
[...]
> I wonder whether we need to reset the cache at all:

Good point.

> We could make cache_update() ignore cache->initialized and instead
> check whether nft_genid did change after calling netlink_genid_get()
> - if not, cache is up to date, otherwise call cache_init(). When we
> discussed possible performance implications of cache updates, I
> suggested just that as a first counter-measure.
> 
> Could this work? Or am I missing something?

For the simple API, I think it makes sense to remove this
nft_ctx_flush_cache() and just perform inconditional cache refresh on
every nft_cmd_*() call by now.

We can revisit later on to do incremental cache updates based on
generation ID as you said. If we keep track of incremental updates,
then we will need event handling. But for now I will go simple.

Thanks!
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 44d3e95d399e6..1207f10cd2457 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -51,6 +51,7 @@  enum nftables_exit_codes {
 struct nft_ctx *nft_ctx_new(uint32_t flags);
 void nft_ctx_free(struct nft_ctx *ctx);
 FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);
+void nft_ctx_flush_cache(struct nft_ctx *ctx);
 
 int nft_run_cmd_from_buffer(struct nft_ctx *nft, char *buf, size_t buflen);
 int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename);
diff --git a/src/cli.c b/src/cli.c
index cadc3af6e8034..3174cfed05a7d 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -140,8 +140,7 @@  static void cli_complete(char *line)
 	nft_run(cli_nft, cli_nf_sock, scanner, state, &msgs);
 	erec_print_list(&cli_nft->output, &msgs, cli_nft->debug_mask);
 	xfree(line);
-	cache_release(&cli_nft->cache);
-	iface_cache_release();
+	nft_ctx_flush_cache(cli_nft);
 }
 
 static char **cli_completion(const char *text, int start, int end)
diff --git a/src/libnftables.c b/src/libnftables.c
index 9bc51dd894d09..d34e52759e947 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -147,13 +147,18 @@  struct nft_ctx *nft_ctx_new(uint32_t flags)
 	return ctx;
 }
 
+void nft_ctx_flush_cache(struct nft_ctx *ctx)
+{
+	iface_cache_release();
+	cache_release(&ctx->cache);
+}
+
 void nft_ctx_free(struct nft_ctx *ctx)
 {
 	if (ctx->nf_sock)
 		netlink_close_sock(ctx->nf_sock);
 
-	iface_cache_release();
-	cache_release(&ctx->cache);
+	nft_ctx_flush_cache(ctx);
 	xfree(ctx);
 	nft_exit();
 }