Skip to content

Commit

Permalink
QUIC APL: Optimise write buffer sizes automatically
Browse files Browse the repository at this point in the history
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #22569)

(cherry picked from commit b119f8b)
  • Loading branch information
hlandau committed Nov 1, 2023
1 parent 18a431b commit 96040e5
Showing 1 changed file with 56 additions and 7 deletions.
63 changes: 56 additions & 7 deletions ssl/quic/quic_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,58 @@ struct quic_write_again_args {
int err;
};

/*
* Absolute maximum write buffer size, enforced to prevent a rogue peer from
* deliberately inducing DoS. This has been chosen based on the optimal buffer
* size for an RTT of 500ms and a bandwidth of 100 Mb/s.
*/
#define MAX_WRITE_BUF_SIZE (6 * 1024 * 1024)

/*
* Ensure spare buffer space available (up until a limit, at least).
*/
QUIC_NEEDS_LOCK
static int sstream_ensure_spare(QUIC_SSTREAM *sstream, uint64_t spare)
{
size_t cur_sz = ossl_quic_sstream_get_buffer_size(sstream);
size_t avail = ossl_quic_sstream_get_buffer_avail(sstream);
size_t spare_ = (spare > SIZE_MAX) ? SIZE_MAX : (size_t)spare;
size_t new_sz, growth;

if (spare_ <= avail || cur_sz == MAX_WRITE_BUF_SIZE)
return 1;

growth = spare_ - avail;
if (cur_sz + growth > MAX_WRITE_BUF_SIZE)
new_sz = MAX_WRITE_BUF_SIZE;
else
new_sz = cur_sz + growth;

return ossl_quic_sstream_set_buffer_size(sstream, new_sz);
}

/*
* Append to a QUIC_STREAM's QUIC_SSTREAM, ensuring buffer space is expanded
* as needed according to flow control.
*/
QUIC_NEEDS_LOCK
static int xso_sstream_append(QUIC_XSO *xso, const unsigned char *buf,
size_t len, size_t *actual_written)
{
QUIC_SSTREAM *sstream = xso->stream->sstream;
uint64_t cur = ossl_quic_sstream_get_cur_size(sstream);
uint64_t cwm = ossl_quic_txfc_get_cwm(&xso->stream->txfc);
uint64_t permitted = (cwm >= cur ? cwm - cur : 0);

if (len > permitted)
len = (size_t)permitted;

if (!sstream_ensure_spare(sstream, len))
return 0;

return ossl_quic_sstream_append(sstream, buf, len, actual_written);
}

QUIC_NEEDS_LOCK
static int quic_write_again(void *arg)
{
Expand All @@ -2195,8 +2247,7 @@ static int quic_write_again(void *arg)
return -2;

args->err = ERR_R_INTERNAL_ERROR;
if (!ossl_quic_sstream_append(args->xso->stream->sstream,
args->buf, args->len, &actual_written))
if (!xso_sstream_append(args->xso, args->buf, args->len, &actual_written))
return -2;

quic_post_write(args->xso, actual_written > 0, 0);
Expand All @@ -2223,8 +2274,7 @@ static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len,
size_t actual_written = 0;

/* First make a best effort to append as much of the data as possible. */
if (!ossl_quic_sstream_append(xso->stream->sstream, buf, len,
&actual_written)) {
if (!xso_sstream_append(xso, buf, len, &actual_written)) {
/* Stream already finished or allocation error. */
*written = 0;
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
Expand Down Expand Up @@ -2317,8 +2367,7 @@ static int quic_write_nonblocking_aon(QCTX *ctx, const void *buf,
}

/* First make a best effort to append as much of the data as possible. */
if (!ossl_quic_sstream_append(xso->stream->sstream, actual_buf, actual_len,
&actual_written)) {
if (!xso_sstream_append(xso, actual_buf, actual_len, &actual_written)) {
/* Stream already finished or allocation error. */
*written = 0;
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
Expand Down Expand Up @@ -2379,7 +2428,7 @@ static int quic_write_nonblocking_epw(QCTX *ctx, const void *buf, size_t len,
QUIC_XSO *xso = ctx->xso;

/* Simple best effort operation. */
if (!ossl_quic_sstream_append(xso->stream->sstream, buf, len, written)) {
if (!xso_sstream_append(xso, buf, len, written)) {
/* Stream already finished or allocation error. */
*written = 0;
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
Expand Down

0 comments on commit 96040e5

Please sign in to comment.