mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MINOR: quic: refactor handling of streams after MUX release
quic-conn layer has to handle itself STREAM frames after MUX release. If the stream was already seen, it is probably only a retransmitted frame which can be safely ignored. For other streams, an active closure may be needed. Thus it's necessary that quic-conn layer knows the highest stream ID already handled by the MUX after its release. Previously, this was done via <nb_streams> member array in quic-conn structure. Refactor this by replacing <nb_streams> by two members called <stream_max_uni>/<stream_max_bidi>. Indeed, it is unnecessary for quic-conn layer to monitor locally opened uni streams, as the peer cannot by definition emit a STREAM frame on it. Also, bidirectional streams are always opened by the remote side. Previously, <nb_streams> were set by quic-stream layer. Now, <stream_max_uni>/<stream_max_bidi> members are only set one time, just prior to QUIC MUX release. This is sufficient as quic-conn do not use them if the MUX is available. Note that previously, IDs were used relatively to their type, thus incremented by 1, after shifting the original value. For simplification, use the plain stream ID, which is incremented by 4.
This commit is contained in:
parent
07d41a043c
commit
f286288471
@ -28,9 +28,6 @@ enum qcs_type {
|
|||||||
QCS_SRV_BIDI,
|
QCS_SRV_BIDI,
|
||||||
QCS_CLT_UNI,
|
QCS_CLT_UNI,
|
||||||
QCS_SRV_UNI,
|
QCS_SRV_UNI,
|
||||||
|
|
||||||
/* Must be the last one */
|
|
||||||
QCS_MAX_TYPES
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qcc_app_st {
|
enum qcc_app_st {
|
||||||
|
@ -51,15 +51,7 @@ static inline int qmux_stream_rx_bufsz(void)
|
|||||||
return global.tune.bufsize - NCB_RESERVED_SZ;
|
return global.tune.bufsize - NCB_RESERVED_SZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bit shift to get the stream sub ID for internal use which is obtained
|
|
||||||
* shifting the stream IDs by this value, knowing that the
|
|
||||||
* QCS_ID_TYPE_SHIFT less significant bits identify the stream ID
|
|
||||||
* types (client initiated bidirectional, server initiated bidirectional,
|
|
||||||
* client initiated unidirectional, server initiated bidirectional).
|
|
||||||
* Note that there is no reference to such stream sub IDs in the RFC.
|
|
||||||
*/
|
|
||||||
#define QCS_ID_TYPE_MASK 0x3
|
#define QCS_ID_TYPE_MASK 0x3
|
||||||
#define QCS_ID_TYPE_SHIFT 2
|
|
||||||
/* The less significant bit of a stream ID is set for a server initiated stream */
|
/* The less significant bit of a stream ID is set for a server initiated stream */
|
||||||
#define QCS_ID_SRV_INTIATOR_BIT 0x1
|
#define QCS_ID_SRV_INTIATOR_BIT 0x1
|
||||||
/* This bit is set for unidirectional streams */
|
/* This bit is set for unidirectional streams */
|
||||||
|
@ -385,10 +385,10 @@ struct quic_conn {
|
|||||||
/* RX buffer */
|
/* RX buffer */
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct list pkt_list;
|
struct list pkt_list;
|
||||||
struct {
|
|
||||||
/* Number of open or closed streams */
|
/* first unhandled streams ID, set by MUX after release */
|
||||||
uint64_t nb_streams;
|
uint64_t stream_max_uni;
|
||||||
} strms[QCS_MAX_TYPES];
|
uint64_t stream_max_bidi;
|
||||||
} rx;
|
} rx;
|
||||||
struct {
|
struct {
|
||||||
struct quic_tls_kp prv_rx;
|
struct quic_tls_kp prv_rx;
|
||||||
|
@ -3225,15 +3225,20 @@ static void qcc_release(struct qcc *qcc)
|
|||||||
qcs_free(qcs);
|
qcs_free(qcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unsubscribe from all remaining qc_stream_desc */
|
|
||||||
if (conn) {
|
if (conn) {
|
||||||
qc = conn->handle.qc;
|
qc = conn->handle.qc;
|
||||||
|
|
||||||
|
/* unsubscribe from all remaining qc_stream_desc */
|
||||||
node = eb64_first(&qc->streams_by_id);
|
node = eb64_first(&qc->streams_by_id);
|
||||||
while (node) {
|
while (node) {
|
||||||
struct qc_stream_desc *stream = eb64_entry(node, struct qc_stream_desc, by_id);
|
struct qc_stream_desc *stream = eb64_entry(node, struct qc_stream_desc, by_id);
|
||||||
qc_stream_desc_sub_room(stream, NULL);
|
qc_stream_desc_sub_room(stream, NULL);
|
||||||
node = eb64_next(node);
|
node = eb64_next(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* register streams IDs so that quic-conn layer can ignore already closed streams. */
|
||||||
|
qc->rx.stream_max_uni = qcc->largest_uni_r;
|
||||||
|
qc->rx.stream_max_bidi = qcc->largest_bidi_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
tasklet_free(qcc->wait_event.tasklet);
|
tasklet_free(qcc->wait_event.tasklet);
|
||||||
|
@ -1030,7 +1030,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
struct sockaddr_storage *peer_addr,
|
struct sockaddr_storage *peer_addr,
|
||||||
int server, int token, void *owner)
|
int server, int token, void *owner)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct quic_conn *qc = NULL;
|
struct quic_conn *qc = NULL;
|
||||||
struct listener *l = server ? owner : NULL;
|
struct listener *l = server ? owner : NULL;
|
||||||
struct proxy *prx = l ? l->bind_conf->frontend : NULL;
|
struct proxy *prx = l ? l->bind_conf->frontend : NULL;
|
||||||
@ -1216,8 +1215,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
|||||||
qc->bytes.rx = 0;
|
qc->bytes.rx = 0;
|
||||||
memset(&qc->rx.params, 0, sizeof(qc->rx.params));
|
memset(&qc->rx.params, 0, sizeof(qc->rx.params));
|
||||||
qc->rx.buf = b_make(qc->rx.buf.area, QUIC_CONN_RX_BUFSZ, 0, 0);
|
qc->rx.buf = b_make(qc->rx.buf.area, QUIC_CONN_RX_BUFSZ, 0, 0);
|
||||||
for (i = 0; i < QCS_MAX_TYPES; i++)
|
qc->rx.stream_max_uni = qc->rx.stream_max_bidi = 0;
|
||||||
qc->rx.strms[i].nb_streams = 0;
|
|
||||||
|
|
||||||
qc->nb_pkt_for_cc = 1;
|
qc->nb_pkt_for_cc = 1;
|
||||||
qc->nb_pkt_since_cc = 0;
|
qc->nb_pkt_since_cc = 0;
|
||||||
|
@ -955,12 +955,13 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
|||||||
case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
|
case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
|
||||||
{
|
{
|
||||||
struct qf_stream *strm_frm = &frm->stream;
|
struct qf_stream *strm_frm = &frm->stream;
|
||||||
unsigned nb_streams = qc->rx.strms[qcs_id_type(strm_frm->id)].nb_streams;
|
|
||||||
const char fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
|
const char fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
|
||||||
|
const uint64_t max = quic_stream_is_uni(strm_frm->id) ?
|
||||||
|
qc->rx.stream_max_uni : qc->rx.stream_max_bidi;
|
||||||
|
|
||||||
/* The upper layer may not be allocated. */
|
/* The upper layer may not be allocated. */
|
||||||
if (qc->mux_state != QC_MUX_READY) {
|
if (qc->mux_state != QC_MUX_READY) {
|
||||||
if ((strm_frm->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
|
if (strm_frm->id < max) {
|
||||||
TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
|
TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -80,7 +80,6 @@ struct qc_stream_desc *qc_stream_desc_new(uint64_t id, enum qcs_type type, void
|
|||||||
else {
|
else {
|
||||||
stream->by_id.key = id;
|
stream->by_id.key = id;
|
||||||
eb64_insert(&qc->streams_by_id, &stream->by_id);
|
eb64_insert(&qc->streams_by_id, &stream->by_id);
|
||||||
qc->rx.strms[type].nb_streams++;
|
|
||||||
}
|
}
|
||||||
stream->qc = qc;
|
stream->qc = qc;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user