]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: hpack: use a pool for the hpack table
authorWilly Tarreau <w@1wt.eu>
Tue, 19 May 2020 09:31:11 +0000 (11:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 19 May 2020 09:40:39 +0000 (11:40 +0200)
Instead of using malloc/free to allocate an HPACK table, let's declare
a pool. However the HPACK size is configured by the H2 mux, so it's
also this one which allocates it after post_check.

include/common/hpack-tbl.h
src/hpack-tbl.c
src/mux_h2.c

index bb1ac06e148a208cb048fda9b3969649fa55d45d..44c0cc1178e6abfd77c5280d08ede637c9f68da0 100644 (file)
@@ -32,6 +32,7 @@
 #include <common/config.h>
 #include <common/http-hdr.h>
 #include <common/ist.h>
+#include <common/memory.h>
 
 /* Dynamic Headers Table, usable for tables up to 4GB long and values of 64kB-1.
  * The model can be improved by using offsets relative to the table entry's end
@@ -133,6 +134,7 @@ enum {
 /* static header table as in RFC7541 Appendix A. [0] unused. */
 #define HPACK_SHT_SIZE 62
 extern const struct http_hdr hpack_sht[HPACK_SHT_SIZE];
+extern struct pool_head *pool_head_hpack_tbl;
 
 extern int __hpack_dht_make_room(struct hpack_dht *dht, unsigned int needed);
 extern int hpack_dht_insert(struct hpack_dht *dht, struct ist name, struct ist value);
@@ -233,23 +235,24 @@ static inline void hpack_dht_init(struct hpack_dht *dht, uint32_t size)
        dht->used = 0;
 }
 
-/* allocate a dynamic headers table of <size> bytes and return it initialized */
-static inline struct hpack_dht *hpack_dht_alloc(uint32_t size)
+/* allocate a dynamic headers table from the pool and return it initialized */
+static inline struct hpack_dht *hpack_dht_alloc()
 {
        struct hpack_dht *dht;
 
-       dht = malloc(size);
-       if (!dht)
-               return dht;
+       if (unlikely(!pool_head_hpack_tbl))
+               return NULL;
 
-       hpack_dht_init(dht, size);
+       dht = pool_alloc(pool_head_hpack_tbl);
+       if (dht)
+               hpack_dht_init(dht, pool_head_hpack_tbl->size);
        return dht;
 }
 
 /* free a dynamic headers table */
 static inline void hpack_dht_free(struct hpack_dht *dht)
 {
-       free(dht);
+       pool_free(pool_head_hpack_tbl, dht);
 }
 
 #endif /* _COMMON_HPACK_TBL_H */
index 727ff7a17b5c01847d06e56d21da7e7a4e4217e4..effe5e01e0c131297bf55137f752a305a0da6421 100644 (file)
@@ -101,6 +101,8 @@ const struct http_hdr hpack_sht[HPACK_SHT_SIZE] = {
        [61] = { .n = IST("www-authenticate"),             .v = IST("")              },
 };
 
+struct pool_head *pool_head_hpack_tbl = NULL;
+
 /* returns the slot number of the oldest entry (tail). Must not be used on an
  * empty table.
  */
@@ -173,7 +175,7 @@ static struct hpack_dht *hpack_dht_defrag(struct hpack_dht *dht)
        /* Note: for small tables we could use alloca() instead but
         * portability especially for large tables can be problematic.
         */
-       alt_dht = hpack_dht_alloc(dht->size);
+       alt_dht = hpack_dht_alloc();
        if (!alt_dht)
                return NULL;
 
index 6b1c0d1184d45cf070a69f9096b430ff47918774..297292503f36e904ff9c5940653979cca3ebad69 100644 (file)
@@ -823,7 +823,7 @@ static int h2_init(struct connection *conn, struct proxy *prx, struct session *s
        h2c->wait_event.tasklet->context = h2c;
        h2c->wait_event.events = 0;
 
-       h2c->ddht = hpack_dht_alloc(h2_settings_header_table_size);
+       h2c->ddht = hpack_dht_alloc();
        if (!h2c->ddht)
                goto fail;
 
@@ -6195,3 +6195,18 @@ static struct cfg_kw_list cfg_kws = {ILH, {
 }};
 
 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+
+/* initialize internal structs after the config is parsed.
+ * Returns zero on success, non-zero on error.
+ */
+static int init_h2()
+{
+       pool_head_hpack_tbl = create_pool("hpack_tbl",
+                                         h2_settings_header_table_size,
+                                         MEM_F_SHARED|MEM_F_EXACT);
+       if (!pool_head_hpack_tbl)
+               return -1;
+       return 0;
+}
+
+REGISTER_POST_CHECK(init_h2);