comparison src/event/ngx_event_quic.c @ 8476:f9fbeb4ee0de quic

QUIC: added limit of queued data. The ngx_quic_queue_frame() functions puts a frame into send queue and schedules a push timer to actually send data. The patch adds tracking for data amount in the queue and sends data immediately if amount of data exceeds limit.
author Vladimir Homutov <vl@nginx.com>
date Thu, 16 Jul 2020 15:02:38 +0300
parents b276833111cf
children 031918df51c0
comparison
equal deleted inserted replaced
8475:b276833111cf 8476:f9fbeb4ee0de
71 uint64_t largest_ack; /* received from peer */ 71 uint64_t largest_ack; /* received from peer */
72 uint64_t largest_pn; /* received from peer */ 72 uint64_t largest_pn; /* received from peer */
73 73
74 ngx_queue_t frames; 74 ngx_queue_t frames;
75 ngx_queue_t sent; 75 ngx_queue_t sent;
76
77 size_t frames_len;
76 } ngx_quic_send_ctx_t; 78 } ngx_quic_send_ctx_t;
77 79
78 80
79 struct ngx_quic_connection_s { 81 struct ngx_quic_connection_s {
80 ngx_str_t scid; 82 ngx_str_t scid;
3271 3273
3272 ctx = ngx_quic_get_send_ctx(qc, frame->level); 3274 ctx = ngx_quic_get_send_ctx(qc, frame->level);
3273 3275
3274 ngx_queue_insert_tail(&ctx->frames, &frame->queue); 3276 ngx_queue_insert_tail(&ctx->frames, &frame->queue);
3275 3277
3276 /* TODO: check PUSH flag on stream and call output */ 3278 frame->len = ngx_quic_create_frame(NULL, frame);
3277 3279 /* always succeeds */
3278 if (!qc->push.timer_set && !qc->closing) { 3280
3279 ngx_add_timer(&qc->push, qc->tp.max_ack_delay); 3281 ctx->frames_len += frame->len;
3282
3283 if (qc->closing) {
3284 return;
3285 }
3286
3287 /* TODO: TCP_NODELAY analogue ? TCP_CORK and others... */
3288
3289 if (ctx->frames_len < NGX_QUIC_MIN_DATA_NODELAY) {
3290 if (!qc->push.timer_set) {
3291 ngx_add_timer(&qc->push, qc->tp.max_ack_delay);
3292 }
3293
3294 } else {
3295 ngx_post_event(&qc->push, &ngx_posted_events);
3280 } 3296 }
3281 } 3297 }
3282 3298
3283 3299
3284 static ngx_int_t 3300 static ngx_int_t
3307 3323
3308 3324
3309 static ngx_int_t 3325 static ngx_int_t
3310 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) 3326 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3311 { 3327 {
3312 size_t len, hlen, n; 3328 size_t len, hlen;
3313 ngx_uint_t need_ack; 3329 ngx_uint_t need_ack;
3314 ngx_queue_t *q, range; 3330 ngx_queue_t *q, range;
3315 ngx_quic_frame_t *f; 3331 ngx_quic_frame_t *f;
3316 ngx_quic_congestion_t *cg; 3332 ngx_quic_congestion_t *cg;
3317 ngx_quic_connection_t *qc; 3333 ngx_quic_connection_t *qc;
3338 3354
3339 do { 3355 do {
3340 /* process group of frames that fits into packet */ 3356 /* process group of frames that fits into packet */
3341 f = ngx_queue_data(q, ngx_quic_frame_t, queue); 3357 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3342 3358
3343 n = ngx_quic_create_frame(NULL, f); 3359 if (len && hlen + len + f->len > qc->ctp.max_udp_payload_size) {
3344
3345 if (len && hlen + len + n > qc->ctp.max_udp_payload_size) {
3346 break; 3360 break;
3347 } 3361 }
3348 3362
3349 if (f->need_ack) { 3363 if (f->need_ack) {
3350 need_ack = 1; 3364 need_ack = 1;
3351 } 3365 }
3352 3366
3353 if (need_ack && cg->in_flight + len + n > cg->window) { 3367 if (need_ack && cg->in_flight + len + f->len > cg->window) {
3354 break; 3368 break;
3355 } 3369 }
3356 3370
3357 q = ngx_queue_next(q); 3371 q = ngx_queue_next(q);
3358 3372
3359 f->first = ngx_current_msec; 3373 f->first = ngx_current_msec;
3360 3374
3361 ngx_queue_remove(&f->queue); 3375 ngx_queue_remove(&f->queue);
3362 ngx_queue_insert_tail(&range, &f->queue); 3376 ngx_queue_insert_tail(&range, &f->queue);
3363 3377 ctx->frames_len -= f->len;
3364 len += n; 3378
3379 len += f->len;
3365 3380
3366 } while (q != ngx_queue_sentinel(&ctx->frames)); 3381 } while (q != ngx_queue_sentinel(&ctx->frames));
3367 3382
3368 if (ngx_queue_empty(&range)) { 3383 if (ngx_queue_empty(&range)) {
3369 break; 3384 break;
4269 4284
4270 4285
4271 static void 4286 static void
4272 ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) 4287 ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
4273 { 4288 {
4274 ssize_t n;
4275 ngx_msec_t timer; 4289 ngx_msec_t timer;
4276 ngx_quic_congestion_t *cg; 4290 ngx_quic_congestion_t *cg;
4277 ngx_quic_connection_t *qc; 4291 ngx_quic_connection_t *qc;
4278 4292
4279 qc = c->quic; 4293 qc = c->quic;
4280 cg = &qc->congestion; 4294 cg = &qc->congestion;
4281 4295
4282 n = ngx_quic_create_frame(NULL, f); 4296 cg->in_flight -= f->len;
4283
4284 cg->in_flight -= n;
4285 4297
4286 timer = f->last - cg->recovery_start; 4298 timer = f->last - cg->recovery_start;
4287 4299
4288 if ((ngx_msec_int_t) timer <= 0) { 4300 if ((ngx_msec_int_t) timer <= 0) {
4289 return; 4301 return;
4290 } 4302 }
4291 4303
4292 if (cg->window < cg->ssthresh) { 4304 if (cg->window < cg->ssthresh) {
4293 cg->window += n; 4305 cg->window += f->len;
4294 4306
4295 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 4307 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4296 "quic congestion slow start win:%uz, ss:%uz, if:%uz", 4308 "quic congestion slow start win:%uz, ss:%uz, if:%uz",
4297 cg->window, cg->ssthresh, cg->in_flight); 4309 cg->window, cg->ssthresh, cg->in_flight);
4298 4310
4299 } else { 4311 } else {
4300 cg->window += qc->tp.max_udp_payload_size * n / cg->window; 4312 cg->window += qc->tp.max_udp_payload_size * f->len / cg->window;
4301 4313
4302 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 4314 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4303 "quic congestion avoidance win:%uz, ss:%uz, if:%uz", 4315 "quic congestion avoidance win:%uz, ss:%uz, if:%uz",
4304 cg->window, cg->ssthresh, cg->in_flight); 4316 cg->window, cg->ssthresh, cg->in_flight);
4305 } 4317 }