From: Willy Tarreau Date: Mon, 14 Jan 2019 16:07:39 +0000 (+0100) Subject: BUG/MINOR: backend: BE_LB_LKUP_CHTREE is a value, not a bit X-Git-Tag: v2.0-dev1~211 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c30be52da3d949a8dd6fb5e2de7319c031e656e;p=thirdparty%2Fhaproxy.git BUG/MINOR: backend: BE_LB_LKUP_CHTREE is a value, not a bit There are a few instances where the lookup algo is tested against BE_LB_LKUP_CHTREE using a binary "AND" operation while this macro is a value among a set, and not a bit. The test happens to work because the value is exactly 4 and no bit overlaps with the other possible values but this is a latent bug waiting for a new LB algo to appear to strike. At the moment the only other algo sharing a bit with it is the "first" algo which is never supported in the same code places. This fix should be backported to maintained versions for safety if it passes easily, otherwise it's not important as it will not fix any visible issue. --- diff --git a/src/backend.c b/src/backend.c index 00537f094b..13543c90e4 100644 --- a/src/backend.c +++ b/src/backend.c @@ -185,7 +185,7 @@ static struct server *get_server_sh(struct proxy *px, const char *addr, int len, if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) h = full_hash(h); hash_done: - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, h, avoid); else return map_get_server_hash(px, h); @@ -238,7 +238,7 @@ static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, co if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); hash_done: - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); @@ -295,7 +295,7 @@ static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_l if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); @@ -369,7 +369,7 @@ static struct server *get_server_ph_post(struct stream *s, const struct server * if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); @@ -465,7 +465,7 @@ static struct server *get_server_hh(struct stream *s, const struct server *avoid if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); hash_done: - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); @@ -510,7 +510,7 @@ static struct server *get_server_rch(struct stream *s, const struct server *avoi if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); hash_done: - if (px->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((px->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash, avoid); else return map_get_server_hash(px, hash); @@ -640,7 +640,7 @@ int assign_server(struct stream *s) if ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR) { if ((s->be->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) srv = get_server_rnd(s, prev_srv); - else if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) + else if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) srv = chash_get_next_server(s->be, prev_srv); else srv = map_get_server_rr(s->be, prev_srv); @@ -716,7 +716,7 @@ int assign_server(struct stream *s) * back to round robin on the map. */ if (!srv) { - if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE) + if ((s->be->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_CHTREE) srv = chash_get_next_server(s->be, prev_srv); else srv = map_get_server_rr(s->be, prev_srv);