# UNDF: UNDF-2026-000000101 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -343,6 +343,7 @@ struct server { int cklen; /* the len of the cookie, to speed up checks */ unsigned int flags; /* server permanent flags */ char *cookie; /* the id set in the cookie */ + struct ebpt_node cookie_node; /* eb-tree node keyed by cookie string; used by proxy->cookies_tree */ --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -364,6 +364,7 @@ struct proxy { struct server *srv, *defsrv; /* known servers; default server configuration */ + struct eb_root cookies_tree; /* eb-tree of srv->cookie_node for O(1) cookie lookup; populated after config parse */ --- a/src/server.c +++ b/src/server.c @@ -XXX,0 +XXX,12 @@ +/* + * Build or rebuild the proxy's cookies_tree index. + * Called after srv_set_dyncookie() and after initial config parse. + * O(S log S) one-time cost; amortises the O(C×S) per-request cookie scan. + */ +void proxy_build_cookie_tree(struct proxy *px) +{ + struct server *srv; + px->cookies_tree = EB_ROOT_UNIQUE; + for (srv = px->srv; srv; srv = srv->next) { + if (srv->cookie) { + srv->cookie_node.key = srv->cookie; + ebis_insert(&px->cookies_tree, &srv->cookie_node); + } + } +} --- a/src/http_ana.c +++ b/src/http_ana.c @@ -3514,10 +3514,18 @@ static void http_manage_client_side_cookies(...) if ((delim == val_beg) || (s->flags & (SF_IGNORE_PRST | SF_ASSIGNED))) srv = NULL; - while (srv) { - if (srv->cookie && (srv->cklen == delim - val_beg) && - !memcmp(val_beg, srv->cookie, delim - val_beg)) { - /* ... */ - } - srv = srv->next; - } + /* Replace O(S) linked-list walk with O(log S) eb-tree lookup. + * proxy_build_cookie_tree() indexes all srv->cookie strings at + * config-time; lookup is safe at runtime (cookies are immutable). */ + if (srv) { + char cookie_key[delim - val_beg + 1]; + memcpy(cookie_key, val_beg, delim - val_beg); + cookie_key[delim - val_beg] = '\0'; + + struct ebpt_node *node = ebis_lookup(&s->be->cookies_tree, cookie_key); + srv = node ? container_of(node, struct server, cookie_node) : NULL; + if (srv) { + if ((srv->cur_state != SRV_ST_STOPPED) || + (s->be->options & PR_O_PERSIST) || + (s->flags & SF_FORCE_PRST)) { + txn->flags &= ~TX_CK_MASK; + txn->flags |= (srv->cur_state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN; + s->flags |= SF_DIRECT | SF_ASSIGNED; + stream_set_srv_target(s, srv); + } else { + txn->flags &= ~TX_CK_MASK; + txn->flags |= TX_CK_DOWN; + srv = NULL; + } + } + }