BUG/MINOR: quic: do not consider idle timeout on CLOSING state

When entering closing state, a QUIC connection is maintained during a
certain delay. The principle is to ensure the other peer has received
the CONNECTION_CLOSE frame. In case of packet duplication/reordering,
CONNECTION_CLOSE is reemitted.

QUIC RFC recommends to use at least 3 times the PTO value. However,
prior to this patch, haproxy used instead the max value between 3 times
the PTO and the connection idle timeout. In the default case, idle
timeout is set to 30s which is in most of the times largely superior to
the PTO. This has the downside of keeping the connection in memory for
too long whereas all resources could be released much earlier.

Fix this behavior by using 3 times the PTO on closing or draining state.
This value is limited up to 1s. This ensures that most of connections
are covered by this. If a connection runs with a very high RTT, it must
not impact the whole process and should be released in a reasonable
delay.

This should be backported up to 2.6.
This commit is contained in:
Amaury Denoyelle 2023-10-25 14:45:53 +02:00
parent 96bb99a87d
commit fe29dba872

View File

@ -1534,7 +1534,33 @@ void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack)
task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG); task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
} }
else { else {
expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout); if (qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
/* RFC 9000 10.2. Immediate Close
*
* The closing and draining connection states exist to ensure that
* connections close cleanly and that delayed or reordered packets are
* properly discarded. These states SHOULD persist for at least three
* times the current PTO interval as defined in [QUIC-RECOVERY].
*/
/* Delay is limited to 1s which should cover most of
* network conditions. The process should not be
* impacted by a connection with a high RTT.
*/
expire = MIN(3 * quic_pto(qc), 1000);
}
else {
/* RFC 9000 10.1. Idle Timeout
*
* To avoid excessively small idle timeout periods, endpoints MUST
* increase the idle timeout period to be at least three times the
* current Probe Timeout (PTO). This allows for multiple PTOs to expire,
* and therefore multiple probes to be sent and lost, prior to idle
* timeout.
*/
expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
}
qc->idle_expire = tick_add(now_ms, MS_TO_TICKS(expire)); qc->idle_expire = tick_add(now_ms, MS_TO_TICKS(expire));
if (arm_ack) { if (arm_ack) {
/* Arm the ack timer only if not already armed. */ /* Arm the ack timer only if not already armed. */