if (!LIST_ISEMPTY(&px->conf.filter_enabled) || !LIST_ISEMPTY(&px->conf.filter_sequences))
return 1;
- list_for_each_entry(ref, &px->conf.filter_req_refs, list) {
- list_for_each_entry(inst, &ref->instances, req.list) {
- if (!(inst->flags & FLT_INST_F_IMPLICIT))
- return 1;
- }
- }
- list_for_each_entry(ref, &px->conf.filter_res_refs, list) {
- list_for_each_entry(inst, &ref->instances, res.list) {
+ list_for_each_entry(ref, &px->conf.filter_refs, list) {
+ list_for_each_entry(inst, &ref->instances, global.list) {
if (!(inst->flags & FLT_INST_F_IMPLICIT))
return 1;
}
if (fconf->ops->init && fconf->ops->init(proxy, fconf) < 0)
return ERR_ALERT|ERR_FATAL;
}
- list_for_each_entry(inst, &proxy->filter_req_instances, req.list) {
- fconf = inst->fconf;
- if (!fconf)
- continue;
- if (fconf->ops->init && fconf->ops->init(proxy, fconf) < 0)
- return ERR_ALERT|ERR_FATAL;
- }
- list_for_each_entry(inst, &proxy->filter_res_instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already handled from the request side */
+ list_for_each_entry(inst, &proxy->filter_instances, global.list) {
fconf = inst->fconf;
if (!fconf)
continue;
if (fconf->ops->init_per_thread && fconf->ops->init_per_thread(proxy, fconf) < 0)
return ERR_ALERT|ERR_FATAL;
}
- list_for_each_entry(inst, &proxy->filter_req_instances, req.list) {
- fconf = inst->fconf;
- if (!fconf)
- continue;
- if (fconf->ops->init_per_thread && fconf->ops->init_per_thread(proxy, fconf) < 0)
- return ERR_ALERT|ERR_FATAL;
- }
- list_for_each_entry(inst, &proxy->filter_res_instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already handled from the request side */
+ list_for_each_entry(inst, &proxy->filter_instances, global.list) {
fconf = inst->fconf;
if (!fconf)
continue;
struct flt_conf *fconf;
int err = 0;
- list_for_each_entry(inst, &px->filter_req_instances, req.list) {
- fconf = inst->fconf;
- if (!fconf)
- continue;
- if (fconf->ops->check)
- err += fconf->ops->check(px, fconf);
- }
- list_for_each_entry(inst, &px->filter_res_instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already handled from the request side */
+ list_for_each_entry(inst, &px->filter_instances, global.list) {
fconf = inst->fconf;
if (!fconf)
continue;
LIST_DELETE(&fconf->list);
free(fconf);
}
- list_for_each_entry(inst, &proxy->filter_req_instances, req.list) {
- fconf = inst->fconf;
- if (!fconf)
- continue;
- if (fconf->ops->deinit)
- fconf->ops->deinit(proxy, fconf);
- }
- list_for_each_entry(inst, &proxy->filter_res_instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already handled from the request side */
+ list_for_each_entry(inst, &proxy->filter_instances, global.list) {
fconf = inst->fconf;
if (fconf && fconf->ops && fconf->ops->deinit)
fconf->ops->deinit(proxy, fconf);
*
* The callback is called for the legacy filters (px->filter_configs) and
* for the finalized filter instances (inst->fconf), iterating the flat
- * per-side lists of the proxy.
+ * global list of the proxy.
*/
void
flt_deinit_per_thread(struct proxy *proxy)
if (fconf->ops->deinit_per_thread)
fconf->ops->deinit_per_thread(proxy, fconf);
}
- list_for_each_entry(inst, &proxy->filter_req_instances, req.list) {
- fconf = inst->fconf;
- if (!fconf)
- continue;
- if (fconf->ops->deinit_per_thread)
- fconf->ops->deinit_per_thread(proxy, fconf);
- }
- list_for_each_entry(inst, &proxy->filter_res_instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already handled from the request side */
+ list_for_each_entry(inst, &proxy->filter_instances, global.list) {
fconf = inst->fconf;
if (!fconf)
continue;
struct flt_match_instance_ctx {
struct filter_class *cls; /* the class to match */
const char *id; /* the id to match, NULL for any id */
- unsigned int side; /* the side being iterated (FLT_SIDE_REQ or FLT_SIDE_RES) */
struct filter_instance *found; /* the first matching instance, if any */
int count; /* the number of matching instances */
};
if (inst->class != ctx->cls)
return 0;
- if (ctx->side == FLT_SIDE_RES && LIST_INLIST(&inst->req.list))
- return 0; /* already matched from the request side */
if (ctx->id && (!inst->id || strcmp(inst->id, ctx->id) != 0))
return 0;
if (!ctx->found)
{
struct flt_match_instance_ctx ctx = { .cls = cls, .id = id, .found = NULL, .count = 0 };
- /* instances are in the flat per-side lists of the proxy, or in the
- * class references if the configuration was not flattened yet (or
- * for the defaults sections): the request side first, then the
- * response side
+ /* The global order contains every instance exactly once, whether it
+ * is still in class references (including defaults) or already flat.
*/
- ctx.side = FLT_SIDE_REQ;
- if (flt_foreach_instance(&px->filter_req_instances, FLT_SIDE_REQ, flt_match_instance_cb, &ctx) && ctx.found)
- goto end;
- ctx.side = FLT_SIDE_RES;
- if (flt_foreach_instance(&px->filter_res_instances, FLT_SIDE_RES, flt_match_instance_cb, &ctx) && ctx.found)
+ if (flt_foreach_instance(&px->filter_instances, FLT_SIDE_GLOBAL, flt_match_instance_cb, &ctx) && ctx.found)
goto end;
- ctx.side = FLT_SIDE_REQ;
- if (flt_foreach_instance_side(px, FLT_SIDE_REQ, flt_match_instance_cb, &ctx) && ctx.found)
- goto end;
- ctx.side = FLT_SIDE_RES;
- flt_foreach_instance_side(px, FLT_SIDE_RES, flt_match_instance_cb, &ctx);
+ flt_foreach_instance_side(px, FLT_SIDE_GLOBAL, flt_match_instance_cb, &ctx);
end:
if (count)
return -1;
}
-/* Copy all filter deinitions of the defaults proxy <defpx> into the proxy <px>.
+/* Copy all filter instances of the defaults proxy <defpx> into the proxy <px>.
* Returns 0 on success, -1 on error (out of memory).
*/
int flt_copy_instances(struct proxy *px, const struct proxy *defpx)
struct filter_enabled *flt_en, *new_en;
struct filter_sequence *seq, *new_seq;
- /* iterate over all the instances of the defaults proxy: the request
- * side first, then the instances of the classes with no request side
- * from the response side
+ /* Defaults keep their class references until destruction. Copy every
+ * instance once, in the global class order.
*/
- list_for_each_entry(ref, &defpx->conf.filter_req_refs, list) {
- list_for_each_entry(inst, &ref->instances, req.list)
+ list_for_each_entry(ref, &defpx->conf.filter_refs, list) {
+ list_for_each_entry(inst, &ref->instances, global.list)
if (flt_copy_instance(px, inst) < 0)
goto error;
}
- list_for_each_entry(ref, &defpx->conf.filter_res_refs, list) {
- list_for_each_entry(inst, &ref->instances, res.list) {
- if (LIST_INLIST(&inst->req.list))
- continue; /* already copied from the request side */
- if (flt_copy_instance(px, inst) < 0)
- goto error;
- }
- }
/* inherit the filter-enable entries too */
list_for_each_entry(flt_en, &defpx->conf.filter_enabled, list) {
ctx.id = flt_en->id;
ctx.enable = flt_en->enable;
ctx.found = 0;
- flt_foreach_instance_side(proxy, FLT_SIDE_REQ, flt_enable_cb, &ctx);
- flt_foreach_instance_side(proxy, FLT_SIDE_RES, flt_enable_cb, &ctx);
+ flt_foreach_instance_side(proxy, FLT_SIDE_GLOBAL, flt_enable_cb, &ctx);
if (!ctx.found) {
ha_alert("config: %s '%s' : 'filter-%s' : no instance of filter class '%s'%s%s%s (from %s:%d).\n",
proxy_type_str(proxy), proxy->id,
* instance is allowed for classes without FLT_CLS_FL_MULTI. Returns a
* combination of ERR_* flags, ERR_NONE on success.
*/
-static int flt_precheck_class_instances(struct proxy *proxy, struct filter_class_ref *ref, unsigned int side)
+static int flt_precheck_class_instances(struct proxy *proxy, struct filter_class_ref *ref)
{
struct filter_instance *inst;
int err_code = ERR_NONE;
int count = 0;
- if (side == FLT_SIDE_REQ) {
- list_for_each_entry(inst, &ref->instances, req.list)
- count++;
- }
- else {
- list_for_each_entry(inst, &ref->instances, res.list)
- count++;
- }
+ list_for_each_entry(inst, &ref->instances, global.list)
+ count++;
if (count > 1 && !(ref->class->flags & FLT_CLS_FL_MULTI)) {
- if (side == FLT_SIDE_REQ) {
- list_for_each_entry(inst, &ref->instances, req.list) {
- ha_alert("config: %s '%s' : several instances of filter class '%s', but only one is allowed (see %s:%d).\n",
- proxy_type_str(proxy), proxy->id, ref->class->name,
- inst->conf.file, inst->conf.line);
- }
- }
- else {
- list_for_each_entry(inst, &ref->instances, res.list) {
- ha_alert("config: %s '%s' : several instances of filter class '%s', but only one is allowed (see %s:%d).\n",
- proxy_type_str(proxy), proxy->id, ref->class->name,
- inst->conf.file, inst->conf.line);
- }
+ list_for_each_entry(inst, &ref->instances, global.list) {
+ ha_alert("config: %s '%s' : several instances of filter class '%s', but only one is allowed (see %s:%d).\n",
+ proxy_type_str(proxy), proxy->id, ref->class->name,
+ inst->conf.file, inst->conf.line);
}
return ERR_ALERT | ERR_FATAL;
}
- if (side == FLT_SIDE_REQ) {
- list_for_each_entry(inst, &ref->instances, req.list)
- err_code |= flt_precheck_instance(proxy, inst);
- }
- else {
- list_for_each_entry(inst, &ref->instances, res.list)
- err_code |= flt_precheck_instance(proxy, inst);
- }
+ list_for_each_entry(inst, &ref->instances, global.list)
+ err_code |= flt_precheck_instance(proxy, inst);
return err_code;
}
struct filter_class_ref *ref;
int err_code = ERR_NONE;
- /* iterate over all the class references of the proxy: the request side
- * first, then the references of the classes with no request side from
- * the response side
- */
- list_for_each_entry(ref, &proxy->conf.filter_req_refs, list)
- err_code |= flt_precheck_class_instances(proxy, ref, FLT_SIDE_REQ);
- list_for_each_entry(ref, &proxy->conf.filter_res_refs, list) {
- if (LIST_INLIST(&ref->class->req.list))
- continue; /* already handled from the request side */
- err_code |= flt_precheck_class_instances(proxy, ref, FLT_SIDE_RES);
- }
+ /* Finalize every instance once, following the global class order. */
+ list_for_each_entry(ref, &proxy->conf.filter_refs, list)
+ err_code |= flt_precheck_class_instances(proxy, ref);
return err_code;
}