MEDIUM: quic: trigger fast connection closing on process stopping

With previous commit, quic-conn are now handled as jobs to prevent the
termination of haproxy process. This ensures that QUIC connections are
closed when all data are acknowledged by the client and there is no more
active streams.

The quic-conn layer emits a CONNECTION_CLOSE once the MUX has been
released and all streams are acknowledged. Then, the timer is scheduled
to definitely free the connection after the idle timeout period. This
allows to treat late-arriving packets.

Adjust this procedure to deactivate this timer when process stopping is
in progress. In this case, quic-conn timer is set to expire immediately
to free the quic-conn instance as soon as possible. This allows to
quickly close haproxy process.

This should be backported up to 2.7.
This commit is contained in:
Amaury Denoyelle 2023-02-01 09:28:55 +01:00
parent fb375574f9
commit 77ed63106d
3 changed files with 17 additions and 7 deletions

View File

@ -623,9 +623,9 @@ enum qc_mux_state {
#define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */ #define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */
#define QUIC_FL_CONN_NOTIFY_CLOSE (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */ #define QUIC_FL_CONN_NOTIFY_CLOSE (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */
#define QUIC_FL_CONN_EXP_TIMER (1U << 28) /* timer has expired, quic-conn can be freed */ #define QUIC_FL_CONN_EXP_TIMER (1U << 28) /* timer has expired, quic-conn can be freed */
#define QUIC_FL_CONN_CLOSING (1U << 29) #define QUIC_FL_CONN_CLOSING (1U << 29) /* closing state, entered on CONNECTION_CLOSE emission */
#define QUIC_FL_CONN_DRAINING (1U << 30) #define QUIC_FL_CONN_DRAINING (1U << 30) /* draining state, entered on CONNECTION_CLOSE reception */
#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31) #define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31) /* A CONNECTION_CLOSE must be sent */
struct quic_conn { struct quic_conn {
const struct quic_version *original_version; const struct quic_version *original_version;

View File

@ -3032,8 +3032,8 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
* Rearm the idle timeout only one time when entering draining * Rearm the idle timeout only one time when entering draining
* state. * state.
*/ */
qc_idle_timer_do_rearm(qc);
qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE; qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE;
qc_idle_timer_do_rearm(qc);
qc_notify_close(qc); qc_notify_close(qc);
} }
break; break;
@ -5280,9 +5280,15 @@ static void qc_idle_timer_do_rearm(struct quic_conn *qc)
{ {
unsigned int expire; unsigned int expire;
expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout); if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire)); TRACE_STATE("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc);
task_queue(qc->idle_timer_task); task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
}
else {
expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire));
task_queue(qc->idle_timer_task);
}
} }
/* Rearm the idle timer for <qc> QUIC connection depending on <read> boolean /* Rearm the idle timer for <qc> QUIC connection depending on <read> boolean

View File

@ -34,6 +34,10 @@ static void quic_close(struct connection *conn, void *xprt_ctx)
goto leave; goto leave;
} }
/* Schedule a CONNECTION_CLOSE emission. If process stopping is in
* progress, quic-conn idle-timer will be scheduled immediately after
* its emission to ensure an immediate connection closing.
*/
qc_check_close_on_released_mux(qc); qc_check_close_on_released_mux(qc);
leave: leave:
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc); TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);