summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorVladimir Homutov <vl@nginx.com>2020-10-20 18:53:25 +0300
committerVladimir Homutov <vl@nginx.com>2020-10-20 18:53:25 +0300
commitcb3a1d7f490b73546055034a01dcb305e7a09b9f (patch)
tree1a6c550885457932c49f30a52110ee4b5fe215a5 /src
parent6e412bf182bf47a9c8053d859ada515552c3aba1 (diff)
downloadnginx-cb3a1d7f490b73546055034a01dcb305e7a09b9f.tar.gz
nginx-cb3a1d7f490b73546055034a01dcb305e7a09b9f.tar.bz2
QUIC: drop acknowledged ranges.
13.2.4. Limiting Ranges by Tracking ACK Frames When a packet containing an ACK frame is sent, the largest acknowledged in that frame may be saved. When a packet containing an ACK frame is acknowledged, the receiver can stop acknowledging packets less than or equal to the largest acknowledged in the sent ACK frame.
Diffstat (limited to 'src')
-rw-r--r--src/event/ngx_event_quic.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c
index e30d5f64f..c941d21eb 100644
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -244,6 +244,8 @@ static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c,
ngx_quic_header_t *pkt);
static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest);
+static void ngx_quic_drop_ack_ranges(ngx_connection_t *c,
+ ngx_quic_send_ctx_t *ctx, uint64_t pn);
static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx);
static ngx_int_t ngx_quic_ack_delay(ngx_connection_t *c,
@@ -2537,6 +2539,59 @@ ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
}
+static void
+ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
+ uint64_t pn)
+{
+ uint64_t base;
+ ngx_uint_t i, smallest, largest;
+ ngx_quic_ack_range_t *r;
+
+ base = ctx->largest_range;
+
+ if (base == (uint64_t) -1) {
+ return;
+ }
+
+ if (ctx->pending_ack != (uint64_t) -1 && pn >= ctx->pending_ack) {
+ ctx->pending_ack = (uint64_t) -1;
+ }
+
+ largest = base;
+ smallest = largest - ctx->first_range;
+
+ if (pn >= largest) {
+ ctx->largest_range = (uint64_t) - 1;
+ ctx->first_range = 0;
+ ctx->nranges = 0;
+ return;
+ }
+
+ if (pn >= smallest) {
+ ctx->first_range = largest - pn - 1;
+ ctx->nranges = 0;
+ return;
+ }
+
+ for (i = 0; i < ctx->nranges; i++) {
+ r = &ctx->ranges[i];
+
+ largest = smallest - r->gap - 2;
+ smallest = largest - r->range;
+
+ if (pn >= largest) {
+ ctx->nranges = i;
+ return;
+ }
+ if (pn >= smallest) {
+ r->range = largest - pn - 1;
+ ctx->nranges = i + 1;
+ return;
+ }
+ }
+}
+
+
static ngx_int_t
ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
{
@@ -2805,7 +2860,22 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
if (f->pnum >= min && f->pnum <= max) {
ngx_quic_congestion_ack(c, f);
- ngx_quic_handle_stream_ack(c, f);
+ switch (f->type) {
+ case NGX_QUIC_FT_ACK:
+ ngx_quic_drop_ack_ranges(c, ctx, f->u.ack.largest);
+ break;
+
+ case NGX_QUIC_FT_STREAM0:
+ case NGX_QUIC_FT_STREAM1:
+ case NGX_QUIC_FT_STREAM2:
+ case NGX_QUIC_FT_STREAM3:
+ case NGX_QUIC_FT_STREAM4:
+ case NGX_QUIC_FT_STREAM5:
+ case NGX_QUIC_FT_STREAM6:
+ case NGX_QUIC_FT_STREAM7:
+ ngx_quic_handle_stream_ack(c, f);
+ break;
+ }
if (f->pnum > found_num || !found) {
*send_time = f->last;
@@ -2927,10 +2997,6 @@ ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
ngx_quic_stream_t *sn;
ngx_quic_connection_t *qc;
- if (f->type < NGX_QUIC_FT_STREAM0 || f->type > NGX_QUIC_FT_STREAM7) {
- return;
- }
-
qc = c->quic;
sn = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);