diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index ff455e52c5..97ef98b971 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -72,9 +72,9 @@ #define QUIC_MAX_STREAMS (256 * 1024) #define QUIC_HANDSHAKE_TIMEOUT (10 * NGTCP2_SECONDS) -/* A stream window is the maximum amount we need to buffer for - * each active transfer. - * Chunk size is large enough to take a full DATA frame */ +/* We announce a small window size in transport param to the server, + * and grow that immediately to max when no rate limit is in place. + * We need to start small as we are not able to decrease it. */ #define H3_STREAM_WINDOW_SIZE_INITIAL (32 * 1024) #define H3_STREAM_WINDOW_SIZE_MAX (10 * 1024 * 1024) #define H3_CONN_WINDOW_SIZE_MAX (100 * H3_STREAM_WINDOW_SIZE_MAX) @@ -90,10 +90,10 @@ * spares. Memory consumption goes down when streams run empty, * have a large upload done, etc. */ #define H3_STREAM_POOL_SPARES 2 -/* Receive and Send max number of chunks just follows from the - * chunk size and window size */ +/* The max amount of un-acked upload data we keep around per stream */ +#define H3_STREAM_SEND_BUFFER_MAX (10 * 1024 * 1024) #define H3_STREAM_SEND_CHUNKS \ - (H3_STREAM_WINDOW_SIZE_MAX / H3_STREAM_CHUNK_SIZE) + (H3_STREAM_SEND_BUFFER_MAX / H3_STREAM_CHUNK_SIZE) /* * Store ngtcp2 version info in this buffer. diff --git a/tests/http/test_07_upload.py b/tests/http/test_07_upload.py index 495ec7a989..daead90930 100644 --- a/tests/http/test_07_upload.py +++ b/tests/http/test_07_upload.py @@ -639,21 +639,18 @@ class TestUpload: ]) r.check_exit_code(0) - # nghttpx is the only server we have that supports TLS early data and - # has a limit of 16k it announces + # nghttpx is the only server we have that supports TLS early data @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx") - @pytest.mark.parametrize("proto,upload_size,exp_early", [ - pytest.param('http/1.1', 100, 203, id='h1-small-body'), - pytest.param('http/1.1', 10*1024, 10345, id='h1-medium-body'), - pytest.param('http/1.1', 32*1024, 16384, id='h1-limited-body'), - pytest.param('h2', 10*1024, 10378, id='h2-medium-body'), - pytest.param('h2', 32*1024, 16384, id='h2-limited-body'), - pytest.param('h3', 1024, 1126, id='h3-small-body'), - pytest.param('h3', 1024 * 1024, 131177, id='h3-limited-body'), - # h3: limited+body (long app data). The 0RTT size is limited by - # our sendbuf size of 128K. + @pytest.mark.parametrize("proto,upload_size", [ + pytest.param('http/1.1', 100, id='h1-small-body'), + pytest.param('http/1.1', 10*1024, id='h1-medium-body'), + pytest.param('http/1.1', 32*1024, id='h1-limited-body'), + pytest.param('h2', 10*1024, id='h2-medium-body'), + pytest.param('h2', 32*1024, id='h2-limited-body'), + pytest.param('h3', 1024, id='h3-small-body'), + pytest.param('h3', 1024 * 1024, id='h3-limited-body'), ]) - def test_07_70_put_earlydata(self, env: Env, httpd, nghttpx, proto, upload_size, exp_early): + def test_07_70_put_earlydata(self, env: Env, httpd, nghttpx, proto, upload_size): if not env.curl_can_early_data(): pytest.skip('TLS earlydata not implemented') if proto == 'h2' and not env.have_h2_curl(): @@ -693,10 +690,12 @@ class TestUpload: m = re.match(r'^\[t-(\d+)] EarlyData: (-?\d+)', line) if m: earlydata[int(m.group(1))] = int(m.group(2)) + # 1st transfer did not use early data assert earlydata[0] == 0, f'{earlydata}\n{r.dump_logs()}' - # depending on cpu load, curl might not upload as much before - # the handshake starts and early data stops. - assert 0 < earlydata[1] <= exp_early, f'{earlydata}\n{r.dump_logs()}' + # depending on cpu load, the amount of early data might differ. + # when the server is slow, we might send more. when curl is slow, + # we might send less before the server handshakes. + assert 0 < earlydata[1] <= (upload_size + 1024), f'{earlydata}\n{r.dump_logs()}' def check_downloads(self, client, r, source: List[str], count: int, complete: bool = True):