comparison src/event/ngx_event_quic.c @ 7815:0f9e9786b90d quic

Added primitive flow control mechanisms. + MAX_STREAM_DATA frame is sent when recv() is performed on stream The new value is a sum of total bytes received by stream + free space in a buffer; The sending of MAX_STREM_DATA frame in response to STREAM_DATA_BLOCKED frame is adjusted to follow the same logic as above. + MAX_DATA frame is sent when total amount of received data is 2x of current limit. The limit is doubled. + Default values of transport parameters are adjusted to more meaningful values: initial stream limits are set to quic buffer size instead of unrealistically small 255. initial max data is decreased to 16 buffer sizes, in an assumption that this is enough for a relatively short connection, instead of randomly chosen big number. All this allows to initiate a stable flow of streams that does not block on stream/connection limits (tested with FF 77.0a1 and 100K requests)
author Vladimir Homutov <vl@nginx.com>
date Wed, 15 Apr 2020 18:54:03 +0300
parents ab443e80d9e4
children aba84d9ab256
comparison
equal deleted inserted replaced
7814:ab443e80d9e4 7815:0f9e9786b90d
45 ngx_rbtree_t tree; 45 ngx_rbtree_t tree;
46 ngx_rbtree_node_t sentinel; 46 ngx_rbtree_node_t sentinel;
47 ngx_connection_handler_pt handler; 47 ngx_connection_handler_pt handler;
48 48
49 ngx_uint_t id_counter; 49 ngx_uint_t id_counter;
50
51 uint64_t total_received;
52 uint64_t max_data;
50 } ngx_quic_streams_t; 53 } ngx_quic_streams_t;
51 54
52 55
53 /* 56 /*
54 * 12.3. Packet Numbers 57 * 12.3. Packet Numbers
533 ctp = &qc->ctp; 536 ctp = &qc->ctp;
534 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE; 537 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE;
535 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; 538 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
536 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; 539 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
537 540
541 qc->streams.max_data = qc->tp.initial_max_data;
542
538 qc->dcid.len = pkt->dcid.len; 543 qc->dcid.len = pkt->dcid.len;
539 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len); 544 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len);
540 if (qc->dcid.data == NULL) { 545 if (qc->dcid.data == NULL) {
541 return NGX_ERROR; 546 return NGX_ERROR;
542 } 547 }
1961 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unknown stream id:%uL", f->id); 1966 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unknown stream id:%uL", f->id);
1962 return NGX_ERROR; 1967 return NGX_ERROR;
1963 } 1968 }
1964 1969
1965 b = sn->b; 1970 b = sn->b;
1966 n = (b->pos - b->start) + (b->end - b->last); 1971 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last);
1967 1972
1968 frame = ngx_quic_alloc_frame(c, 0); 1973 frame = ngx_quic_alloc_frame(c, 0);
1969 if (frame == NULL) { 1974 if (frame == NULL) {
1970 return NGX_ERROR; 1975 return NGX_ERROR;
1971 } 1976 }
2557 2562
2558 2563
2559 static ssize_t 2564 static ssize_t
2560 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size) 2565 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
2561 { 2566 {
2562 ssize_t len; 2567 ssize_t len;
2563 ngx_buf_t *b; 2568 ngx_buf_t *b;
2564 ngx_event_t *rev; 2569 ngx_event_t *rev;
2565 ngx_quic_stream_t *qs; 2570 ngx_connection_t *pc;
2571 ngx_quic_frame_t *frame;
2572 ngx_quic_stream_t *qs;
2573 ngx_quic_connection_t *qc;
2566 2574
2567 qs = c->qs; 2575 qs = c->qs;
2568 b = qs->b; 2576 b = qs->b;
2577 pc = qs->parent;
2578 qc = pc->quic;
2569 rev = c->read; 2579 rev = c->read;
2570 2580
2571 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 2581 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2572 "quic recv: eof:%d, avail:%z", 2582 "quic recv: eof:%d, avail:%z",
2573 rev->pending_eof, b->last - b->pos); 2583 rev->pending_eof, b->last - b->pos);
2587 len = ngx_min(b->last - b->pos, (ssize_t) size); 2597 len = ngx_min(b->last - b->pos, (ssize_t) size);
2588 2598
2589 ngx_memcpy(buf, b->pos, len); 2599 ngx_memcpy(buf, b->pos, len);
2590 2600
2591 b->pos += len; 2601 b->pos += len;
2602 qc->streams.total_received += len;
2592 2603
2593 if (b->pos == b->last) { 2604 if (b->pos == b->last) {
2594 b->pos = b->start; 2605 b->pos = b->start;
2595 b->last = b->start; 2606 b->last = b->start;
2596 rev->ready = rev->pending_eof; 2607 rev->ready = rev->pending_eof;
2597 } 2608 }
2598 2609
2599 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 2610 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2600 "quic recv: %z of %uz", len, size); 2611 "quic recv: %z of %uz", len, size);
2612
2613 if (!rev->pending_eof) {
2614 frame = ngx_quic_alloc_frame(pc, 0);
2615 if (frame == NULL) {
2616 return NGX_ERROR;
2617 }
2618
2619 frame->level = ssl_encryption_application;
2620 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
2621 frame->u.max_stream_data.id = qs->id;
2622 frame->u.max_stream_data.limit = qs->fs.received + (b->pos - b->start)
2623 + (b->end - b->last);
2624
2625 ngx_sprintf(frame->info, "MAX_STREAM_DATA id:%d limit:%d l=%d on recv",
2626 (int) frame->u.max_stream_data.id,
2627 (int) frame->u.max_stream_data.limit,
2628 frame->level);
2629
2630 ngx_quic_queue_frame(pc->quic, frame);
2631 }
2632
2633 if ((qc->streams.max_data / 2) < qc->streams.total_received) {
2634
2635 frame = ngx_quic_alloc_frame(pc, 0);
2636
2637 if (frame == NULL) {
2638 return NGX_ERROR;
2639 }
2640
2641 qc->streams.max_data *= 2;
2642
2643 frame->level = ssl_encryption_application;
2644 frame->type = NGX_QUIC_FT_MAX_DATA;
2645 frame->u.max_data.max_data = qc->streams.max_data;
2646
2647 ngx_sprintf(frame->info, "MAX_DATA max_data:%d level=%d on recv",
2648 (int) frame->u.max_data.max_data, frame->level);
2649
2650 ngx_quic_queue_frame(pc->quic, frame);
2651
2652 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2653 "quic recv: increased max data: %ui",
2654 qc->streams.max_data);
2655 }
2601 2656
2602 return len; 2657 return len;
2603 } 2658 }
2604 2659
2605 2660