Skip to content

Commit

Permalink
Merge pull request h2o#464 from h2o/kazuho/state-exhaustion
Browse files Browse the repository at this point in the history
relax stream state limits
  • Loading branch information
kazuho authored Jun 15, 2021
2 parents 4c460f4 + 068a21a commit e479d17
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 7 deletions.
11 changes: 8 additions & 3 deletions lib/quicly.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,11 +1020,16 @@ static void init_stream_properties(quicly_stream_t *stream, uint32_t initial_max

/* Set the number of max ranges to be capable of handling following case:
* * every one of the two packets being sent are lost
* * average size of a STREAM frame found in a packet is >= ~512 bytes
* * average size of a STREAM frame found in a packet is >= ~512 bytes, or small STREAM frame is sent for every other stream
* being opened (e.g., sending QPACK encoder/decoder stream frame for each HTTP/3 request)
* See also: the doc-comment on `_recv_aux.max_ranges`.
*/
if ((stream->_recv_aux.max_ranges = initial_max_stream_data_local / 1024) < 63)
stream->_recv_aux.max_ranges = 63;
uint32_t fragments_minmax = (uint32_t)(stream->conn->super.ctx->transport_params.max_streams_uni +
stream->conn->super.ctx->transport_params.max_streams_bidi);
if (fragments_minmax < 63)
fragments_minmax = 63;
if ((stream->_recv_aux.max_ranges = initial_max_stream_data_local / 1024) < fragments_minmax)
stream->_recv_aux.max_ranges = fragments_minmax;
}

static void dispose_stream_properties(quicly_stream_t *stream)
Expand Down
12 changes: 8 additions & 4 deletions lib/sendstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,21 @@ static int check_amount_of_state(quicly_sendstate_t *state)
{
size_t num_ranges = state->acked.num_ranges + state->pending.num_ranges;

/* bail out if number of gaps are small */
if (PTLS_LIKELY(num_ranges < 32))
/* Bail out if number of gaps are small.
* In case of HTTP/3, the worst case is when each HTTP request is received as a separate QUIC packet, and sending a small STREAM
* frame carrying a HPACK encoder / decoder in response. If half of those STREAM frames are lost (note: loss of every other
* packet can happen during slow start), `num_ranges` can become as large as `request_concurrency * 2`, as each gaps will be
* recognized in `acked.num_ranges` and `pending.num_ranges`. */
if (PTLS_LIKELY(num_ranges < 256))
return 0;

/* When there are large number of gaps, make sure that the amount of state retained in quicly is relatively smaller than the
* amount of state retained by application (in form of the stream-level send buffer). 512 is used as the threshold, based on the
* assumption that the STREAM frames that have been sent are on average at least 512 bytes long, when seeing excess number of
* gaps. */
int64_t bytes_buffered = (int64_t)state->size_inflight - (int64_t)state->acked.ranges[0].end;
if ((int64_t)num_ranges * 512 > bytes_buffered)
return QUICLY_TRANSPORT_ERROR_PROTOCOL_VIOLATION;
if ((int64_t)num_ranges * 128 > bytes_buffered)
return QUICLY_ERROR_STATE_EXHAUSTION;

return 0;
}
Expand Down

0 comments on commit e479d17

Please sign in to comment.