mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-01 19:20:59 +02:00
OPTIM: quic: reduce the size of struct quic_dgram
The QUIC code can only handle IPv4 or IPv6 addresses, so using two sockaddr_storage structs wastes a lot of space in the quic_dgram struct. This is a very large overhead since this structure is written in the MPSC ring buffers before every datagram, while many of those datagrams are only 50 bytes or less. Using an union instead saves 200 bytes per datagram, increasing the capacity of the buffers significantly.
This commit is contained in:
parent
df0614b177
commit
cc231f3468
@ -7,6 +7,7 @@ extern struct pool_head *pool_head_quic_rx_packet;
|
||||
#include <import/eb64tree.h>
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/quic_cid-t.h>
|
||||
#include <haproxy/quic_sock-t.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@ -52,7 +53,7 @@ struct quic_rx_packet {
|
||||
struct eb64_node pn_node;
|
||||
volatile unsigned int refcnt;
|
||||
/* Source address of this packet. */
|
||||
struct sockaddr_storage saddr;
|
||||
union sockaddr_in46 saddr;
|
||||
unsigned int flags;
|
||||
unsigned int time_received;
|
||||
};
|
||||
|
||||
@ -21,6 +21,11 @@ struct quic_accept_queue {
|
||||
#define QUIC_DGRAM_FL_REJECT 0x00000001
|
||||
#define QUIC_DGRAM_FL_SEND_RETRY 0x00000002
|
||||
|
||||
union sockaddr_in46 {
|
||||
struct sockaddr_in in4;
|
||||
struct sockaddr_in6 in6;
|
||||
};
|
||||
|
||||
/* QUIC datagram */
|
||||
struct quic_dgram {
|
||||
enum obj_type obj_type;
|
||||
@ -29,8 +34,8 @@ struct quic_dgram {
|
||||
size_t len;
|
||||
size_t dcid_off;
|
||||
size_t dcid_len;
|
||||
struct sockaddr_storage saddr;
|
||||
struct sockaddr_storage daddr;
|
||||
union sockaddr_in46 saddr;
|
||||
union sockaddr_in46 daddr;
|
||||
struct quic_conn *qc;
|
||||
|
||||
int flags; /* QUIC_DGRAM_FL_* values */
|
||||
|
||||
@ -283,7 +283,8 @@ int quic_retry_token_check(struct quic_rx_packet *pkt,
|
||||
goto err;
|
||||
}
|
||||
|
||||
aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid, &dgram->saddr);
|
||||
aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid,
|
||||
(struct sockaddr_storage *)&dgram->saddr);
|
||||
salt = token + tokenlen - QUIC_RETRY_TOKEN_SALTLEN;
|
||||
if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
|
||||
salt, QUIC_RETRY_TOKEN_SALTLEN, sec, seclen)) {
|
||||
|
||||
@ -28,8 +28,8 @@ int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram)
|
||||
*/
|
||||
rule_sess.fe = px;
|
||||
rule_sess.listener = li;
|
||||
rule_sess.src = &dgram->saddr;
|
||||
rule_sess.dst = &dgram->daddr;
|
||||
rule_sess.src = (struct sockaddr_storage *)&dgram->saddr;
|
||||
rule_sess.dst = (struct sockaddr_storage *)&dgram->daddr;
|
||||
rule_sess.origin = &dgram->obj_type;
|
||||
|
||||
list_for_each_entry(rule, &px->quic_init_rules, list) {
|
||||
|
||||
@ -1753,7 +1753,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
prx = l->bind_conf->frontend;
|
||||
prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
|
||||
|
||||
qc = retrieve_qc_conn_from_cid(pkt, &dgram->saddr, new_tid);
|
||||
qc = retrieve_qc_conn_from_cid(pkt, (struct sockaddr_storage *)&dgram->saddr, new_tid);
|
||||
|
||||
/* quic_conn must be set to NULL if bind on another thread. */
|
||||
BUG_ON_HOT(qc && *new_tid != -1);
|
||||
@ -1788,7 +1788,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
/* Validate the token, retry or not only when connection is unknown. */
|
||||
if (!quic_token_validate(pkt, dgram, l, qc, &token_odcid)) {
|
||||
if (dgram->flags & QUIC_DGRAM_FL_SEND_RETRY) {
|
||||
if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
|
||||
if (send_retry(l->rx.fd, (struct sockaddr_storage *)&dgram->saddr, pkt, pkt->version)) {
|
||||
TRACE_ERROR("Error during Retry generation",
|
||||
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
}
|
||||
@ -1818,7 +1818,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
|
||||
TRACE_PROTO("Initial without token, sending retry",
|
||||
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
|
||||
if (send_retry(l->rx.fd, (struct sockaddr_storage *)&dgram->saddr, pkt, pkt->version)) {
|
||||
TRACE_ERROR("Error during Retry generation",
|
||||
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
goto out;
|
||||
@ -1850,7 +1850,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (quic_cid_derive_from_odcid(conn_id, &pkt->dcid, &pkt->saddr)) {
|
||||
if (quic_cid_derive_from_odcid(conn_id, &pkt->dcid, (struct sockaddr_storage *)&pkt->saddr)) {
|
||||
TRACE_ERROR("error on CID generation",
|
||||
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
pool_free(pool_head_quic_connection_id, conn_id);
|
||||
@ -1868,8 +1868,9 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
pool_free(pool_head_quic_connection_id, conn_id);
|
||||
}
|
||||
else {
|
||||
qc = qc_new_conn(l, pkt, &token_odcid,
|
||||
NULL, conn_id, &dgram->daddr, &pkt->saddr);
|
||||
qc = qc_new_conn(l, pkt, &token_odcid, NULL, conn_id,
|
||||
(struct sockaddr_storage *)&dgram->daddr,
|
||||
(struct sockaddr_storage *)&pkt->saddr);
|
||||
if (qc == NULL) {
|
||||
quic_cid_delete(conn_id); /* Removes CID from global tree as it points to a NULL qc. */
|
||||
pool_free(pool_head_quic_connection_id, conn_id);
|
||||
@ -1896,7 +1897,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
* emits stateless_reset_token in its TPs.
|
||||
*/
|
||||
TRACE_PROTO("RX non Initial pkt without connection", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
if (!send_stateless_reset(l, &dgram->saddr, pkt))
|
||||
if (!send_stateless_reset(l, (struct sockaddr_storage *)&dgram->saddr, pkt))
|
||||
TRACE_ERROR("stateless reset not sent", QUIC_EV_CONN_LPKT, qc);
|
||||
goto err;
|
||||
}
|
||||
@ -1993,7 +1994,7 @@ static int quic_rx_pkt_parse(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
*/
|
||||
if (l && !pkt->version) {
|
||||
/* unsupported version, send Negotiation packet */
|
||||
if (send_version_negotiation(l->rx.fd, &dgram->saddr, pkt)) {
|
||||
if (send_version_negotiation(l->rx.fd, (struct sockaddr_storage *)&dgram->saddr, pkt)) {
|
||||
TRACE_ERROR("VN packet not sent", QUIC_EV_CONN_LPKT);
|
||||
goto drop_silent;
|
||||
}
|
||||
@ -2489,8 +2490,10 @@ int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
|
||||
}
|
||||
|
||||
/* Detect QUIC connection migration. */
|
||||
if (li && ipcmp(&qc->peer_addr, &dgram->saddr, 1)) {
|
||||
if (qc_handle_conn_migration(qc, &dgram->saddr, &dgram->daddr)) {
|
||||
if (li && ipcmp(&qc->peer_addr, (struct sockaddr_storage *)&dgram->saddr, 1)) {
|
||||
if (qc_handle_conn_migration(qc,
|
||||
(struct sockaddr_storage *)&dgram->saddr,
|
||||
(struct sockaddr_storage *)&dgram->daddr)) {
|
||||
/* Skip the entire datagram. */
|
||||
TRACE_ERROR("error during connection migration, datagram dropped", QUIC_EV_CONN_LPKT, qc);
|
||||
pkt->len = end - pos;
|
||||
|
||||
@ -267,14 +267,16 @@ static void quic_dgram_init(struct quic_dgram *dgram,
|
||||
struct sockaddr_storage *saddr,
|
||||
struct sockaddr_storage *daddr)
|
||||
{
|
||||
BUG_ON_HOT(!is_inet_addr(saddr) || !is_inet_addr(daddr));
|
||||
|
||||
dgram->obj_type = OBJ_TYPE_DGRAM;
|
||||
dgram->owner = owner;
|
||||
dgram->buf = pos;
|
||||
dgram->len = len;
|
||||
dgram->dcid_off = dcid_off;
|
||||
dgram->dcid_len = dcid_len;
|
||||
dgram->saddr = *saddr;
|
||||
dgram->daddr = *daddr;
|
||||
memcpy(&dgram->saddr, saddr, sizeof(dgram->saddr));
|
||||
memcpy(&dgram->daddr, daddr, sizeof(dgram->daddr));
|
||||
dgram->qc = NULL;
|
||||
dgram->flags = 0;
|
||||
}
|
||||
@ -432,7 +434,8 @@ int quic_dgram_requeue(struct quic_dgram *dgram, int cid_tid)
|
||||
{
|
||||
return quic_dgram_write(dgram->buf, dgram->len, dgram->owner,
|
||||
dgram->dcid_off, dgram->dcid_len,
|
||||
&dgram->saddr, &dgram->daddr, cid_tid);
|
||||
(struct sockaddr_storage *)&dgram->saddr,
|
||||
(struct sockaddr_storage *)&dgram->daddr, cid_tid);
|
||||
}
|
||||
|
||||
/* Attempt to push a datagram to its handler thread.
|
||||
|
||||
@ -135,7 +135,7 @@ int quic_token_check(struct quic_rx_packet *pkt,
|
||||
}
|
||||
|
||||
/* Generate the AAD. */
|
||||
aadlen = ipaddrcpy(aad, &dgram->saddr);
|
||||
aadlen = ipaddrcpy(aad, (struct sockaddr_storage *)&dgram->saddr);
|
||||
rand = token + tokenlen - QUIC_TOKEN_RAND_DLEN;
|
||||
if (!quic_tls_derive_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
|
||||
rand, QUIC_TOKEN_RAND_DLEN, sec, seclen)) {
|
||||
|
||||
@ -606,6 +606,7 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
|
||||
if (mask & QUIC_EV_CONN_RCV) {
|
||||
int i;
|
||||
const struct quic_dgram *dgram = a2;
|
||||
const struct sockaddr_storage *saddr, *daddr;
|
||||
char bufaddr[INET6_ADDRSTRLEN], bufport[6];
|
||||
|
||||
if (qc) {
|
||||
@ -617,14 +618,15 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
|
||||
if (dgram) {
|
||||
chunk_appendf(&trace_buf, " dgram.len=%zu", dgram->len);
|
||||
/* Socket */
|
||||
if (dgram->saddr.ss_family == AF_INET ||
|
||||
dgram->saddr.ss_family == AF_INET6) {
|
||||
addr_to_str(&dgram->saddr, bufaddr, sizeof(bufaddr));
|
||||
port_to_str(&dgram->saddr, bufport, sizeof(bufport));
|
||||
saddr = (struct sockaddr_storage *)&dgram->saddr;
|
||||
daddr = (struct sockaddr_storage *)&dgram->daddr;
|
||||
if (saddr->ss_family == AF_INET || saddr->ss_family == AF_INET6) {
|
||||
addr_to_str(saddr, bufaddr, sizeof(bufaddr));
|
||||
port_to_str(saddr, bufport, sizeof(bufport));
|
||||
chunk_appendf(&trace_buf, "saddr=%s:%s ", bufaddr, bufport);
|
||||
|
||||
addr_to_str(&dgram->daddr, bufaddr, sizeof(bufaddr));
|
||||
port_to_str(&dgram->daddr, bufport, sizeof(bufport));
|
||||
addr_to_str(daddr, bufaddr, sizeof(bufaddr));
|
||||
port_to_str(daddr, bufport, sizeof(bufport));
|
||||
chunk_appendf(&trace_buf, "daddr=%s:%s ", bufaddr, bufport);
|
||||
}
|
||||
/* DCID */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user