]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: filters: Warn about ignored legacy filters for a proxy
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 27 Oct 2026 10:15:51 +0000 (11:15 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 27 Oct 2026 12:30:22 +0000 (13:30 +0100)
A proxy without explicit filter declaration now gets its filter mode
deduced from the filters implied by its other directives. When it implies
filters of both kinds, it uses the filter instance mode and the
class-less ones are ignored: their configurations are legacy filter
configurations with no filter instance, so they are never evaluated and
the features they implement silently stop working on that proxy.

Such a proxy is now reported at startup, with a warning per ignored
configuration, naming the configuration and reminding the two ways to
have it evaluated: declare the filter explicitly with the "filter"
directive, which selects the legacy mode for the whole proxy, or set the
"filter-api downgrade-to-legacy" global option.

The relation between a legacy configuration and the instances of its
filter relies on the callbacks table of the filter: a filter supporting
both modes produces configurations with the same table from its legacy
keyword parser and from its class parse callback (see
flt_parse_instance_legacy()), so an instance with the same table means
the filter declared its class. The check runs after the instances are
finalized, when their configurations exist, and before the class
references are released by the flattening.

All the filters supported in-tree register their classes, so only the
third-party filters relying on an implicit declaration are concerned.
The documentation is updated accordingly, in the filters internals guide
and in the configuration manual.

doc/configuration.txt
doc/internals/api/filters.txt
src/filters.c

index 88c50bb47be17603028419153c8e89f3c0fc35f3..9d7537af3d76e05eb9bb39e91f3589d31343bade 100644 (file)
@@ -2824,7 +2824,8 @@ filter-api default | downgrade-to-legacy
   directives: a proxy implying only filters known as legacy filter
   configurations, without any filter class, uses the legacy API, while a
   proxy implying at least one filter class uses the filter instance API, and
-  the class-less filters it may also imply are ignored. By setting this option
+  the class-less filters it may also imply are ignored, with a warning on
+  each of their legacy filter configurations. By setting this option
   to "downgrade-to-legacy", it is possible to force the proxies without
   explicit filter directives to use the legacy filter API, whatever they
   imply. It could be useful the time to convert outdated filters still relying
index 2f94a9d5a0966f8e08b78009f2c0c2cd855cdc42..b8333fca313c55ddaad730922f54f8fc89d8aa1d 100644 (file)
@@ -86,8 +86,9 @@ filters do not select a mode, so a proxy using only implicit filters works in
 the new mode, unless the implicitly declared filters are only known as legacy
 filter configurations: a filter not supporting the new mode declares no
 class, hence no instance, and a proxy implying such filters keeps working in
-the legacy mode. A proxy implying filters of both kinds uses the new mode,
-where the class-less ones are ignored. The "filter-api" global option forces
+legacy mode. A proxy implying filters of both kinds uses the new mode, where
+the class-less ones are ignored: their legacy configurations are reported as
+a warning. The "filter-api" global option forces
 the legacy mode for every proxy using only implicitly declared filters,
 whatever they imply. It is a fallback for the filters not supporting the
 new mode, and the explicit declarations always win.
@@ -1662,7 +1663,8 @@ working as-is, nothing is required to use it with the "filter" directive.
 But it is invisible to the new mode until its class is declared. A proxy
 implying only such filters keeps working in the legacy mode, since HAProxy
 3.5 deduces it from the implied declarations, but a proxy implying filters
-of both kinds ignores the class-less ones: the "filter-api
+of both kinds ignores the class-less ones, with a warning on each of their
+legacy configurations: the "filter-api
 downgrade-to-legacy" global option keeps them working in the meantime, see
 the FAQ (section 5.7).
 This section lists what changed for a filter developer, then explains how to
@@ -2036,7 +2038,8 @@ enabled by another directive, or is referenced by other directives.
     works in the legacy mode by default, since HAProxy 3.5 deduces the mode
     from the implied declarations, so they keep working as-is. The problem
     only arises for a proxy implying filters of both kinds: the class-less
-    ones are ignored. All the filters implied by such a proxy must then
+    ones are ignored, and HAProxy reports a warning for each of their legacy
+    configurations. All the filters implied by such a proxy must then
     support the new mode, or the legacy ones must be declared explicitly
     with the "filter" directive.
 
index 9987ed5f39751cd2ff4e3950b3e7c56cb6d74435..36f6c14154de1b60a63a8187fff1e4397c7ea9e0 100644 (file)
@@ -3191,6 +3191,57 @@ static int flt_has_conf_instances(const struct proxy *px)
        return 0;
 }
 
+/* Returns true if the proxy <px> has a filter instance of the filter owning
+ * the callbacks table <ops>. A filter supporting the new mode registers a
+ * class whose parse callback produces configurations with the same callbacks
+ * table as its legacy keyword parser (see flt_parse_instance_legacy()), so
+ * the table identifies the filter behind a configuration. Must be called
+ * after the instances were finalized, when their configuration exists.
+ */
+static int flt_conf_has_instance(struct proxy *px, const struct flt_ops *ops)
+{
+       struct filter_class_ref *ref;
+       struct filter_instance *inst;
+
+       list_for_each_entry(ref, &px->conf.filter_refs, list) {
+               list_for_each_entry(inst, &ref->instances, global.list) {
+                       if (inst->fconf && inst->fconf->ops == ops)
+                               return 1;
+               }
+       }
+       return 0;
+}
+
+/* Warns about the legacy filter configurations of the proxy <px> that the new
+ * filter API ignores. Only the filter instances are evaluated in the new
+ * mode: a legacy filter configuration with no instance of the same filter is
+ * never used, and the filter it configures does not work. Such a
+ * configuration comes from an implicit declaration of a filter that
+ * registered no class, an explicit "filter" directive would have selected the
+ * legacy mode for the whole proxy. The relation between a configuration and
+ * the instances of its filter relies on the callbacks table of the filter,
+ * see flt_conf_has_instance(). Must be called when the proxy uses the new
+ * mode, after its instances were finalized and before they are flattened.
+ */
+static void flt_warn_ignored_conf(struct proxy *px)
+{
+       struct flt_conf *fconf;
+
+       if (flt_use_legacy_filter(px) || LIST_ISEMPTY(&px->filter_configs))
+               return;
+
+       list_for_each_entry(fconf, &px->filter_configs, list) {
+               if (flt_conf_has_instance(px, fconf->ops))
+                       continue;
+               ha_warning("config: %s '%s' : ignoring the legacy filter configuration '%s'. "
+                          "Declare all filters with the 'filter' directive or use the 'filter-api "
+                          "downgrade-to-legacy' option to evaluate it with the legacy filter API.\n",
+                          proxy_type_str(px), px->id,
+                          fconf->id ? fconf->id : (fconf->name ? fconf->name : "<unnamed>"));
+       }
+}
+
+
 /* Applies the default filter mode on the proxy <px>, when it used no explicit
  * filter declaration (neither "filter" nor "filter-*" directives): the mode
  * is deduced from the filter configurations and the filter instances implied
@@ -3261,6 +3312,11 @@ static int flt_precheck_instances_all()
                                 px->id);
                        return err_code;
                }
+               /* The instances are finalized: the legacy configurations of the
+                * filters that registered no class, ignored by the new mode,
+                * are identified now, before the class references are released.
+                */
+               flt_warn_ignored_conf(px);
                err_code |= flt_enable_filters(px);
                if (err_code & (ERR_ABORT|ERR_FATAL)) {
                        ha_alert("Failed to apply the filter-enable/filter-disable directives of proxy '%s'.\n",