mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 22:31:28 +02:00
MEDIUM: quic: Retransmission functions rework
qc_prep_fast_retrans() and qc_prep_hdshk_fast_retrans() are modified to take two list of frames as parameters. Two lists are needed for qc_prep_hdshk_fast_retrans() to build datagrams with two packets during handshake. qc_prep_fast_retrans() needs two lists of frames to be used to send two datagrams with one list by datagram.
This commit is contained in:
parent
a9568411e4
commit
e248e378c8
@ -2442,22 +2442,24 @@ static void qc_dup_pkt_frms(struct quic_conn *qc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare a fast retransmission from <qel> encryption level */
|
/* Prepare a fast retransmission from <qel> encryption level */
|
||||||
static void qc_prep_fast_retrans(struct quic_enc_level *qel,
|
static void qc_prep_fast_retrans(struct quic_conn *qc,
|
||||||
struct quic_conn *qc)
|
struct quic_enc_level *qel,
|
||||||
|
struct list *frms1, struct list *frms2)
|
||||||
{
|
{
|
||||||
struct eb_root *pkts = &qel->pktns->tx.pkts;
|
struct eb_root *pkts = &qel->pktns->tx.pkts;
|
||||||
|
struct list *frms = frms1;
|
||||||
struct eb64_node *node;
|
struct eb64_node *node;
|
||||||
struct quic_tx_packet *pkt;
|
struct quic_tx_packet *pkt;
|
||||||
|
|
||||||
pkt = NULL;
|
pkt = NULL;
|
||||||
pkts = &qel->pktns->tx.pkts;
|
|
||||||
node = eb64_first(pkts);
|
node = eb64_first(pkts);
|
||||||
/* Skip the empty packet (they have already been retransmitted) */
|
start:
|
||||||
while (node) {
|
while (node) {
|
||||||
pkt = eb64_entry(&node->node, struct quic_tx_packet, pn_node);
|
pkt = eb64_entry(node, struct quic_tx_packet, pn_node);
|
||||||
|
node = eb64_next(node);
|
||||||
|
/* Skip the empty and coalesced packets */
|
||||||
if (!LIST_ISEMPTY(&pkt->frms) && !(pkt->flags & QUIC_FL_TX_PACKET_COALESCED))
|
if (!LIST_ISEMPTY(&pkt->frms) && !(pkt->flags & QUIC_FL_TX_PACKET_COALESCED))
|
||||||
break;
|
break;
|
||||||
node = eb64_next(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pkt)
|
if (!pkt)
|
||||||
@ -2472,20 +2474,24 @@ static void qc_prep_fast_retrans(struct quic_enc_level *qel,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qc_requeue_nacked_pkt_tx_frms(qc, &pkt->frms, &qel->pktns->tx.frms);
|
TRACE_PROTO("duplicating packet", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
|
||||||
|
qc_dup_pkt_frms(qc, &pkt->frms, frms);
|
||||||
|
if (frms == frms1 && frms2) {
|
||||||
|
frms = frms2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare a fast retransmission during handshake after a client
|
/* Prepare a fast retransmission during a handshake after a client
|
||||||
* has resent Initial packets. According to the RFC a server may retransmit
|
* has resent Initial packets. According to the RFC a server may retransmit
|
||||||
* up to two datagrams of Initial packets if did not receive all Initial packets
|
* Initial packets send them coalescing with others (Handshake here).
|
||||||
* and resend them coalescing with others (Handshake here).
|
* (Listener only function).
|
||||||
* (Listener only).
|
|
||||||
*/
|
*/
|
||||||
static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc)
|
static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
|
||||||
|
struct list *ifrms, struct list *hfrms)
|
||||||
{
|
{
|
||||||
struct list itmp = LIST_HEAD_INIT(itmp);
|
struct list itmp = LIST_HEAD_INIT(itmp);
|
||||||
struct list htmp = LIST_HEAD_INIT(htmp);
|
struct list htmp = LIST_HEAD_INIT(htmp);
|
||||||
struct quic_frame *frm, *frmbak;
|
|
||||||
|
|
||||||
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
|
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
|
||||||
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
|
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
|
||||||
@ -2495,15 +2501,6 @@ static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc)
|
|||||||
struct quic_tx_packet *pkt;
|
struct quic_tx_packet *pkt;
|
||||||
struct list *tmp = &itmp;
|
struct list *tmp = &itmp;
|
||||||
|
|
||||||
/* Do not probe from a packet number space if some probing
|
|
||||||
* was already asked.
|
|
||||||
*/
|
|
||||||
if (qel->pktns->tx.pto_probe) {
|
|
||||||
qel = hqel;
|
|
||||||
if (qel->pktns->tx.pto_probe)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
start:
|
start:
|
||||||
pkt = NULL;
|
pkt = NULL;
|
||||||
pkts = &qel->pktns->tx.pkts;
|
pkts = &qel->pktns->tx.pkts;
|
||||||
@ -2530,21 +2527,8 @@ static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc)
|
|||||||
|
|
||||||
qel->pktns->tx.pto_probe += 1;
|
qel->pktns->tx.pto_probe += 1;
|
||||||
requeue:
|
requeue:
|
||||||
list_for_each_entry_safe(frm, frmbak, &pkt->frms, list) {
|
TRACE_PROTO("duplicating packet", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
|
||||||
struct quic_frame *dup_frm;
|
qc_dup_pkt_frms(qc, &pkt->frms, tmp);
|
||||||
|
|
||||||
|
|
||||||
dup_frm = pool_alloc(pool_head_quic_frame);
|
|
||||||
if (!dup_frm) {
|
|
||||||
TRACE_PROTO("could not duplicate frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_PROTO("to resend frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
|
|
||||||
*dup_frm = *frm;
|
|
||||||
LIST_APPEND(tmp, &dup_frm->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qel == iqel) {
|
if (qel == iqel) {
|
||||||
if (pkt->next && pkt->next->type == QUIC_PACKET_TYPE_HANDSHAKE) {
|
if (pkt->next && pkt->next->type == QUIC_PACKET_TYPE_HANDSHAKE) {
|
||||||
pkt = pkt->next;
|
pkt = pkt->next;
|
||||||
@ -2552,15 +2536,11 @@ static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc)
|
|||||||
hqel->pktns->tx.pto_probe += 1;
|
hqel->pktns->tx.pto_probe += 1;
|
||||||
goto requeue;
|
goto requeue;
|
||||||
}
|
}
|
||||||
|
|
||||||
qel = hqel;
|
|
||||||
tmp = &htmp;
|
|
||||||
goto start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
LIST_SPLICE(&iqel->pktns->tx.frms, &itmp);
|
LIST_SPLICE(ifrms, &itmp);
|
||||||
LIST_SPLICE(&hqel->pktns->tx.frms, &htmp);
|
LIST_SPLICE(hfrms, &htmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse all the frames of <pkt> QUIC packet for QUIC connection with <ctx>
|
/* Parse all the frames of <pkt> QUIC packet for QUIC connection with <ctx>
|
||||||
@ -2761,8 +2741,12 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
|
|||||||
/* Flag this packet number space as having received a packet. */
|
/* Flag this packet number space as having received a packet. */
|
||||||
qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
|
qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
|
||||||
|
|
||||||
if (fast_retrans)
|
if (fast_retrans) {
|
||||||
qc_prep_hdshk_fast_retrans(qc);
|
struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
|
||||||
|
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
|
||||||
|
|
||||||
|
qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms);
|
||||||
|
}
|
||||||
|
|
||||||
/* The server must switch from INITIAL to HANDSHAKE handshake state when it
|
/* The server must switch from INITIAL to HANDSHAKE handshake state when it
|
||||||
* has successfully parse a Handshake packet. The Initial encryption must also
|
* has successfully parse a Handshake packet. The Initial encryption must also
|
||||||
|
Loading…
x
Reference in New Issue
Block a user