comparison src/event/ngx_event_quic.c @ 7991:1b9db5c8c29b quic

QUIC: reworked ngx_quic_send_frames() function. Instead of returning NGX_DONE/NGX_OK, the function now itself moves passed frames range into sent queue and sets PTO timer if required.
author Vladimir Homutov <vl@nginx.com>
date Wed, 15 Jul 2020 15:10:17 +0300
parents 3b15732ac03f
children 909b989ec088
comparison
equal deleted inserted replaced
7990:3b15732ac03f 7991:1b9db5c8c29b
239 239
240 static ngx_int_t ngx_quic_output(ngx_connection_t *c); 240 static ngx_int_t ngx_quic_output(ngx_connection_t *c);
241 static ngx_int_t ngx_quic_output_frames(ngx_connection_t *c, 241 static ngx_int_t ngx_quic_output_frames(ngx_connection_t *c,
242 ngx_quic_send_ctx_t *ctx); 242 ngx_quic_send_ctx_t *ctx);
243 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames); 243 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames);
244 static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames); 244 static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c,
245 ngx_quic_send_ctx_t *ctx, ngx_queue_t *frames);
245 246
246 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, 247 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
247 ngx_quic_send_ctx_t *ctx); 248 ngx_quic_send_ctx_t *ctx);
248 static void ngx_quic_pto_handler(ngx_event_t *ev); 249 static void ngx_quic_pto_handler(ngx_event_t *ev);
249 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, 250 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c,
3258 if (!qc->send_timer_set && !qc->closing) { 3259 if (!qc->send_timer_set && !qc->closing) {
3259 qc->send_timer_set = 1; 3260 qc->send_timer_set = 1;
3260 ngx_add_timer(c->read, qc->tp.max_idle_timeout); 3261 ngx_add_timer(c->read, qc->tp.max_idle_timeout);
3261 } 3262 }
3262 3263
3263 if (!qc->pto.timer_set && !qc->closing) {
3264 ngx_add_timer(&qc->pto, qc->ctp.max_ack_delay + NGX_QUIC_HARDCODED_PTO);
3265 }
3266
3267 return NGX_OK; 3264 return NGX_OK;
3268 } 3265 }
3269 3266
3270 3267
3271 static ngx_int_t 3268 static ngx_int_t
3272 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) 3269 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3273 { 3270 {
3274 size_t len, hlen, n; 3271 size_t len, hlen, n;
3275 ngx_int_t rc;
3276 ngx_uint_t need_ack; 3272 ngx_uint_t need_ack;
3277 ngx_queue_t *q, range; 3273 ngx_queue_t *q, range;
3278 ngx_quic_frame_t *f; 3274 ngx_quic_frame_t *f;
3279 ngx_quic_congestion_t *cg; 3275 ngx_quic_congestion_t *cg;
3280 ngx_quic_connection_t *qc; 3276 ngx_quic_connection_t *qc;
3330 3326
3331 if (ngx_queue_empty(&range)) { 3327 if (ngx_queue_empty(&range)) {
3332 break; 3328 break;
3333 } 3329 }
3334 3330
3335 rc = ngx_quic_send_frames(c, &range); 3331 if (ngx_quic_send_frames(c, ctx, &range) != NGX_OK) {
3336
3337 if (rc == NGX_OK) {
3338 /*
3339 * frames are moved into the sent queue
3340 * to wait for ack/be retransmitted
3341 */
3342 if (qc->closing) {
3343 /* if we are closing, any ack will be discarded */
3344 ngx_quic_free_frames(c, &range);
3345
3346 } else {
3347 ngx_queue_add(&ctx->sent, &range);
3348 }
3349
3350 cg->in_flight += len;
3351
3352 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3353 "quic congestion send if:%uz", cg->in_flight);
3354
3355 } else if (rc == NGX_DONE) {
3356
3357 /* no ack is expected for this frames, can free them */
3358 ngx_quic_free_frames(c, &range);
3359
3360 } else {
3361 return NGX_ERROR; 3332 return NGX_ERROR;
3362 } 3333 }
3363 3334
3364 } while (q != ngx_queue_sentinel(&ctx->frames)); 3335 } while (q != ngx_queue_sentinel(&ctx->frames));
3365 3336
3388 } while (1); 3359 } while (1);
3389 } 3360 }
3390 3361
3391 3362
3392 static ngx_int_t 3363 static ngx_int_t
3393 ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames) 3364 ngx_quic_send_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
3365 ngx_queue_t *frames)
3394 { 3366 {
3395 ssize_t len; 3367 ssize_t len;
3396 u_char *p; 3368 u_char *p;
3397 ngx_msec_t now; 3369 ngx_msec_t now;
3398 ngx_str_t out, res; 3370 ngx_str_t out, res;
3399 ngx_queue_t *q; 3371 ngx_queue_t *q;
3400 ngx_ssl_conn_t *ssl_conn; 3372 ngx_ssl_conn_t *ssl_conn;
3401 ngx_quic_frame_t *f, *start; 3373 ngx_quic_frame_t *f, *start;
3402 ngx_quic_header_t pkt; 3374 ngx_quic_header_t pkt;
3403 ngx_quic_secrets_t *keys; 3375 ngx_quic_secrets_t *keys;
3404 ngx_quic_send_ctx_t *ctx;
3405 ngx_quic_connection_t *qc; 3376 ngx_quic_connection_t *qc;
3406 static ngx_str_t initial_token = ngx_null_string; 3377 static ngx_str_t initial_token = ngx_null_string;
3407 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 3378 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
3408 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 3379 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
3409 3380
3412 3383
3413 ssl_conn = c->ssl ? c->ssl->connection : NULL; 3384 ssl_conn = c->ssl ? c->ssl->connection : NULL;
3414 3385
3415 q = ngx_queue_head(frames); 3386 q = ngx_queue_head(frames);
3416 start = ngx_queue_data(q, ngx_quic_frame_t, queue); 3387 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
3417
3418 ctx = ngx_quic_get_send_ctx(c->quic, start->level);
3419 3388
3420 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 3389 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
3421 3390
3422 now = ngx_current_msec; 3391 now = ngx_current_msec;
3423 3392
3505 } 3474 }
3506 3475
3507 /* len == NGX_OK || NGX_AGAIN */ 3476 /* len == NGX_OK || NGX_AGAIN */
3508 ctx->pnum++; 3477 ctx->pnum++;
3509 3478
3510 return pkt.need_ack ? NGX_OK : NGX_DONE; 3479 if (pkt.need_ack) {
3480 /* move frames into the sent queue to wait for ack */
3481
3482 if (qc->closing) {
3483 /* if we are closing, any ack will be discarded */
3484 ngx_quic_free_frames(c, frames);
3485
3486 } else {
3487 ngx_queue_add(&ctx->sent, frames);
3488 ngx_add_timer(&qc->pto, NGX_QUIC_HARDCODED_PTO);
3489 }
3490
3491 qc->congestion.in_flight += out.len;
3492
3493 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3494 "quic congestion send if:%uz",
3495 qc->congestion.in_flight);
3496 } else {
3497 /* no ack is expected for this frames, so we can free them */
3498 ngx_quic_free_frames(c, frames);
3499 }
3500
3501 return NGX_OK;
3511 } 3502 }
3512 3503
3513 3504
3514 static void 3505 static void
3515 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx) 3506 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx)
3648 3639
3649 } while (q != ngx_queue_sentinel(&ctx->sent)); 3640 } while (q != ngx_queue_sentinel(&ctx->sent));
3650 3641
3651 ngx_quic_congestion_lost(c, start->last); 3642 ngx_quic_congestion_lost(c, start->last);
3652 3643
3653 /* NGX_DONE is impossible here, such frames don't get into this queue */ 3644 if (ngx_quic_send_frames(c, ctx, &range) != NGX_OK) {
3654 if (ngx_quic_send_frames(c, &range) != NGX_OK) {
3655 return NGX_ERROR; 3645 return NGX_ERROR;
3656 } 3646 }
3657
3658 /* move frames group to the end of queue */
3659 ngx_queue_add(&ctx->sent, &range);
3660
3661 wait = qc->ctp.max_ack_delay + NGX_QUIC_HARDCODED_PTO;
3662 3647
3663 } while (q != ngx_queue_sentinel(&ctx->sent)); 3648 } while (q != ngx_queue_sentinel(&ctx->sent));
3664 3649
3665 *waitp = wait; 3650 *waitp = wait;
3666 3651