]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lb: infrastructure for declarative initialization
authorMaxime Henrion <mhenrion@haproxy.com>
Mon, 27 Apr 2026 18:26:18 +0000 (14:26 -0400)
committerOlivier Houchard <cognet@ci0.org>
Tue, 28 Apr 2026 13:31:51 +0000 (15:31 +0200)
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.

13 files changed:
include/haproxy/backend-t.h
include/haproxy/lb_chash.h
include/haproxy/lb_fas.h
include/haproxy/lb_fwlc.h
include/haproxy/lb_fwrr.h
include/haproxy/lb_map.h
include/haproxy/lb_ss.h
src/lb_chash.c
src/lb_fas.c
src/lb_fwlc.c
src/lb_fwrr.c
src/lb_map.c
src/lb_ss.c

index da3c10a5a472ca5ac31268b6f6d882410452dce7..8243c3cdf3c359cc12e5c9503d0048acd865e662 100644 (file)
@@ -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.
index 79504574b803faaa144f9f777c2491a2e4ec136e..c96285dffdc0839bab795d05e9d8cce8b81ccfb7 100644 (file)
@@ -23,6 +23,7 @@
 #define _HAPROXY_LB_CHASH_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/lb_chash-t.h>
 
 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 */
 
 /*
index b12831c21d72505bffa95c41de91c25f9f1b3ee5..fb81b3a9368dea9b46ae2735761b6701f16c644d 100644 (file)
 #define _HAPROXY_LB_FAS_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/lb_fas-t.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 
 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 */
 
index a598af9f37a9576fdc64e0511ad40f094d09c939..d5dc0c471238380f674e5367f702432b5c97abee 100644 (file)
 #define _HAPROXY_LB_FWLC_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/lb_fwlc-t.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 
 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 */
 
index 27b0a94e04c349b6027d0c15ff039a855df8fb52..0e37850a65a8edd97a002346a157ea9a7c03e555 100644 (file)
 #define _HAPROXY_LB_FWRR_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/lb_fwrr-t.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 
-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 */
 
 /*
index ca483b2394fa6faa55a09118dfe9f16ff2c91d1b..67d5e341d90932d152c15b1fd5980adae2855510 100644 (file)
 #define _HAPROXY_LB_MAP_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 
 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 */
 
 /*
index 6ec31531ff677a72237bb560697899fedb928c06..1696e7538ea995fc6a38dea91d8626e6a26d6a6f 100644 (file)
 #define _HAPROXY_LB_SS_H
 
 #include <haproxy/api.h>
+#include <haproxy/backend-t.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/server-t.h>
 
 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 */
index a852ae07dcf2c2fc7a655f788c88d63dd1b7e8c9..8b4d5490816ad4e6536fcdc2f7aa79e4b8be2616 100644 (file)
@@ -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,
+};
index bac20d28bb764b9f3909b107d6360d0e01b8bb2a..43dc3be808597057ef3af4ca60c5876031d62244 100644 (file)
@@ -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 <p>. 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:
index 20a679e3af5a681a7d908b0ae3a5762468919bea..933bc55911bcc16c84aab2821fb7592028ae47be 100644 (file)
@@ -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 <p>. 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:
index 26fca7c4aaae1814cf60ee3f0dce880f8e357aac..d8f7742201715ef6c5eacb9b276350fb56835ed7 100644 (file)
@@ -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
index 7dc27b444778e1d210acdb63c37bd810045822d7..c62d81822c72a76e55f1f1ae2ab4c40b9561bec2 100644 (file)
@@ -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:
index 4af031b2910c3afb0ef2416ef6e927c8ed27ad7a..e95b888dfc73e5bec5de41e2b1db05490546a0f9 100644 (file)
@@ -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,
+};