mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-23 06:41:32 +02:00
MINOR: quic: qc_prep_app_pkts() implementation
We want to get rid of the code used during the handshake step. qc_prep_app_pkts() aim is to build short packets which are also datagrams. Make quic_conn_app_io_cb() call this new function to prepare short packets.
This commit is contained in:
parent
1455113e93
commit
1c5968b275
120
src/xprt_quic.c
120
src/xprt_quic.c
@ -2453,6 +2453,124 @@ static inline void qc_set_dg(struct cbuf *cbuf,
|
|||||||
cb_add(cbuf, dglen + sizeof dglen + sizeof pkt);
|
cb_add(cbuf, dglen + sizeof dglen + sizeof pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare as much as possible short packets which are also datagrams into <qr>
|
||||||
|
* ring buffer for the QUIC connection with <ctx> as I/O handler context.
|
||||||
|
* A header made of two fields is added to each datagram: the datagram length followed
|
||||||
|
* by the address of the first packet in this datagram.
|
||||||
|
* Returns 1 if succeeded, or 0 if something wrong happened.
|
||||||
|
*/
|
||||||
|
static int qc_prep_app_pkts(struct quic_conn *qc, struct qring *qr)
|
||||||
|
{
|
||||||
|
struct quic_enc_level *qel;
|
||||||
|
struct cbuf *cbuf;
|
||||||
|
unsigned char *end_buf, *end, *pos, *spos;
|
||||||
|
struct quic_tx_packet *pkt;
|
||||||
|
size_t total;
|
||||||
|
size_t dg_headlen;
|
||||||
|
|
||||||
|
TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
|
||||||
|
/* Each datagram is prepended with its length followed by the
|
||||||
|
* address of the first packet in the datagram.
|
||||||
|
*/
|
||||||
|
dg_headlen = sizeof(uint16_t) + sizeof pkt;
|
||||||
|
qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
|
||||||
|
total = 0;
|
||||||
|
start:
|
||||||
|
cbuf = qr->cbuf;
|
||||||
|
spos = pos = cb_wr(cbuf);
|
||||||
|
/* Leave at least <sizeof(uint16_t)> bytes at the end of this buffer
|
||||||
|
* to ensure there is enough room to mark the end of prepared
|
||||||
|
* contiguous data with a zero length.
|
||||||
|
*/
|
||||||
|
end_buf = pos + cb_contig_space(cbuf) - sizeof(uint16_t);
|
||||||
|
while (end_buf - pos >= (int)qc->path->mtu + dg_headlen) {
|
||||||
|
int err, probe, ack, cc;
|
||||||
|
|
||||||
|
TRACE_POINT(QUIC_EV_CONN_PHPKTS, qc, qel);
|
||||||
|
probe = ack = 0;
|
||||||
|
cc = HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE;
|
||||||
|
if (!cc) {
|
||||||
|
probe = qel->pktns->tx.pto_probe;
|
||||||
|
ack = HA_ATOMIC_BTR(&qel->pktns->flags, QUIC_FL_PKTNS_ACK_REQUIRED_BIT);
|
||||||
|
}
|
||||||
|
/* Do not build any more packet if the TX secrets are not available or
|
||||||
|
* if there is nothing to send, i.e. if no CONNECTION_CLOSE or ACK are required
|
||||||
|
* and if there is no more packets to send upon PTO expiration
|
||||||
|
* and if there is no more CRYPTO data available or in flight
|
||||||
|
* congestion control limit is reached for prepared data
|
||||||
|
*/
|
||||||
|
if (!(qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_SET) ||
|
||||||
|
(!cc && !ack && !probe &&
|
||||||
|
(LIST_ISEMPTY(&qel->pktns->tx.frms) ||
|
||||||
|
qc->path->prep_in_flight >= qc->path->cwnd))) {
|
||||||
|
TRACE_DEVEL("nothing more to do", QUIC_EV_CONN_PHPKTS, qc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Leave room for the datagram header */
|
||||||
|
pos += dg_headlen;
|
||||||
|
if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
|
||||||
|
end = pos + QUIC_MIN(qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
end = pos + qc->path->mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt = qc_build_pkt(&pos, end, qel, qc, 0, 0,
|
||||||
|
QUIC_PACKET_TYPE_SHORT, ack, probe, cc, &err);
|
||||||
|
/* Restore the PTO dgrams counter if a packet could not be built */
|
||||||
|
if (err < 0) {
|
||||||
|
if (ack)
|
||||||
|
HA_ATOMIC_BTS(&qel->pktns->flags, QUIC_FL_PKTNS_ACK_REQUIRED_BIT);
|
||||||
|
}
|
||||||
|
switch (err) {
|
||||||
|
case -2:
|
||||||
|
goto err;
|
||||||
|
case -1:
|
||||||
|
goto out;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is to please to GCC. We cannot have (err >= 0 && !pkt) */
|
||||||
|
if (!pkt)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
total += pkt->len;
|
||||||
|
/* Set the current datagram as prepared into <cbuf>. */
|
||||||
|
qc_set_dg(cbuf, pkt->len, pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_build:
|
||||||
|
/* Reset <wr> writer index if in front of <rd> index */
|
||||||
|
if (end_buf - pos < (int)qc->path->mtu + dg_headlen) {
|
||||||
|
int rd = HA_ATOMIC_LOAD(&cbuf->rd);
|
||||||
|
|
||||||
|
TRACE_DEVEL("buffer full", QUIC_EV_CONN_PHPKTS, qc);
|
||||||
|
if (cb_contig_space(cbuf) >= sizeof(uint16_t)) {
|
||||||
|
if ((pos != spos && cbuf->wr > rd) || (pos == spos && rd <= cbuf->wr)) {
|
||||||
|
/* Mark the end of contiguous data for the reader */
|
||||||
|
write_u16(cb_wr(cbuf), 0);
|
||||||
|
cb_add(cbuf, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rd && rd <= cbuf->wr) {
|
||||||
|
cb_wr_reset(cbuf);
|
||||||
|
/* Let's try to reuse this buffer */
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
|
||||||
|
return total;
|
||||||
|
|
||||||
|
err:
|
||||||
|
TRACE_DEVEL("leaving in error", QUIC_EV_CONN_PHPKTS, qc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare as much as possible packets into <qr> ring buffer for
|
/* Prepare as much as possible packets into <qr> ring buffer for
|
||||||
* the QUIC connection with <ctx> as I/O handler context, possibly concatenating
|
* the QUIC connection with <ctx> as I/O handler context, possibly concatenating
|
||||||
* several packets in the same datagram. A header made of two fields is added
|
* several packets in the same datagram. A header made of two fields is added
|
||||||
@ -3168,7 +3286,7 @@ static int qc_send_app_pkts(struct quic_conn *qc)
|
|||||||
/* Never happens */
|
/* Never happens */
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ret = qc_prep_pkts(qc, qr, QUIC_TLS_ENC_LEVEL_APP, QUIC_TLS_ENC_LEVEL_NONE);
|
ret = qc_prep_app_pkts(qc, qr);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
goto err;
|
goto err;
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user