From: Maxime Henrion Date: Mon, 27 Apr 2026 18:26:18 +0000 (-0400) Subject: MINOR: lb: infrastructure for declarative initialization X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=16a4de0d5c58234092c702ab0b12049e2ade9d60;p=thirdparty%2Fhaproxy.git MINOR: lb: infrastructure for declarative initialization This creates an ops structure for the various callbacks into the LB algorithms, and defines those ops structure for each algorithm. A new proxy_init callback is added for the initialization functions called from proxy_finalize(). Since one of them needs to return an int in case of an error, we change all the others to also return an int so we have a uniform type. No functional changes. --- diff --git a/include/haproxy/backend-t.h b/include/haproxy/backend-t.h index da3c10a5a..8243c3cdf 100644 --- a/include/haproxy/backend-t.h +++ b/include/haproxy/backend-t.h @@ -150,6 +150,24 @@ struct lbprm_per_tgrp { struct lb_fwrr_per_tgrp fwrr; }; }; + +/* Call backs for some LB actions. Any of them may be NULL (thus should be ignored). + * Those marked "srvlock" will need to be called with the server lock held. + * The other ones might take it themselves if needed. + */ +struct lb_ops { + 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 */ + void (*set_server_status_down)(struct server *); /* to be called after status changes to DOWN // srvlock */ + void (*server_take_conn)(struct server *); /* to be called when connection is assigned */ + void (*server_drop_conn)(struct server *); /* to be called when connection is dropped */ + void (*server_requeue)(struct server *); /* function used to place the server where it must be */ + 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. */ +}; + /* LB parameters for all algorithms */ struct lbprm { union { /* LB parameters depending on the algo type */ @@ -179,6 +197,7 @@ struct lbprm { struct mt_list lb_free_list; /* LB tree elements available */ __decl_thread(HA_RWLOCK_T lock); struct server *fbck; /* first backup server when !PR_O_USE_ALL_BK, or NULL */ + const struct lb_ops *ops; /* algo-specific operations; NULL = no LB algo selected */ /* Call backs for some actions. Any of them may be NULL (thus should be ignored). * Those marked "srvlock" will need to be called with the server lock held. diff --git a/include/haproxy/lb_chash.h b/include/haproxy/lb_chash.h index 79504574b..c96285dff 100644 --- a/include/haproxy/lb_chash.h +++ b/include/haproxy/lb_chash.h @@ -23,6 +23,7 @@ #define _HAPROXY_LB_CHASH_H #include +#include #include struct proxy; @@ -31,6 +32,8 @@ int chash_init_server_tree(struct proxy *p); 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 b12831c21..fb81b3a93 100644 --- a/include/haproxy/lb_fas.h +++ b/include/haproxy/lb_fas.h @@ -23,12 +23,15 @@ #define _HAPROXY_LB_FAS_H #include +#include #include #include #include struct server *fas_get_next_server(struct proxy *p, struct server *srvtoavoid); -void fas_init_server_tree(struct proxy *p); +int fas_init_server_tree(struct proxy *p); + +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 a598af9f3..d5dc0c471 100644 --- a/include/haproxy/lb_fwlc.h +++ b/include/haproxy/lb_fwlc.h @@ -23,12 +23,15 @@ #define _HAPROXY_LB_FWLC_H #include +#include #include #include #include struct server *fwlc_get_next_server(struct proxy *p, struct server *srvtoavoid); -void fwlc_init_server_tree(struct proxy *p); +int fwlc_init_server_tree(struct proxy *p); + +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 27b0a94e0..0e37850a6 100644 --- a/include/haproxy/lb_fwrr.h +++ b/include/haproxy/lb_fwrr.h @@ -23,13 +23,16 @@ #define _HAPROXY_LB_FWRR_H #include +#include #include #include #include -void fwrr_init_server_groups(struct proxy *p); +int fwrr_init_server_groups(struct proxy *p); 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 ca483b239..67d5e341d 100644 --- a/include/haproxy/lb_map.h +++ b/include/haproxy/lb_map.h @@ -23,14 +23,17 @@ #define _HAPROXY_LB_MAP_H #include +#include #include #include void recalc_server_map(struct proxy *px); -void init_server_map(struct proxy *p); +int init_server_map(struct proxy *p); 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 6ec31531f..1696e7538 100644 --- a/include/haproxy/lb_ss.h +++ b/include/haproxy/lb_ss.h @@ -23,11 +23,14 @@ #define _HAPROXY_LB_SS_H #include +#include #include #include void recalc_server_ss(struct proxy *px); -void init_server_ss(struct proxy *px); +int init_server_ss(struct proxy *px); 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/lb_chash.c b/src/lb_chash.c index a852ae07d..8b4d54908 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -626,3 +626,12 @@ int chash_init_server_tree(struct proxy *p) } return 0; } + +const struct lb_ops lb_chash_ops = { + .proxy_init = chash_init_server_tree, + .set_server_status_up = chash_set_server_status_up, + .set_server_status_down = chash_set_server_status_down, + .update_server_eweight = chash_update_server_weight, + .server_init = chash_server_init, + .server_deinit = chash_server_deinit, +}; diff --git a/src/lb_fas.c b/src/lb_fas.c index bac20d28b..43dc3be80 100644 --- a/src/lb_fas.c +++ b/src/lb_fas.c @@ -255,7 +255,7 @@ static void fas_update_server_weight(struct server *srv) * weighted least-conns. It also sets p->lbprm.wdiv to the eweight to * uweight ratio. Both active and backup groups are initialized. */ -void fas_init_server_tree(struct proxy *p) +int fas_init_server_tree(struct proxy *p) { struct server *srv; struct eb_root init_head = EB_ROOT; @@ -285,6 +285,7 @@ void fas_init_server_tree(struct proxy *p) srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fas.bck : &p->lbprm.fas.act; fas_queue_srv(srv); } + return 0; } /* Return next server from the FS tree in backend

. If the tree is empty, @@ -339,6 +340,14 @@ struct server *fas_get_next_server(struct proxy *p, struct server *srvtoavoid) return srv; } +const struct lb_ops lb_fas_ops = { + .proxy_init = fas_init_server_tree, + .set_server_status_up = fas_set_server_status_up, + .set_server_status_down = fas_set_server_status_down, + .update_server_eweight = fas_update_server_weight, + .server_take_conn = fas_srv_reposition, + .server_drop_conn = fas_srv_reposition, +}; /* * Local variables: diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c index 20a679e3a..933bc5591 100644 --- a/src/lb_fwlc.c +++ b/src/lb_fwlc.c @@ -709,7 +709,7 @@ static void fwlc_update_server_weight(struct server *srv) * weighted least-conns. It also sets p->lbprm.wdiv to the eweight to * uweight ratio. Both active and backup groups are initialized. */ -void fwlc_init_server_tree(struct proxy *p) +int fwlc_init_server_tree(struct proxy *p) { struct server *srv; struct eb_root init_head = EB_ROOT; @@ -744,6 +744,7 @@ void fwlc_init_server_tree(struct proxy *p) srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwlc.bck : &p->lbprm.fwlc.act; fwlc_queue_srv(srv, srv->next_eweight); } + return 0; } /* Return next server from the FWLC tree in backend

. If the tree is empty, @@ -886,6 +887,17 @@ redo: return srv; } +const struct lb_ops lb_fwlc_ops = { + .proxy_init = fwlc_init_server_tree, + .set_server_status_up = fwlc_set_server_status_up, + .set_server_status_down = fwlc_set_server_status_down, + .update_server_eweight = fwlc_update_server_weight, + .server_take_conn = fwlc_srv_reposition, + .server_drop_conn = fwlc_srv_reposition, + .server_requeue = fwlc_srv_reposition, + .server_deinit = fwlc_server_deinit, + .proxy_deinit = fwlc_proxy_deinit, +}; /* * Local variables: diff --git a/src/lb_fwrr.c b/src/lb_fwrr.c index 26fca7c4a..d8f774220 100644 --- a/src/lb_fwrr.c +++ b/src/lb_fwrr.c @@ -293,7 +293,7 @@ static inline void fwrr_queue_by_weight(struct eb_root *root, struct server *s, * weighted round-robin. It also sets p->lbprm.wdiv to the eweight to uweight * ratio. Both active and backup groups are initialized. */ -void fwrr_init_server_groups(struct proxy *p) +int fwrr_init_server_groups(struct proxy *p) { struct server *srv; struct eb_root init_head = EB_ROOT; @@ -357,6 +357,7 @@ void fwrr_init_server_groups(struct proxy *p) srv, i + 1); } } + return 0; } /* simply removes a server from a weight tree. @@ -671,6 +672,13 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid) return srv; } +const struct lb_ops lb_fwrr_ops = { + .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, +}; + /* * Local variables: * c-indent-level: 8 diff --git a/src/lb_map.c b/src/lb_map.c index 7dc27b444..c62d81822 100644 --- a/src/lb_map.c +++ b/src/lb_map.c @@ -137,7 +137,7 @@ void recalc_server_map(struct proxy *px) * weights if applicable. It should be called only once per proxy, at config * time. */ -void init_server_map(struct proxy *p) +int init_server_map(struct proxy *p) { struct server *srv; int pgcd; @@ -148,7 +148,7 @@ void init_server_map(struct proxy *p) p->lbprm.update_server_eweight = NULL; if (!p->srv) - return; + return 0; /* We will factor the weights to reduce the table, * using Euclide's largest common divisor algorithm. @@ -201,6 +201,7 @@ void init_server_map(struct proxy *p) recount_servers(p); update_backend_weight(p); recalc_server_map(p); + return 0; } /* @@ -272,6 +273,11 @@ struct server *map_get_server_hash(struct proxy *px, unsigned int hash) return srv; } +const struct lb_ops lb_map_ops = { + .proxy_init = init_server_map, + .set_server_status_up = map_set_server_status_up, + .set_server_status_down = map_set_server_status_down, +}; /* * Local variables: diff --git a/src/lb_ss.c b/src/lb_ss.c index 4af031b29..e95b888df 100644 --- a/src/lb_ss.c +++ b/src/lb_ss.c @@ -143,7 +143,7 @@ void recalc_server_ss(struct proxy *px) /* This function is responsible for preparing sticky LB algorithm. * It should be called only once per proxy, at config time. */ -void init_server_ss(struct proxy *p) +int init_server_ss(struct proxy *p) { struct server *srv; @@ -152,7 +152,7 @@ void init_server_ss(struct proxy *p) p->lbprm.update_server_eweight = NULL; if (!p->srv) - return; + return 0; for (srv = p->srv; srv; srv = srv->next) { srv->next_eweight = 1; /* ignore weights, all servers have the same weight */ @@ -163,6 +163,7 @@ void init_server_ss(struct proxy *p) recount_servers(p); update_backend_weight(p); recalc_server_ss(p); + return 0; } /* @@ -181,3 +182,9 @@ struct server *ss_get_server(struct proxy *px) HA_RWLOCK_RDUNLOCK(LBPRM_LOCK, &px->lbprm.lock); return srv; } + +const struct lb_ops lb_ss_ops = { + .proxy_init = init_server_ss, + .set_server_status_up = ss_set_server_status_up, + .set_server_status_down = ss_set_server_status_down, +};