]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: listener: index listener ID using compact trees
authorWilly Tarreau <w@1wt.eu>
Sun, 24 Aug 2025 09:12:49 +0000 (11:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 16 Sep 2025 07:23:46 +0000 (09:23 +0200)
The listener ID is currently stored as a 32-bit int using an eb32 tree.
It's used essentially to find holes in order to automatically assign IDs,
and to detect duplicates. Let's change this to use compact trees instead
in order to save 24 bytes in struct listener for this node, plus 8 bytes
in struct proxy. The struct listener is now 704 bytes large, and the
struct proxy 3080.

include/haproxy/listener-t.h
include/haproxy/listener.h
include/haproxy/proxy-t.h
src/cfgparse.c
src/listener.c
src/proxy.c

index ce7e850193da0c86a8d0f0dc61e28aab9f41d279..c36108713bbdec45bb726d37d8c0223a647fdd6a 100644 (file)
@@ -238,7 +238,7 @@ struct listener {
        enum obj_type obj_type;         /* object type = OBJ_TYPE_LISTENER */
        enum li_state state;            /* state: NEW, INIT, ASSIGNED, LISTEN, READY, FULL */
        uint16_t flags;                 /* listener flags: LI_F_* */
-       int luid;                       /* listener universally unique ID, used for SNMP */
+       int luid;                       /* listener universally unique ID, used for SNMP, indexed by <luid_node> below */
        int nbconn;                     /* current number of connections on this listener */
        unsigned long thr_idx;          /* thread indexes for queue distribution (see listener_accept()) */
        __decl_thread(HA_RWLOCK_T lock);
@@ -253,10 +253,7 @@ struct listener {
        struct list by_bind;            /* chaining in bind_conf's list of listeners */
        struct bind_conf *bind_conf;    /* "bind" line settings, include SSL settings among other things */
        struct receiver rx;             /* network receiver parts */
-       struct {
-               struct eb32_node id;    /* place in the tree of used IDs */
-       } conf;                         /* config information */
-
+       struct ceb_node luid_node;      /* place in the tree of used IDs, indexes <luid> above */
        struct guid_node guid;          /* GUID global tree node */
 
        struct li_per_thread *per_thr;  /* per-thread fields (one per thread in the group) */
index 88146e0a49d8b32a9eb730880a6b7021e17838d1..d8aea274b6bb37d45acd178209a0f119e4b8d48a 100644 (file)
@@ -25,7 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <import/eb32tree.h>
+#include <import/ceb32_tree.h>
 
 #include <haproxy/api.h>
 #include <haproxy/listener-t.h>
@@ -242,7 +242,7 @@ extern ullong maxconn_reached;
 /* index listener <li>'s id into proxy <px>'s used_listener_id */
 static inline void listener_index_id(struct proxy *px, struct listener *li)
 {
-       eb32_insert(&px->conf.used_listener_id, &li->conf.id);
+       ceb32_item_insert(&px->conf.used_listener_id, luid_node, luid, li);
 }
 
 static inline uint accept_queue_ring_len(const struct accept_queue_ring *ring)
index 66b9f110a6a24ae7ae71d650d92dbe52c0bc0e69..50da4dcad0869076c07a244b6abf13cf121c0aeb 100644 (file)
@@ -462,7 +462,7 @@ struct proxy {
                const char *file;               /* file where the section appears */
                struct ceb_node uuid_node;      /* place in the tree of used IDs, indexes <uuid> above */
                int line;                       /* line where the section appears */
-               struct eb_root used_listener_id;/* list of listener IDs in use */
+               struct ceb_root *used_listener_id; /* list of listener IDs in use */
                struct eb_root used_server_id;  /* list of server IDs in use */
                struct ceb_root *used_server_name; /* list of server names in use */
                struct list bind;               /* list of bind settings */
index 7814ceadc2852b6125383f2674cbd20e59bc7387..8bc57eebf8d23082626fb1d7f19775c2fd31f12a 100644 (file)
@@ -4291,7 +4291,7 @@ init_proxies_list_stage2:
                                                next_id = prev_li->luid + 1;
                                }
                                next_id = listener_get_next_id(curproxy, next_id);
-                               listener->conf.id.key = listener->luid = next_id;
+                               listener->luid = next_id;
                                listener_index_id(curproxy, listener);
                        }
                        next_id++;
index 87ac573ed88f63e719917ceddf5e79eb879d8e9a..089137b665f8636e913985a8e63f1fc1b0a3aa25 100644 (file)
@@ -405,11 +405,11 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
  */
 uint listener_get_next_id(const struct proxy *px, uint from)
 {
-       const struct eb32_node *used;
+       const struct listener *li;
 
        do {
-               used = eb32_lookup_ge((struct eb_root*)&px->conf.used_listener_id, from);
-               if (!used || used->key > from)
+               li = ceb32_item_lookup_ge(&px->conf.used_listener_id, luid_node, luid, from, struct listener);
+               if (!li || li->luid > from)
                        return from; /* available */
                from++;
        } while (from);
@@ -1870,9 +1870,9 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
                                                return cfgerr;
                                        }
                                        /* assign the ID to the first one only */
-                                       new_li->luid = new_li->conf.id.key = tmp_li->luid;
+                                       ceb32_item_delete(&fe->conf.used_listener_id, luid_node, luid, tmp_li);
+                                       new_li->luid = tmp_li->luid;
                                        tmp_li->luid = 0;
-                                       eb32_delete(&tmp_li->conf.id);
                                        if (new_li->luid)
                                                listener_index_id(fe, new_li);
                                        new_li = tmp_li;
@@ -1894,9 +1894,9 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
                                return cfgerr;
                        }
                        /* assign the ID to the first one only */
-                       new_li->luid = new_li->conf.id.key = li->luid;
+                       ceb32_item_delete(&fe->conf.used_listener_id, luid_node, luid, li);
+                       new_li->luid = li->luid;
                        li->luid = 0;
-                       eb32_delete(&li->conf.id);
                        if (new_li->luid)
                                listener_index_id(fe, new_li);
                }
@@ -2220,7 +2220,6 @@ static int bind_parse_guid_prefix(char **args, int cur_arg, struct proxy *px, st
 /* parse the "id" bind keyword */
 static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
 {
-       struct eb32_node *node;
        struct listener *l, *new;
        char *error;
 
@@ -2240,16 +2239,14 @@ static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind
                memprintf(err, "'%s' : expects an integer argument, found '%s'", args[cur_arg], args[cur_arg + 1]);
                return ERR_ALERT | ERR_FATAL;
        }
-       new->conf.id.key = new->luid;
 
        if (new->luid <= 0) {
                memprintf(err, "'%s' : custom id has to be > 0", args[cur_arg]);
                return ERR_ALERT | ERR_FATAL;
        }
 
-       node = eb32_lookup(&px->conf.used_listener_id, new->luid);
-       if (node) {
-               l = container_of(node, struct listener, conf.id);
+       l = ceb32_item_lookup(&px->conf.used_listener_id, luid_node, luid, new->luid, struct listener);
+       if (l) {
                memprintf(err, "'%s' : custom id %d already used at %s:%d ('bind %s')",
                          args[cur_arg], l->luid, l->bind_conf->file, l->bind_conf->line,
                          l->bind_conf->arg);
index 7339945647427279361f465b8fc970dacb13ac62..524c886d4aefb051814984a40f3be8ed1169449b 100644 (file)
@@ -1476,7 +1476,7 @@ void init_new_proxy(struct proxy *p)
 
        MT_LIST_INIT(&p->lbprm.lb_free_list);
 
-       p->conf.used_listener_id = EB_ROOT;
+       p->conf.used_listener_id = NULL;
        p->conf.used_server_id   = EB_ROOT;
        p->used_server_addr      = NULL;