diff --git a/include/internal/quic_txp.h b/include/internal/quic_txp.h index 7238fae1aa0c8..2a503770bc864 100644 --- a/include/internal/quic_txp.h +++ b/include/internal/quic_txp.h @@ -162,6 +162,13 @@ void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *tx void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp, uint32_t pn_space); +/* + * Asks the TXP to ensure an ACK is put in the next packet in the given PN + * space. + */ +void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp, + uint32_t pn_space); + /* * Schedules a connection close. *f and f->reason are copied. This operation is * irreversible and causes all further packets generated by the TXP to contain a diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index c4dfa58bc14be..efc9fd7f4a0b7 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -701,6 +701,23 @@ static void rxku_detected(QUIC_PN pn, void *arg) if (decision == DECISION_SOLICITED_TXKU) /* NOT gated by usual txku_allowed() */ ch_trigger_txku(ch); + + /* + * Ordinarily, we only generate ACK when some ACK-eliciting frame has been + * received. In some cases, this may not occur for a long time, for example + * if transmission of application data is going in only one direction and + * nothing else is happening with the connection. However, since the peer + * cannot initiate a subsequent (spontaneous) TXKU until its prior + * (spontaneous or solicited) TXKU has completed - meaning that that prior + * TXKU's trigger packet (or subsequent packet) has been acknowledged, this + * can lead to very long times before a TXKU is considered 'completed'. + * Optimise this by forcing ACK generation after triggering TXKU. + * (Basically, we consider a RXKU event something that is 'ACK-eliciting', + * which it more or less should be; it is necessarily separate from ordinary + * processing of ACK-eliciting frames as key update is not indicated via a + * frame.) + */ + ossl_quic_tx_packetiser_schedule_ack(ch->txp, QUIC_PN_SPACE_APP); } /* Called per tick to handle RXKU timer events. */ diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c index 1acf42104acf5..f471237e2a4a3 100644 --- a/ssl/quic/quic_txp.c +++ b/ssl/quic/quic_txp.c @@ -519,6 +519,12 @@ void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp txp->force_ack_eliciting |= (1UL << pn_space); } +void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp, + uint32_t pn_space) +{ + txp->want_ack |= (1UL << pn_space); +} + #define TXP_ERR_INTERNAL 0 /* Internal (e.g. alloc) error */ #define TXP_ERR_SUCCESS 1 /* Success */ #define TXP_ERR_SPACE 2 /* Not enough room for another packet */