QUIC TXP: Refactor TXP-related deadline handling into TXP

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21458)
This commit is contained in:
Hugo Landau 2023-07-13 11:36:24 +01:00 committed by Tomas Mraz
parent 9441624ee9
commit c206f2aa62
3 changed files with 53 additions and 13 deletions

View File

@ -90,6 +90,18 @@ typedef struct quic_txp_status_st {
int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
QUIC_TXP_STATUS *status);
/*
* Returns a deadline after which a call to ossl_quic_tx_packetiser_generate()
* might succeed even if it did not previously. This may return
* ossl_time_infinite() if there is no such deadline currently applicable. It
* returns ossl_time_zero() if there is (potentially) more data to be generated
* immediately. The value returned is liable to change after any call to
* ossl_quic_tx_packetiser_generate() (or after ACKM or CC state changes). Note
* that ossl_quic_tx_packetiser_generate() can also start to succeed for other
* non-chronological reasons, such as changes to send stream buffers, etc.
*/
OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp);
/*
* Set the token used in Initial packets. The callback is called when the buffer
* is no longer needed; for example, when the TXP is freed or when this function

View File

@ -2126,9 +2126,7 @@ static int ch_tx(QUIC_CHANNEL *ch)
* Best effort. In particular if TXP fails for some reason we should still
* flush any queued packets which we already generated.
*/
switch (ossl_quic_tx_packetiser_generate(ch->txp,
TX_PACKETISER_ARCHETYPE_NORMAL,
&status)) {
switch (ossl_quic_tx_packetiser_generate(ch->txp, &status)) {
case TX_PACKETISER_RES_SENT_PKT:
ch->have_sent_any_pkt = 1; /* Packet was sent */
@ -2212,11 +2210,9 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
}
}
/* When will CC let us send more? */
if (ossl_quic_tx_packetiser_has_pending(ch->txp, TX_PACKETISER_ARCHETYPE_NORMAL,
TX_PACKETISER_BYPASS_CC))
deadline = ossl_time_min(deadline,
ch->cc_method->get_wakeup_deadline(ch->cc_data));
/* Apply TXP wakeup deadline. */
deadline = ossl_time_min(deadline,
ossl_quic_tx_packetiser_get_deadline(ch->txp));
/* Is the terminating timer armed? */
if (ossl_quic_channel_is_terminating(ch))

View File

@ -440,7 +440,8 @@ static int txp_pkt_append_padding(struct txp_pkt *pkt,
OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes);
static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, struct txp_pkt *pkt,
uint32_t archetype);
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp);
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
uint64_t cc_limit);
OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args)
{
@ -712,7 +713,7 @@ int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
ossl_qtx_finish_dgram(txp->args.qtx);
/* 1. Archetype Selection */
archetype = txp_determine_archetype(txp);
archetype = txp_determine_archetype(txp, cc_limit);
/* 2. Packet Staging */
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
@ -1166,12 +1167,11 @@ static int txp_determine_geometry(OSSL_QUIC_TX_PACKETISER *txp,
return 1;
}
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp)
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
uint64_t cc_limit)
{
OSSL_ACKM_PROBE_INFO *probe_info
= ossl_ackm_get0_probe_request(txp->args.ackm);
uint64_t cc_limit
= txp->args.cc_method->get_tx_allowance(txp->args.cc_data);
uint32_t pn_space;
/*
@ -2933,3 +2933,35 @@ QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp,
return txp->next_pn[pn_space];
}
OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp)
{
/*
* TXP-specific deadline computations which rely on TXP innards. This is in
* turn relied on by the QUIC_CHANNEL code to determine the channel event
* handling deadline.
*/
OSSL_TIME deadline = ossl_time_infinite();
uint32_t enc_level, pn_space;
/*
* ACK generation is not CC-gated - packets containing only ACKs are allowed
* to bypass CC. We want to generate ACK frames even if we are currently
* restricted by CC so the peer knows we have received data. The generate
* call will take care of selecting the correct packet archetype.
*/
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
enc_level < QUIC_ENC_LEVEL_NUM;
++enc_level)
if (ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) {
pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
deadline = ossl_time_min(deadline,
ossl_ackm_get_ack_deadline(txp->args.ackm, pn_space));
}
/* When will CC let us send more? */
deadline = ossl_time_min(deadline,
txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
return deadline;
}