comparison src/event/quic/ngx_event_quic_output.c @ 9147:58afcd72446f

QUIC: path MTU discovery. MTU selection starts by doubling the initial MTU until the first failure. Then binary search is used to find the path MTU.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 14 Aug 2023 09:21:27 +0400
parents f3412ec3b6d1
children 60c4e8d3151f
comparison
equal deleted inserted replaced
9146:f3412ec3b6d1 9147:58afcd72446f
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_event_quic_connection.h> 10 #include <ngx_event_quic_connection.h>
11 11
12
13 #define NGX_QUIC_MAX_UDP_PAYLOAD_OUT 1252
14 #define NGX_QUIC_MAX_UDP_PAYLOAD_OUT6 1232
15 12
16 #define NGX_QUIC_MAX_UDP_SEGMENT_BUF 65487 /* 65K - IPv6 header */ 13 #define NGX_QUIC_MAX_UDP_SEGMENT_BUF 65487 /* 65K - IPv6 header */
17 #define NGX_QUIC_MAX_SEGMENTS 64 /* UDP_MAX_SEGMENTS */ 14 #define NGX_QUIC_MAX_SEGMENTS 64 /* UDP_MAX_SEGMENTS */
18 15
19 #define NGX_QUIC_RETRY_TOKEN_LIFETIME 3 /* seconds */ 16 #define NGX_QUIC_RETRY_TOKEN_LIFETIME 3 /* seconds */
59 ngx_quic_send_ctx_t *ctx); 56 ngx_quic_send_ctx_t *ctx);
60 static size_t ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, 57 static size_t ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path,
61 size_t size); 58 size_t size);
62 59
63 60
64 size_t
65 ngx_quic_max_udp_payload(ngx_connection_t *c)
66 {
67 /* TODO: path MTU discovery */
68
69 #if (NGX_HAVE_INET6)
70 if (c->sockaddr->sa_family == AF_INET6) {
71 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT6;
72 }
73 #endif
74
75 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT;
76 }
77
78
79 ngx_int_t 61 ngx_int_t
80 ngx_quic_output(ngx_connection_t *c) 62 ngx_quic_output(ngx_connection_t *c)
81 { 63 {
82 size_t in_flight; 64 size_t in_flight;
83 ngx_int_t rc; 65 ngx_int_t rc;
140 122
141 while (cg->in_flight < cg->window) { 123 while (cg->in_flight < cg->window) {
142 124
143 p = dst; 125 p = dst;
144 126
145 len = ngx_min(qc->ctp.max_udp_payload_size, 127 len = ngx_quic_path_limit(c, path, path->mtu);
146 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
147
148 len = ngx_quic_path_limit(c, path, len);
149 128
150 pad = ngx_quic_get_padding_level(c); 129 pad = ngx_quic_get_padding_level(c);
151 130
152 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { 131 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
153 132
297 } 276 }
298 277
299 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); 278 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
300 279
301 bytes = 0; 280 bytes = 0;
302 281 len = ngx_min(qc->path->mtu, NGX_QUIC_MAX_UDP_SEGMENT_BUF);
303 len = ngx_min(qc->ctp.max_udp_payload_size,
304 NGX_QUIC_MAX_UDP_SEGMENT_BUF);
305 282
306 for (q = ngx_queue_head(&ctx->frames); 283 for (q = ngx_queue_head(&ctx->frames);
307 q != ngx_queue_sentinel(&ctx->frames); 284 q != ngx_queue_sentinel(&ctx->frames);
308 q = ngx_queue_next(q)) 285 q = ngx_queue_next(q))
309 { 286 {
343 320
344 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { 321 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
345 return NGX_ERROR; 322 return NGX_ERROR;
346 } 323 }
347 324
348 segsize = ngx_min(qc->ctp.max_udp_payload_size, 325 segsize = ngx_min(path->mtu, NGX_QUIC_MAX_UDP_SEGMENT_BUF);
349 NGX_QUIC_MAX_UDP_SEGMENT_BUF);
350 p = dst; 326 p = dst;
351 end = dst + sizeof(dst); 327 end = dst + sizeof(dst);
352 328
353 nseg = 0; 329 nseg = 0;
354 330