mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-14 07:24:32 +00:00
MINOR: quic: Add closing connection state
New received packets after sending CONNECTION_CLOSE frame trigger a new CONNECTION_CLOSE frame to be sent. Each time such a frame is sent we increase the number of packet required to send another CONNECTION_CLOSE frame. Rearm only one time the idle timer when sending a CONNECTION_CLOSE frame.
This commit is contained in:
parent
47756809fb
commit
59bf255806
@ -514,8 +514,10 @@ struct quic_rx_strm_frm {
|
|||||||
#define QUIC_FL_TX_PACKET_PADDING (1UL << 1)
|
#define QUIC_FL_TX_PACKET_PADDING (1UL << 1)
|
||||||
/* Flag a sent packet as being in flight. */
|
/* Flag a sent packet as being in flight. */
|
||||||
#define QUIC_FL_TX_PACKET_IN_FLIGHT (QUIC_FL_TX_PACKET_ACK_ELICITING | QUIC_FL_TX_PACKET_PADDING)
|
#define QUIC_FL_TX_PACKET_IN_FLIGHT (QUIC_FL_TX_PACKET_ACK_ELICITING | QUIC_FL_TX_PACKET_PADDING)
|
||||||
|
/* Flag a sent packet as containg a CONNECTION_CLOSE frame */
|
||||||
|
#define QUIC_FL_TX_PACKET_CC (1UL << 2)
|
||||||
/* Flag a sent packet as containg an ACK frame */
|
/* Flag a sent packet as containg an ACK frame */
|
||||||
#define QUIC_FL_TX_PACKET_ACK (1UL << 2)
|
#define QUIC_FL_TX_PACKET_ACK (1UL << 3)
|
||||||
|
|
||||||
/* Structure to store enough information about TX QUIC packets. */
|
/* Structure to store enough information about TX QUIC packets. */
|
||||||
struct quic_tx_packet {
|
struct quic_tx_packet {
|
||||||
@ -662,6 +664,7 @@ enum qc_mux_state {
|
|||||||
#define QUIC_FL_CONN_LISTENER (1U << 3)
|
#define QUIC_FL_CONN_LISTENER (1U << 3)
|
||||||
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
|
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
|
||||||
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
|
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
|
||||||
|
#define QUIC_FL_CONN_CLOSING (1U << 29)
|
||||||
#define QUIC_FL_CONN_DRAINING (1U << 30)
|
#define QUIC_FL_CONN_DRAINING (1U << 30)
|
||||||
#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31)
|
#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31)
|
||||||
struct quic_conn {
|
struct quic_conn {
|
||||||
@ -754,6 +757,11 @@ struct quic_conn {
|
|||||||
struct task *idle_timer_task;
|
struct task *idle_timer_task;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
/* When in closing state, number of packet before sending CC */
|
||||||
|
unsigned int nb_pkt_for_cc;
|
||||||
|
/* When in closing state, number of packet since receiving CC */
|
||||||
|
unsigned int nb_pkt_since_cc;
|
||||||
|
|
||||||
const struct qcc_app_ops *app_ops;
|
const struct qcc_app_ops *app_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3047,6 +3047,24 @@ int qc_send_ppkts(struct qring *qr, struct ssl_sock_ctx *ctx)
|
|||||||
if (qc->flags & QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ)
|
if (qc->flags & QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ)
|
||||||
qc_idle_timer_rearm(qc, 0);
|
qc_idle_timer_rearm(qc, 0);
|
||||||
}
|
}
|
||||||
|
if (!(qc->flags & QUIC_FL_CONN_CLOSING) &&
|
||||||
|
(pkt->flags & QUIC_FL_TX_PACKET_CC)) {
|
||||||
|
qc->flags |= QUIC_FL_CONN_CLOSING;
|
||||||
|
/* 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...
|
||||||
|
*
|
||||||
|
* Rearm the idle timeout only one time when entering closing
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
qc_idle_timer_do_rearm(qc);
|
||||||
|
if (qc->timer_task) {
|
||||||
|
task_destroy(qc->timer_task);
|
||||||
|
qc->timer_task = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
qc->path->in_flight += pkt->in_flight_len;
|
qc->path->in_flight += pkt->in_flight_len;
|
||||||
pkt->pktns->tx.in_flight += pkt->in_flight_len;
|
pkt->pktns->tx.in_flight += pkt->in_flight_len;
|
||||||
if (pkt->in_flight_len)
|
if (pkt->in_flight_len)
|
||||||
@ -4012,6 +4030,10 @@ static struct quic_conn *qc_new_conn(unsigned int version, int ipv4,
|
|||||||
/* RX part. */
|
/* RX part. */
|
||||||
qc->rx.bytes = 0;
|
qc->rx.bytes = 0;
|
||||||
qc->rx.buf = b_make(buf_area, QUIC_CONN_RX_BUFSZ, 0, 0);
|
qc->rx.buf = b_make(buf_area, QUIC_CONN_RX_BUFSZ, 0, 0);
|
||||||
|
|
||||||
|
qc->nb_pkt_for_cc = 1;
|
||||||
|
qc->nb_pkt_since_cc = 0;
|
||||||
|
|
||||||
LIST_INIT(&qc->rx.pkt_list);
|
LIST_INIT(&qc->rx.pkt_list);
|
||||||
if (!quic_tls_ku_init(qc)) {
|
if (!quic_tls_ku_init(qc)) {
|
||||||
TRACE_PROTO("Key update initialization failed", QUIC_EV_CONN_INIT, qc);
|
TRACE_PROTO("Key update initialization failed", QUIC_EV_CONN_INIT, qc);
|
||||||
@ -4852,6 +4874,17 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
|
|||||||
pkt->qc = qc;
|
pkt->qc = qc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qc->flags & QUIC_FL_CONN_CLOSING) {
|
||||||
|
if (++qc->nb_pkt_since_cc >= qc->nb_pkt_for_cc) {
|
||||||
|
qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
|
||||||
|
qc->nb_pkt_for_cc++;
|
||||||
|
qc->nb_pkt_since_cc = 0;
|
||||||
|
}
|
||||||
|
/* Skip the entire datagram */
|
||||||
|
pkt->len = end - beg;
|
||||||
|
TRACE_PROTO("Closing state connection", QUIC_EV_CONN_LPKT, pkt->qc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* When multiple QUIC packets are coalesced on the same UDP datagram,
|
/* When multiple QUIC packets are coalesced on the same UDP datagram,
|
||||||
* they must have the same DCID.
|
* they must have the same DCID.
|
||||||
@ -5457,8 +5490,12 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build a CONNECTION_CLOSE frame if needed. */
|
/* Build a CONNECTION_CLOSE frame if needed. */
|
||||||
if (cc && !qc_build_frm(&pos, end, &cc_frm, pkt, qc))
|
if (cc) {
|
||||||
goto no_room;
|
if (!qc_build_frm(&pos, end, &cc_frm, pkt, qc))
|
||||||
|
goto no_room;
|
||||||
|
|
||||||
|
pkt->flags |= QUIC_FL_TX_PACKET_CC;
|
||||||
|
}
|
||||||
|
|
||||||
/* Build a PADDING frame if needed. */
|
/* Build a PADDING frame if needed. */
|
||||||
if (padding_len) {
|
if (padding_len) {
|
||||||
|
Loading…
Reference in New Issue
Block a user