MEDIUM: hpack: use a pool for the hpack table

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.
This commit is contained in:
Willy Tarreau 2020-05-19 11:31:11 +02:00
parent 957ec59571
commit 2bdcc70fa7
3 changed files with 29 additions and 9 deletions

View File

@ -32,6 +32,7 @@
#include <common/config.h> #include <common/config.h>
#include <common/http-hdr.h> #include <common/http-hdr.h>
#include <common/ist.h> #include <common/ist.h>
#include <common/memory.h>
/* Dynamic Headers Table, usable for tables up to 4GB long and values of 64kB-1. /* 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 * 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. */ /* static header table as in RFC7541 Appendix A. [0] unused. */
#define HPACK_SHT_SIZE 62 #define HPACK_SHT_SIZE 62
extern const struct http_hdr hpack_sht[HPACK_SHT_SIZE]; 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_make_room(struct hpack_dht *dht, unsigned int needed);
extern int hpack_dht_insert(struct hpack_dht *dht, struct ist name, struct ist value); 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; dht->used = 0;
} }
/* allocate a dynamic headers table of <size> bytes and return it initialized */ /* allocate a dynamic headers table from the pool and return it initialized */
static inline struct hpack_dht *hpack_dht_alloc(uint32_t size) static inline struct hpack_dht *hpack_dht_alloc()
{ {
struct hpack_dht *dht; struct hpack_dht *dht;
dht = malloc(size); if (unlikely(!pool_head_hpack_tbl))
if (!dht) return NULL;
return dht;
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; return dht;
} }
/* free a dynamic headers table */ /* free a dynamic headers table */
static inline void hpack_dht_free(struct hpack_dht *dht) static inline void hpack_dht_free(struct hpack_dht *dht)
{ {
free(dht); pool_free(pool_head_hpack_tbl, dht);
} }
#endif /* _COMMON_HPACK_TBL_H */ #endif /* _COMMON_HPACK_TBL_H */

View File

@ -101,6 +101,8 @@ const struct http_hdr hpack_sht[HPACK_SHT_SIZE] = {
[61] = { .n = IST("www-authenticate"), .v = IST("") }, [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 /* returns the slot number of the oldest entry (tail). Must not be used on an
* empty table. * 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 /* Note: for small tables we could use alloca() instead but
* portability especially for large tables can be problematic. * portability especially for large tables can be problematic.
*/ */
alt_dht = hpack_dht_alloc(dht->size); alt_dht = hpack_dht_alloc();
if (!alt_dht) if (!alt_dht)
return NULL; return NULL;

View 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.tasklet->context = h2c;
h2c->wait_event.events = 0; h2c->wait_event.events = 0;
h2c->ddht = hpack_dht_alloc(h2_settings_header_table_size); h2c->ddht = hpack_dht_alloc();
if (!h2c->ddht) if (!h2c->ddht)
goto fail; goto fail;
@ -6195,3 +6195,18 @@ static struct cfg_kw_list cfg_kws = {ILH, {
}}; }};
INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); 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);