netfilter: conntrack: add nf_conntrack_events autodetect mode
authorFlorian Westphal <fw@strlen.de>
Mon, 25 Apr 2022 13:15:43 +0000 (15:15 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 13 May 2022 16:56:28 +0000 (18:56 +0200)
This adds the new nf_conntrack_events=2 mode and makes it the
default.

This leverages the earlier flag in struct net to allow to avoid
the event extension as long as no event listener is active in
the namespace.

This avoids, for most cases, allocation of ct->ext area.
A followup patch will take further advantage of this by avoiding
calls down into the event framework if the extension isn't present.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Documentation/networking/nf_conntrack-sysctl.rst
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_standalone.c

index 311128abb7685702f65703a04e9fe14760496c7f..834945ebc4cdf3ce3fffeb477d2d9b1047b7a7a4 100644 (file)
@@ -34,10 +34,13 @@ nf_conntrack_count - INTEGER (read-only)
 
 nf_conntrack_events - BOOLEAN
        - 0 - disabled
-       - not 0 - enabled (default)
+       - 1 - enabled
+       - 2 - auto (default)
 
        If this option is enabled, the connection tracking code will
        provide userspace with connection tracking events via ctnetlink.
+       The default allocates the extension if a userspace program is
+       listening to ctnetlink events.
 
 nf_conntrack_expect_max - INTEGER
        Maximum size of expectation table.  Default value is
index 7b078ec1f923c95882c205f5a46cd97f283543e7..082a2fd8d85b1529455cfe843f6d121fb3844a3a 100644 (file)
@@ -1736,7 +1736,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
        ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
 
-       if (!nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
+       if ((ecache || net->ct.sysctl_events) &&
+           !nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
                                  ecache ? ecache->expmask : 0,
                                  GFP_ATOMIC)) {
                nf_conntrack_free(ct);
index 2f0b52fdcbfa2d322684fc6c8031f9593a7dbf3e..8698b3424646039a9fcc0bdc1a11f1af58765010 100644 (file)
@@ -302,12 +302,27 @@ bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp
        struct net *net = nf_ct_net(ct);
        struct nf_conntrack_ecache *e;
 
-       if (!ctmask && !expmask && net->ct.sysctl_events) {
-               ctmask = ~0;
-               expmask = ~0;
+       switch (net->ct.sysctl_events) {
+       case 0:
+                /* assignment via template / ruleset? ignore sysctl. */
+               if (ctmask || expmask)
+                       break;
+               return true;
+       case 2: /* autodetect: no event listener, don't allocate extension. */
+               if (!READ_ONCE(net->ct.ctnetlink_has_listener))
+                       return true;
+               fallthrough;
+       case 1:
+               /* always allocate an extension. */
+               if (!ctmask && !expmask) {
+                       ctmask = ~0;
+                       expmask = ~0;
+               }
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return true;
        }
-       if (!ctmask && !expmask)
-               return false;
 
        e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
        if (e) {
@@ -319,7 +334,7 @@ bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp
 }
 EXPORT_SYMBOL_GPL(nf_ct_ecache_ext_add);
 
-#define NF_CT_EVENTS_DEFAULT 1
+#define NF_CT_EVENTS_DEFAULT 2
 static int nf_ct_events __read_mostly = NF_CT_EVENTS_DEFAULT;
 
 void nf_conntrack_ecache_pernet_init(struct net *net)
index 3e1afd10a9b60d21e3cb6b8f4a73bf0ac43e3ebc..948884deaca51a0f0f6226cd8c6625812250b948 100644 (file)
@@ -693,7 +693,7 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dou8vec_minmax,
                .extra1         = SYSCTL_ZERO,
-               .extra2         = SYSCTL_ONE,
+               .extra2         = SYSCTL_TWO,
        },
 #endif
 #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP