* 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 */
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 */
#include <haproxy/stream-t.h>
#include <haproxy/time.h>
+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);
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 */
/*
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 */
/*
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 */
/*
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 */
/*
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 */
/*
struct server *ss_get_server(struct proxy *px);
-extern const struct lb_ops lb_ss_ops;
-
#endif /* _HAPROXY_LB_SS_H */
#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)
{
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,
.server_init = chash_server_init,
.server_deinit = chash_server_deinit,
};
+
+INITCALL1(STG_REGISTER, lb_ops_register, &lb_chash_ops);
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,
.server_drop_conn = fas_srv_reposition,
};
+INITCALL1(STG_REGISTER, lb_ops_register, &lb_fas_ops);
+
/*
* Local variables:
* c-indent-level: 8
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,
.proxy_deinit = fwlc_proxy_deinit,
};
+INITCALL1(STG_REGISTER, lb_ops_register, &lb_fwlc_ops);
+
/*
* Local variables:
* c-indent-level: 8
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
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
#include <haproxy/api.h>
#include <haproxy/backend.h>
#include <haproxy/lb_ss.h>
+#include <haproxy/list.h>
#include <haproxy/server-t.h>
/* This function elects a new stick server for 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);
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;
*/
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)