MINOR: quic: Convert quic_dgram_read() into a task
quic_dgram_read() parses all the QUIC packets from a UDP datagram. It is the best candidate to be converted into a task, because is processing data unit is the UDP datagram received by the QUIC sock i/o handler. If correct, this datagram is added to the context of a task, quic_lstnr_dghdlr(), a conversion of quic_dgram_read() into a task. This task pop a datagram from an mt_list and passes it among to the packet handler (quic_lstnr_pkt_rcv()). Modify the quic_dgram struct to play the role of the old quic_dgram_ctx struct when passed to quic_lstnr_pkt_rcv(). Modify the datagram handlers allocation to set their tasks to quic_lstnr_dghdlr().
This commit is contained in:
parent
220894a5d6
commit
25bc8875d7
@ -422,10 +422,15 @@ struct quic_pktns {
|
|||||||
|
|
||||||
/* QUIC datagram */
|
/* QUIC datagram */
|
||||||
struct quic_dgram {
|
struct quic_dgram {
|
||||||
|
void *owner;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
unsigned char *dcid;
|
||||||
|
size_t dcid_len;
|
||||||
struct sockaddr_storage saddr;
|
struct sockaddr_storage saddr;
|
||||||
|
struct quic_conn *qc;
|
||||||
struct list list;
|
struct list list;
|
||||||
|
struct mt_list mt_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The QUIC packet numbers are 62-bits integers */
|
/* The QUIC packet numbers are 62-bits integers */
|
||||||
|
@ -1184,6 +1184,7 @@ void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
|
|||||||
|
|
||||||
void quic_set_tls_alert(struct quic_conn *qc, int alert);
|
void quic_set_tls_alert(struct quic_conn *qc, int alert);
|
||||||
int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len);
|
int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len);
|
||||||
|
struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state);
|
||||||
int quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner,
|
int quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner,
|
||||||
struct sockaddr_storage *saddr, struct list *dgrams);
|
struct sockaddr_storage *saddr, struct list *dgrams);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <haproxy/quic_sock.h>
|
#include <haproxy/quic_sock.h>
|
||||||
#include <haproxy/sock_inet.h>
|
#include <haproxy/sock_inet.h>
|
||||||
#include <haproxy/tools.h>
|
#include <haproxy/tools.h>
|
||||||
#include <haproxy/xprt_quic-t.h>
|
#include <haproxy/xprt_quic.h>
|
||||||
|
|
||||||
|
|
||||||
static void quic_add_listener(struct protocol *proto, struct listener *listener);
|
static void quic_add_listener(struct protocol *proto, struct listener *listener);
|
||||||
@ -630,6 +630,7 @@ static int quic_alloc_dghdlrs_listener(struct listener *l)
|
|||||||
|
|
||||||
dghdlr->task->tid = i;
|
dghdlr->task->tid = i;
|
||||||
dghdlr->task->context = dghdlr;
|
dghdlr->task->context = dghdlr;
|
||||||
|
dghdlr->task->process = quic_lstnr_dghdlr;
|
||||||
dghdlr->odcids = EB_ROOT_UNIQUE;
|
dghdlr->odcids = EB_ROOT_UNIQUE;
|
||||||
dghdlr->cids = EB_ROOT_UNIQUE;
|
dghdlr->cids = EB_ROOT_UNIQUE;
|
||||||
MT_LIST_INIT(&dghdlr->dgrams);
|
MT_LIST_INIT(&dghdlr->dgrams);
|
||||||
|
119
src/xprt_quic.c
119
src/xprt_quic.c
@ -4191,9 +4191,8 @@ int qc_conn_alloc_ssl_ctx(struct quic_conn *qc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
||||||
struct quic_rx_packet *pkt,
|
struct quic_rx_packet *pkt, int first_pkt,
|
||||||
struct quic_dgram_ctx *dgram_ctx,
|
struct quic_dgram *dgram)
|
||||||
struct sockaddr_storage *saddr)
|
|
||||||
{
|
{
|
||||||
unsigned char *beg, *payload;
|
unsigned char *beg, *payload;
|
||||||
struct quic_conn *qc, *qc_to_purge = NULL;
|
struct quic_conn *qc, *qc_to_purge = NULL;
|
||||||
@ -4222,7 +4221,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = dgram_ctx->owner;
|
l = dgram->owner;
|
||||||
/* Header form */
|
/* Header form */
|
||||||
qc_parse_hd_form(pkt, *buf++, &long_header);
|
qc_parse_hd_form(pkt, *buf++, &long_header);
|
||||||
if (long_header) {
|
if (long_header) {
|
||||||
@ -4233,6 +4232,16 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When multiple QUIC packets are coalesced on the same UDP datagram,
|
||||||
|
* they must have the same DCID.
|
||||||
|
*/
|
||||||
|
if (!first_pkt &&
|
||||||
|
(pkt->dcid.len != dgram->dcid_len ||
|
||||||
|
memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
|
||||||
|
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Retry of Version Negotiation packets are only sent by servers */
|
/* Retry of Version Negotiation packets are only sent by servers */
|
||||||
if (pkt->type == QUIC_PACKET_TYPE_RETRY || !pkt->version) {
|
if (pkt->type == QUIC_PACKET_TYPE_RETRY || !pkt->version) {
|
||||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
|
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
|
||||||
@ -4242,7 +4251,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
/* RFC9000 6. Version Negotiation */
|
/* RFC9000 6. Version Negotiation */
|
||||||
if (!qc_pkt_is_supported_version(pkt)) {
|
if (!qc_pkt_is_supported_version(pkt)) {
|
||||||
/* unsupported version, send Negotiation packet */
|
/* unsupported version, send Negotiation packet */
|
||||||
if (send_version_negotiation(l->rx.fd, saddr, pkt)) {
|
if (send_version_negotiation(l->rx.fd, &dgram->saddr, pkt)) {
|
||||||
TRACE_PROTO("Error on Version Negotiation sending", QUIC_EV_CONN_LPKT);
|
TRACE_PROTO("Error on Version Negotiation sending", QUIC_EV_CONN_LPKT);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -4273,7 +4282,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
*/
|
*/
|
||||||
if (!token_len && l->bind_conf->quic_force_retry) {
|
if (!token_len && l->bind_conf->quic_force_retry) {
|
||||||
TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
|
TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
|
||||||
if (send_retry(l->rx.fd, saddr, pkt)) {
|
if (send_retry(l->rx.fd, &dgram->saddr, pkt)) {
|
||||||
TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
|
TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -4301,7 +4310,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
payload = buf;
|
payload = buf;
|
||||||
pkt->len = len + payload - beg;
|
pkt->len = len + payload - beg;
|
||||||
|
|
||||||
qc = retrieve_qc_conn_from_cid(pkt, l, saddr);
|
qc = retrieve_qc_conn_from_cid(pkt, l, &dgram->saddr);
|
||||||
if (!qc) {
|
if (!qc) {
|
||||||
int ipv4;
|
int ipv4;
|
||||||
struct quic_cid *odcid;
|
struct quic_cid *odcid;
|
||||||
@ -4314,8 +4323,8 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->saddr = *saddr;
|
pkt->saddr = dgram->saddr;
|
||||||
ipv4 = saddr->ss_family == AF_INET;
|
ipv4 = dgram->saddr.ss_family == AF_INET;
|
||||||
qc = qc_new_conn(pkt->version, ipv4,
|
qc = qc_new_conn(pkt->version, ipv4,
|
||||||
pkt->dcid.data, pkt->dcid.len, pkt->dcid.addrlen,
|
pkt->dcid.data, pkt->dcid.len, pkt->dcid.addrlen,
|
||||||
pkt->scid.data, pkt->scid.len, 1, l);
|
pkt->scid.data, pkt->scid.len, 1, l);
|
||||||
@ -4407,13 +4416,24 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
|
|
||||||
memcpy(pkt->dcid.data, buf, QUIC_HAP_CID_LEN);
|
memcpy(pkt->dcid.data, buf, QUIC_HAP_CID_LEN);
|
||||||
pkt->dcid.len = QUIC_HAP_CID_LEN;
|
pkt->dcid.len = QUIC_HAP_CID_LEN;
|
||||||
|
|
||||||
|
/* When multiple QUIC packets are coalesced on the same UDP datagram,
|
||||||
|
* they must have the same DCID.
|
||||||
|
*/
|
||||||
|
if (!first_pkt &&
|
||||||
|
(pkt->dcid.len != dgram->dcid_len ||
|
||||||
|
memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
|
||||||
|
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
buf += QUIC_HAP_CID_LEN;
|
buf += QUIC_HAP_CID_LEN;
|
||||||
|
|
||||||
/* A short packet is the last one of a UDP datagram. */
|
/* A short packet is the last one of a UDP datagram. */
|
||||||
payload = buf;
|
payload = buf;
|
||||||
pkt->len = end - beg;
|
pkt->len = end - beg;
|
||||||
|
|
||||||
qc = retrieve_qc_conn_from_cid(pkt, l, saddr);
|
qc = retrieve_qc_conn_from_cid(pkt, l, &dgram->saddr);
|
||||||
if (!qc) {
|
if (!qc) {
|
||||||
size_t pktlen = end - buf;
|
size_t pktlen = end - buf;
|
||||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, NULL, pkt, &pktlen);
|
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, NULL, pkt, &pktlen);
|
||||||
@ -4430,27 +4450,19 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
* This check must be done after the final update to pkt.len to
|
* This check must be done after the final update to pkt.len to
|
||||||
* properly drop the packet on failure.
|
* properly drop the packet on failure.
|
||||||
*/
|
*/
|
||||||
if (!dgram_ctx->dcid.len) {
|
if (first_pkt && !quic_peer_validated_addr(qc) &&
|
||||||
memcpy(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len);
|
HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
|
||||||
dgram_ctx->dcid.len = pkt->dcid.len;
|
TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
|
||||||
if (!quic_peer_validated_addr(qc) &&
|
QUIC_EV_CONN_LPKT, qc);
|
||||||
HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
|
/* Reset the anti-amplification bit. It will be set again
|
||||||
TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
|
* when sending the next packet if reached again.
|
||||||
QUIC_EV_CONN_LPKT, qc);
|
*/
|
||||||
/* Reset the anti-amplification bit. It will be set again
|
HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT);
|
||||||
* when sending the next packet if reached again.
|
HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
|
||||||
*/
|
io_cb_wakeup = 1;
|
||||||
HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT);
|
|
||||||
HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
|
|
||||||
io_cb_wakeup = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (memcmp(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len)) {
|
|
||||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
dgram_ctx->qc = qc;
|
|
||||||
|
|
||||||
|
dgram->qc = qc;
|
||||||
|
|
||||||
if (HA_ATOMIC_LOAD(&qc->err_code)) {
|
if (HA_ATOMIC_LOAD(&qc->err_code)) {
|
||||||
TRACE_PROTO("Connection error", QUIC_EV_CONN_LPKT, qc);
|
TRACE_PROTO("Connection error", QUIC_EV_CONN_LPKT, qc);
|
||||||
@ -5360,19 +5372,20 @@ static void __quic_conn_deinit(void)
|
|||||||
* as owner calling <func> function.
|
* as owner calling <func> function.
|
||||||
* Return the number of bytes read if succeeded, -1 if not.
|
* Return the number of bytes read if succeeded, -1 if not.
|
||||||
*/
|
*/
|
||||||
static ssize_t quic_dgram_read(unsigned char *buf, size_t len, void *owner,
|
struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state)
|
||||||
struct sockaddr_storage *saddr, qpkt_read_func *func)
|
|
||||||
{
|
{
|
||||||
unsigned char *pos;
|
unsigned char *pos;
|
||||||
const unsigned char *end;
|
const unsigned char *end;
|
||||||
struct quic_dgram_ctx dgram_ctx = {
|
struct quic_dghdlr *dghdlr = ctx;
|
||||||
.qc = NULL,
|
struct quic_dgram *dgram;
|
||||||
.dcid.len = 0,
|
int first_pkt = 1;
|
||||||
.owner = owner,
|
|
||||||
};
|
|
||||||
|
|
||||||
pos = buf;
|
dgram = MT_LIST_POP(&dghdlr->dgrams, typeof(dgram), mt_list);
|
||||||
end = pos + len;
|
if (!dgram)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pos = dgram->buf;
|
||||||
|
end = pos + dgram->len;
|
||||||
do {
|
do {
|
||||||
int ret;
|
int ret;
|
||||||
struct quic_rx_packet *pkt;
|
struct quic_rx_packet *pkt;
|
||||||
@ -5382,7 +5395,8 @@ static ssize_t quic_dgram_read(unsigned char *buf, size_t len, void *owner,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
quic_rx_packet_refinc(pkt);
|
quic_rx_packet_refinc(pkt);
|
||||||
ret = func(pos, end, pkt, &dgram_ctx, saddr);
|
ret = qc_lstnr_pkt_rcv(pos, end, pkt, first_pkt, dgram);
|
||||||
|
first_pkt = 0;
|
||||||
pos += pkt->len;
|
pos += pkt->len;
|
||||||
quic_rx_packet_refdec(pkt);
|
quic_rx_packet_refdec(pkt);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
@ -5393,13 +5407,13 @@ static ssize_t quic_dgram_read(unsigned char *buf, size_t len, void *owner,
|
|||||||
/* Increasing the received bytes counter by the UDP datagram length
|
/* Increasing the received bytes counter by the UDP datagram length
|
||||||
* if this datagram could be associated to a connection.
|
* if this datagram could be associated to a connection.
|
||||||
*/
|
*/
|
||||||
if (dgram_ctx.qc)
|
if (dgram->qc)
|
||||||
dgram_ctx.qc->rx.bytes += len;
|
dgram->qc->rx.bytes += dgram->len;
|
||||||
|
|
||||||
return pos - buf;
|
return t;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return -1;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retreive the DCID from a QUIC datagram or packet with <buf> as first octet.
|
/* Retreive the DCID from a QUIC datagram or packet with <buf> as first octet.
|
||||||
@ -5441,22 +5455,33 @@ int quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner,
|
|||||||
struct quic_dgram *dgram;
|
struct quic_dgram *dgram;
|
||||||
unsigned char *dcid;
|
unsigned char *dcid;
|
||||||
size_t dcid_len;
|
size_t dcid_len;
|
||||||
|
int tid;
|
||||||
|
struct listener *l = owner;
|
||||||
|
|
||||||
if (!len || !quic_get_dgram_dcid(buf, buf + len, &dcid, &dcid_len))
|
if (!len || !quic_get_dgram_dcid(buf, buf + len, &dcid, &dcid_len))
|
||||||
goto out;
|
goto err;
|
||||||
|
|
||||||
dgram = pool_alloc(pool_head_quic_dgram);
|
dgram = pool_alloc(pool_head_quic_dgram);
|
||||||
if (!dgram)
|
if (!dgram)
|
||||||
goto out;
|
goto err;
|
||||||
|
|
||||||
|
tid = quic_get_cid_tid(dcid);
|
||||||
|
/* All the members must be initialized! */
|
||||||
|
dgram->owner = owner;
|
||||||
dgram->buf = buf;
|
dgram->buf = buf;
|
||||||
dgram->len = len;
|
dgram->len = len;
|
||||||
|
dgram->dcid = dcid;
|
||||||
|
dgram->dcid_len = dcid_len;
|
||||||
dgram->saddr = *saddr;
|
dgram->saddr = *saddr;
|
||||||
|
dgram->qc = NULL;
|
||||||
LIST_APPEND(dgrams, &dgram->list);
|
LIST_APPEND(dgrams, &dgram->list);
|
||||||
|
MT_LIST_APPEND(&l->rx.dghdlrs[tid]->dgrams, &dgram->mt_list);
|
||||||
|
|
||||||
return quic_dgram_read(buf, len, owner, saddr, qc_lstnr_pkt_rcv);
|
tasklet_wakeup(l->rx.dghdlrs[tid]->task);
|
||||||
|
|
||||||
out:
|
return 1;
|
||||||
|
|
||||||
|
err:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user