From 87a4f6d47ea718087d8057c234299e4d06bffe51 Mon Sep 17 00:00:00 2001 From: Maxime Henrion Date: Wed, 29 Apr 2026 13:56:34 -0400 Subject: [PATCH] MINOR: lb: make LB initialization even more declarative This lets lb_ops specify the conditions necessary to bind to this set of ops. The condition is expressed as a list of mask and match fields on the algorithm flags. This is then used in proxy_finalize() to locate the lb_ops corresponding to the current configuration, by iterating over the list of lb_ops structures. This list is implemented using the same mechanisms used for configuration keywords: an INITCALL1 macro to a registration function. This also moves the lookup and property flags into the lb_ops structure that were previously applied manually on a case by case basis. --- include/haproxy/backend-t.h | 6 +++++ include/haproxy/backend.h | 4 +++ include/haproxy/lb_chash.h | 2 -- include/haproxy/lb_fas.h | 2 -- include/haproxy/lb_fwlc.h | 2 -- include/haproxy/lb_fwrr.h | 2 -- include/haproxy/lb_map.h | 2 -- include/haproxy/lb_ss.h | 2 -- src/backend.c | 7 +++++ src/lb_chash.c | 10 ++++++- src/lb_fas.c | 9 ++++++- src/lb_fwlc.c | 9 ++++++- src/lb_fwrr.c | 9 ++++++- src/lb_map.c | 10 ++++++- src/lb_ss.c | 10 ++++++- src/proxy.c | 53 ++++++++++--------------------------- 16 files changed, 82 insertions(+), 57 deletions(-) diff --git a/include/haproxy/backend-t.h b/include/haproxy/backend-t.h index b966ff321..53c3f8748 100644 --- a/include/haproxy/backend-t.h +++ b/include/haproxy/backend-t.h @@ -156,6 +156,7 @@ struct lbprm_per_tgrp { * The other ones might take it themselves if needed. */ struct lb_ops { + struct list link; int (*proxy_init)(struct proxy *); /* set up per-proxy LB state at config time; <0=fail */ void (*update_server_eweight)(struct server *); /* to be called after eweight change // srvlock */ void (*set_server_status_up)(struct server *); /* to be called after status changes to UP // srvlock */ @@ -166,6 +167,11 @@ struct lb_ops { void (*proxy_deinit)(struct proxy *); /* to be called when we're destroying the proxy */ void (*server_deinit)(struct server *); /* to be called when we're destroying the server */ int (*server_init)(struct server *); /* initialize a freshly added server (runtime); <0=fail. */ + uint32_t algo_prop; /* load balancing algorithm lookup and properties */ + struct { + uint32_t mask; + uint32_t match; + } map[VAR_ARRAY]; }; /* LB parameters for all algorithms */ diff --git a/include/haproxy/backend.h b/include/haproxy/backend.h index 263a2e2c2..5d2cb657c 100644 --- a/include/haproxy/backend.h +++ b/include/haproxy/backend.h @@ -30,6 +30,10 @@ #include #include +extern struct list lb_ops_list; + +void lb_ops_register(struct lb_ops *ops); + struct server *get_server_sh(struct proxy *px, const char *addr, int len, const struct server *avoid); struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid); struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len, const struct server *avoid); diff --git a/include/haproxy/lb_chash.h b/include/haproxy/lb_chash.h index 9ffb59c06..fd8ad111f 100644 --- a/include/haproxy/lb_chash.h +++ b/include/haproxy/lb_chash.h @@ -31,8 +31,6 @@ struct server; struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid); struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const struct server *avoid); -extern const struct lb_ops lb_chash_ops; - #endif /* _HAPROXY_LB_CHASH_H */ /* diff --git a/include/haproxy/lb_fas.h b/include/haproxy/lb_fas.h index 55ef90a67..003553235 100644 --- a/include/haproxy/lb_fas.h +++ b/include/haproxy/lb_fas.h @@ -30,8 +30,6 @@ struct server *fas_get_next_server(struct proxy *p, struct server *srvtoavoid); -extern const struct lb_ops lb_fas_ops; - #endif /* _HAPROXY_LB_FAS_H */ /* diff --git a/include/haproxy/lb_fwlc.h b/include/haproxy/lb_fwlc.h index fae30ada5..7fb4b6d67 100644 --- a/include/haproxy/lb_fwlc.h +++ b/include/haproxy/lb_fwlc.h @@ -30,8 +30,6 @@ struct server *fwlc_get_next_server(struct proxy *p, struct server *srvtoavoid); -extern const struct lb_ops lb_fwlc_ops; - #endif /* _HAPROXY_LB_FWLC_H */ /* diff --git a/include/haproxy/lb_fwrr.h b/include/haproxy/lb_fwrr.h index 2b3f5ad9c..f1a7f7d65 100644 --- a/include/haproxy/lb_fwrr.h +++ b/include/haproxy/lb_fwrr.h @@ -30,8 +30,6 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid); -extern const struct lb_ops lb_fwrr_ops; - #endif /* _HAPROXY_LB_FWRR_H */ /* diff --git a/include/haproxy/lb_map.h b/include/haproxy/lb_map.h index c4f624600..f32a11041 100644 --- a/include/haproxy/lb_map.h +++ b/include/haproxy/lb_map.h @@ -30,8 +30,6 @@ struct server *map_get_server_rr(struct proxy *px, struct server *srvtoavoid); struct server *map_get_server_hash(struct proxy *px, unsigned int hash); -extern const struct lb_ops lb_map_ops; - #endif /* _HAPROXY_LB_MAP_H */ /* diff --git a/include/haproxy/lb_ss.h b/include/haproxy/lb_ss.h index 063c7fd2d..66fd79d7f 100644 --- a/include/haproxy/lb_ss.h +++ b/include/haproxy/lb_ss.h @@ -29,6 +29,4 @@ struct server *ss_get_server(struct proxy *px); -extern const struct lb_ops lb_ss_ops; - #endif /* _HAPROXY_LB_SS_H */ diff --git a/src/backend.c b/src/backend.c index fe1f68022..84115cb22 100644 --- a/src/backend.c +++ b/src/backend.c @@ -64,6 +64,13 @@ #define TRACE_SOURCE &trace_strm +struct list lb_ops_list = LIST_HEAD_INIT(lb_ops_list); + +void lb_ops_register(struct lb_ops *ops) +{ + LIST_APPEND(&lb_ops_list, &ops->link); +} + /* helper function to invoke the correct hash method */ unsigned int gen_hash(const struct proxy* px, const char* key, unsigned long len) { diff --git a/src/lb_chash.c b/src/lb_chash.c index abbdcc645..362299d25 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -619,7 +619,13 @@ static int chash_init_server_tree(struct proxy *p) return 0; } -const struct lb_ops lb_chash_ops = { +static struct lb_ops lb_chash_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_RR | BE_LB_RR_RANDOM }, + { .mask = BE_LB_KIND | BE_LB_HASH_TYPE, .match = BE_LB_KIND_HI | BE_LB_HASH_CONS }, + { 0, 0 } + }, + .algo_prop = BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN, .proxy_init = chash_init_server_tree, .set_server_status_up = chash_set_server_status_up, .set_server_status_down = chash_set_server_status_down, @@ -627,3 +633,5 @@ const struct lb_ops lb_chash_ops = { .server_init = chash_server_init, .server_deinit = chash_server_deinit, }; + +INITCALL1(STG_REGISTER, lb_ops_register, &lb_chash_ops); diff --git a/src/lb_fas.c b/src/lb_fas.c index 9cf000cc6..f789d19db 100644 --- a/src/lb_fas.c +++ b/src/lb_fas.c @@ -334,7 +334,12 @@ struct server *fas_get_next_server(struct proxy *p, struct server *srvtoavoid) return srv; } -const struct lb_ops lb_fas_ops = { +static struct lb_ops lb_fas_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_CB | BE_LB_CB_FAS }, + { 0, 0 } + }, + .algo_prop = BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN, .proxy_init = fas_init_server_tree, .set_server_status_up = fas_set_server_status_up, .set_server_status_down = fas_set_server_status_down, @@ -343,6 +348,8 @@ const struct lb_ops lb_fas_ops = { .server_drop_conn = fas_srv_reposition, }; +INITCALL1(STG_REGISTER, lb_ops_register, &lb_fas_ops); + /* * Local variables: * c-indent-level: 8 diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c index 394ce9ef8..6657d4c1e 100644 --- a/src/lb_fwlc.c +++ b/src/lb_fwlc.c @@ -878,7 +878,12 @@ redo: return srv; } -const struct lb_ops lb_fwlc_ops = { +static struct lb_ops lb_fwlc_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_CB | BE_LB_CB_LC }, + { 0, 0 } + }, + .algo_prop = BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN, .proxy_init = fwlc_init_server_tree, .set_server_status_up = fwlc_set_server_status_up, .set_server_status_down = fwlc_set_server_status_down, @@ -890,6 +895,8 @@ const struct lb_ops lb_fwlc_ops = { .proxy_deinit = fwlc_proxy_deinit, }; +INITCALL1(STG_REGISTER, lb_ops_register, &lb_fwlc_ops); + /* * Local variables: * c-indent-level: 8 diff --git a/src/lb_fwrr.c b/src/lb_fwrr.c index 0b6113baf..8d2386529 100644 --- a/src/lb_fwrr.c +++ b/src/lb_fwrr.c @@ -668,13 +668,20 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid) return srv; } -const struct lb_ops lb_fwrr_ops = { +static struct lb_ops lb_fwrr_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_RR | BE_LB_RR_DYN }, + { 0, 0 } + }, + .algo_prop = BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN, .proxy_init = fwrr_init_server_groups, .set_server_status_up = fwrr_set_server_status_up, .set_server_status_down = fwrr_set_server_status_down, .update_server_eweight = fwrr_update_server_weight, }; +INITCALL1(STG_REGISTER, lb_ops_register, &lb_fwrr_ops); + /* * Local variables: * c-indent-level: 8 diff --git a/src/lb_map.c b/src/lb_map.c index bb6ffb8f7..91d09caf5 100644 --- a/src/lb_map.c +++ b/src/lb_map.c @@ -269,12 +269,20 @@ struct server *map_get_server_hash(struct proxy *px, unsigned int hash) return srv; } -const struct lb_ops lb_map_ops = { +static struct lb_ops lb_map_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_RR | BE_LB_RR_STATIC }, + { .mask = BE_LB_KIND | BE_LB_HASH_TYPE, .match = BE_LB_KIND_HI | BE_LB_HASH_MAP }, + { 0, 0 } + }, + .algo_prop = BE_LB_LKUP_MAP, .proxy_init = init_server_map, .set_server_status_up = map_set_server_status_up, .set_server_status_down = map_set_server_status_down, }; +INITCALL1(STG_REGISTER, lb_ops_register, &lb_map_ops); + /* * Local variables: * c-indent-level: 8 diff --git a/src/lb_ss.c b/src/lb_ss.c index add9f19dd..d9c18ee03 100644 --- a/src/lb_ss.c +++ b/src/lb_ss.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* This function elects a new stick server for proxy px. @@ -179,8 +180,15 @@ struct server *ss_get_server(struct proxy *px) return srv; } -const struct lb_ops lb_ss_ops = { +static struct lb_ops lb_ss_ops = {ILH, + .map = { + { .mask = BE_LB_KIND | BE_LB_PARM, .match = BE_LB_KIND_SA | BE_LB_SA_SS }, + { 0, 0 } + }, + .algo_prop = BE_LB_PROP_DYN, .proxy_init = init_server_ss, .set_server_status_up = ss_set_server_status_up, .set_server_status_down = ss_set_server_status_down, }; + +INITCALL1(STG_REGISTER, lb_ops_register, &lb_ss_ops); diff --git a/src/proxy.c b/src/proxy.c index 5656a51d5..3ac67464f 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1648,6 +1648,7 @@ int proxy_finalize(struct proxy *px, int *err_code) struct server_rule *srule; struct sticking_rule *mrule; struct logger *tmplogger; + struct lb_ops *ops; unsigned int next_id; int cfgerr = 0; char *err = NULL; @@ -2611,49 +2612,23 @@ int proxy_finalize(struct proxy *px, int *err_code) */ px->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN); - switch (px->lbprm.algo & BE_LB_KIND) { - case BE_LB_KIND_RR: - if ((px->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) { - px->lbprm.algo |= BE_LB_LKUP_MAP; - px->lbprm.ops = &lb_map_ops; - } else if ((px->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) { - px->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN; - px->lbprm.ops = &lb_chash_ops; - } else { - px->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN; - px->lbprm.ops = &lb_fwrr_ops; - } - break; - - case BE_LB_KIND_CB: - if ((px->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) { - px->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN; - px->lbprm.ops = &lb_fwlc_ops; - } else { - px->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN; - px->lbprm.ops = &lb_fas_ops; + list_for_each_entry(ops, &lb_ops_list, link) { + int i; + for (i = 0; ops->map[i].match != 0; i++) { + if ((px->lbprm.algo & ops->map[i].mask) == ops->map[i].match) { + px->lbprm.ops = ops; + break; + } } - break; - case BE_LB_KIND_HI: - if ((px->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) { - px->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN; - px->lbprm.ops = &lb_chash_ops; - } else { - px->lbprm.algo |= BE_LB_LKUP_MAP; - px->lbprm.ops = &lb_map_ops; - } - break; - case BE_LB_KIND_SA: - if ((px->lbprm.algo & BE_LB_PARM) == BE_LB_SA_SS) { - px->lbprm.algo |= BE_LB_PROP_DYN; - px->lbprm.ops = &lb_ss_ops; + if (px->lbprm.ops) { + px->lbprm.algo |= px->lbprm.ops->algo_prop; + if (px->lbprm.ops->proxy_init && px->lbprm.ops->proxy_init(px) < 0) + cfgerr++; + break; } - break; } - if (px->lbprm.ops && px->lbprm.ops->proxy_init && - px->lbprm.ops->proxy_init(px) < 0) - cfgerr++; + HA_RWLOCK_INIT(&px->lbprm.lock); if (px->options & PR_O_LOGASAP) -- 2.47.3