diff --git a/include/haproxy/proto_quic.h b/include/haproxy/proto_quic.h index b420f3545..b6f473c6d 100644 --- a/include/haproxy/proto_quic.h +++ b/include/haproxy/proto_quic.h @@ -28,12 +28,6 @@ extern struct protocol proto_quic4; extern struct protocol proto_quic6; -struct quic_cid_tree { - struct eb_root root; - __decl_thread(HA_RWLOCK_T lock); -}; - extern struct quic_dghdlr *quic_dghdlrs; -extern struct quic_cid_tree *quic_cid_trees; #endif /* _HAPROXY_PROTO_QUIC_H */ diff --git a/include/haproxy/quic_cid-t.h b/include/haproxy/quic_cid-t.h index ccce84497..f19ce2626 100644 --- a/include/haproxy/quic_cid-t.h +++ b/include/haproxy/quic_cid-t.h @@ -3,6 +3,12 @@ #include #include +#include + +struct quic_cid_tree { + struct eb_root root; + __decl_thread(HA_RWLOCK_T lock); +}; /* QUIC connection ID maximum length for version 1. */ #define QUIC_CID_MAXLEN 20 /* bytes */ diff --git a/include/haproxy/quic_cid.h b/include/haproxy/quic_cid.h index ac0bde0b1..87f675308 100644 --- a/include/haproxy/quic_cid.h +++ b/include/haproxy/quic_cid.h @@ -11,9 +11,12 @@ #include #include #include +#include #include #include +extern struct quic_cid_tree *quic_cid_trees; + struct quic_connection_id *new_quic_cid(struct eb_root *root, struct quic_conn *qc, const struct quic_cid *orig, diff --git a/src/proto_quic.c b/src/proto_quic.c index 64fb45c69..d03123e1e 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -52,10 +52,6 @@ /* per-thread quic datagram handlers */ struct quic_dghdlr *quic_dghdlrs; -/* global CID trees */ -#define QUIC_CID_TREES_CNT 256 -struct quic_cid_tree *quic_cid_trees; - /* Size of the internal buffer of QUIC RX buffer at the fd level */ #define QUIC_RX_BUFSZ (1UL << 18) @@ -704,17 +700,6 @@ static int quic_alloc_dghdlrs(void) MT_LIST_INIT(&dghdlr->dgrams); } - quic_cid_trees = calloc(QUIC_CID_TREES_CNT, sizeof(*quic_cid_trees)); - if (!quic_cid_trees) { - ha_alert("Failed to allocate global quic CIDs trees.\n"); - return 0; - } - - for (i = 0; i < QUIC_CID_TREES_CNT; ++i) { - HA_RWLOCK_INIT(&quic_cid_trees[i].lock); - quic_cid_trees[i].root = EB_ROOT_UNIQUE; - } - return 1; } REGISTER_POST_CHECK(quic_alloc_dghdlrs); @@ -729,8 +714,6 @@ static int quic_deallocate_dghdlrs(void) free(quic_dghdlrs); } - ha_free(&quic_cid_trees); - return 1; } REGISTER_POST_DEINIT(quic_deallocate_dghdlrs); diff --git a/src/quic_cid.c b/src/quic_cid.c index 29140d410..85caf4a6f 100644 --- a/src/quic_cid.c +++ b/src/quic_cid.c @@ -1,6 +1,10 @@ +#include + #include #include +#include +#include #include #include #include @@ -9,6 +13,30 @@ #include #include +/* *** QUIC CID handling general principles + * + * . CID global storage + * CIDs generated by haproxy and reuse by the peer as DCID are stored in a + * global tree. Tree access must only be done under lock protection. + * + * . CID global tree splitting + * To reduce thread contention, global CID tree is in reality splitted into 256 + * distinct tree instances. Each CID is assigned to a single tree instance + * based on its content. Use quic_cid_tree_idx() to retrieve the expected tree + * location for a CID. + * + * . ODCID handling + * ODCID are never stored in global CID tree. This allows to reduce tree size + * as clients are expected to switch quickly to a new haproxy assigned CID. + * This new CID value is derived by haproxy from the ODCID plus a bunch of + * other parameters. If ODCID is reused by the client, first lookup in global + * CID tree won't be successful. In this case, derive operation is performed + * again before a new tree lookup. + */ + +#define QUIC_CID_TREES_CNT 256 +struct quic_cid_tree *quic_cid_trees; + /* Initialize the stateless reset token attached to connection ID. * Returns 1 if succeeded, 0 if not. */ @@ -353,3 +381,29 @@ int qc_build_new_connection_id_frm(struct quic_conn *qc, TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc); return ret; } + +static int quic_alloc_global_cid_tree(void) +{ + int i; + + quic_cid_trees = calloc(QUIC_CID_TREES_CNT, sizeof(*quic_cid_trees)); + if (!quic_cid_trees) { + ha_alert("Failed to allocate global quic CIDs trees.\n"); + return 0; + } + + for (i = 0; i < QUIC_CID_TREES_CNT; ++i) { + HA_RWLOCK_INIT(&quic_cid_trees[i].lock); + quic_cid_trees[i].root = EB_ROOT_UNIQUE; + } + + return 1; +} +REGISTER_POST_CHECK(quic_alloc_global_cid_tree); + +static int quic_deallocate_global_cid_tree(void) +{ + ha_free(&quic_cid_trees); + return 1; +} +REGISTER_POST_DEINIT(quic_deallocate_global_cid_tree);