comparison src/event/quic/ngx_event_quic_output.c @ 8758:e72db9162180 quic

QUIC: got rid of excessive "qsock" argument in ngx_quic_output.c. The output is always sent to the active path, which is stored in the quic connection. There is no need to pass it in arguments. When output has to be send to to a specific path (in rare cases, such as path probing), a separate method exists (ngx_quic_frame_sendto()).
author Vladimir Homutov <vl@nginx.com>
date Mon, 27 Dec 2021 13:52:57 +0300
parents 0433e69f5425
children 19e063e955bf
comparison
equal deleted inserted replaced
8757:b7284807b4fa 8758:e72db9162180
36 #define NGX_QUIC_CC_MIN_INTERVAL 1000 /* 1s */ 36 #define NGX_QUIC_CC_MIN_INTERVAL 1000 /* 1s */
37 37
38 #define NGX_QUIC_SOCKET_RETRY_DELAY 10 /* ms, for NGX_AGAIN on write */ 38 #define NGX_QUIC_SOCKET_RETRY_DELAY 10 /* ms, for NGX_AGAIN on write */
39 39
40 40
41 static ngx_int_t ngx_quic_socket_output(ngx_connection_t *c, 41 static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c);
42 ngx_quic_socket_t *qsock);
43 static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c,
44 ngx_quic_socket_t *qsock);
45 static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx); 42 static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx);
46 static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, 43 static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
47 uint64_t pnum); 44 uint64_t pnum);
48 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL)) 45 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
49 static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c, 46 static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c);
50 ngx_quic_socket_t *qsock); 47 static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c);
51 static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c,
52 ngx_quic_socket_t *qsock);
53 static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, 48 static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf,
54 size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); 49 size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment);
55 #endif 50 #endif
56 static ssize_t ngx_quic_output_packet(ngx_connection_t *c, 51 static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
57 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min, 52 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
58 ngx_quic_socket_t *qsock);
59 static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, 53 static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
60 ngx_quic_socket_t *qsock, ngx_quic_header_t *pkt); 54 ngx_quic_header_t *pkt);
61 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); 55 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
62 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len, 56 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len,
63 struct sockaddr *sockaddr, socklen_t socklen); 57 struct sockaddr *sockaddr, socklen_t socklen);
64 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, 58 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
65 ngx_quic_send_ctx_t *ctx); 59 ngx_quic_send_ctx_t *ctx);
83 77
84 78
85 ngx_int_t 79 ngx_int_t
86 ngx_quic_output(ngx_connection_t *c) 80 ngx_quic_output(ngx_connection_t *c)
87 { 81 {
88 ngx_quic_connection_t *qc;
89
90 qc = ngx_quic_get_connection(c);
91
92 if (ngx_quic_socket_output(c, qc->socket) != NGX_OK) {
93 return NGX_ERROR;
94 }
95
96 ngx_quic_set_lost_timer(c);
97
98 return NGX_OK;
99 }
100
101
102 static ngx_int_t
103 ngx_quic_socket_output(ngx_connection_t *c, ngx_quic_socket_t *qsock)
104 {
105 size_t in_flight; 82 size_t in_flight;
106 ngx_int_t rc; 83 ngx_int_t rc;
107 ngx_quic_congestion_t *cg; 84 ngx_quic_congestion_t *cg;
108 ngx_quic_connection_t *qc; 85 ngx_quic_connection_t *qc;
109 86
113 cg = &qc->congestion; 90 cg = &qc->congestion;
114 91
115 in_flight = cg->in_flight; 92 in_flight = cg->in_flight;
116 93
117 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL)) 94 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
118 if (ngx_quic_allow_segmentation(c, qsock)) { 95 if (ngx_quic_allow_segmentation(c)) {
119 rc = ngx_quic_create_segments(c, qsock); 96 rc = ngx_quic_create_segments(c);
120 } else 97 } else
121 #endif 98 #endif
122 { 99 {
123 rc = ngx_quic_create_datagrams(c, qsock); 100 rc = ngx_quic_create_datagrams(c);
124 } 101 }
125 102
126 if (rc != NGX_OK) { 103 if (rc != NGX_OK) {
127 return NGX_ERROR; 104 return NGX_ERROR;
128 } 105 }
130 if (in_flight != cg->in_flight && !qc->send_timer_set && !qc->closing) { 107 if (in_flight != cg->in_flight && !qc->send_timer_set && !qc->closing) {
131 qc->send_timer_set = 1; 108 qc->send_timer_set = 1;
132 ngx_add_timer(c->read, qc->tp.max_idle_timeout); 109 ngx_add_timer(c->read, qc->tp.max_idle_timeout);
133 } 110 }
134 111
112 ngx_quic_set_lost_timer(c);
113
135 return NGX_OK; 114 return NGX_OK;
136 } 115 }
137 116
138 117
139 static ngx_int_t 118 static ngx_int_t
140 ngx_quic_create_datagrams(ngx_connection_t *c, ngx_quic_socket_t *qsock) 119 ngx_quic_create_datagrams(ngx_connection_t *c)
141 { 120 {
142 size_t len, min; 121 size_t len, min;
143 ssize_t n; 122 ssize_t n;
144 u_char *p; 123 u_char *p;
145 uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; 124 uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST];
150 ngx_quic_connection_t *qc; 129 ngx_quic_connection_t *qc;
151 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 130 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
152 131
153 qc = ngx_quic_get_connection(c); 132 qc = ngx_quic_get_connection(c);
154 cg = &qc->congestion; 133 cg = &qc->congestion;
155 path = qsock->path; 134 path = qc->socket->path;
156 135
157 while (cg->in_flight < cg->window) { 136 while (cg->in_flight < cg->window) {
158 137
159 p = dst; 138 p = dst;
160 139
180 159
181 if (min > len) { 160 if (min > len) {
182 continue; 161 continue;
183 } 162 }
184 163
185 n = ngx_quic_output_packet(c, ctx, p, len, min, qsock); 164 n = ngx_quic_output_packet(c, ctx, p, len, min);
186 if (n == NGX_ERROR) { 165 if (n == NGX_ERROR) {
187 return NGX_ERROR; 166 return NGX_ERROR;
188 } 167 }
189 168
190 p += n; 169 p += n;
274 253
275 254
276 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL)) 255 #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
277 256
278 static ngx_uint_t 257 static ngx_uint_t
279 ngx_quic_allow_segmentation(ngx_connection_t *c, ngx_quic_socket_t *qsock) 258 ngx_quic_allow_segmentation(ngx_connection_t *c)
280 { 259 {
281 size_t bytes, len; 260 size_t bytes, len;
282 ngx_queue_t *q; 261 ngx_queue_t *q;
283 ngx_quic_frame_t *f; 262 ngx_quic_frame_t *f;
284 ngx_quic_send_ctx_t *ctx; 263 ngx_quic_send_ctx_t *ctx;
288 267
289 if (!qc->conf->gso_enabled) { 268 if (!qc->conf->gso_enabled) {
290 return 0; 269 return 0;
291 } 270 }
292 271
293 if (qsock->path->limited) { 272 if (qc->socket->path->limited) {
294 /* don't even try to be faster on non-validated paths */ 273 /* don't even try to be faster on non-validated paths */
295 return 0; 274 return 0;
296 } 275 }
297 276
298 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial); 277 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
329 return 0; 308 return 0;
330 } 309 }
331 310
332 311
333 static ngx_int_t 312 static ngx_int_t
334 ngx_quic_create_segments(ngx_connection_t *c, ngx_quic_socket_t *qsock) 313 ngx_quic_create_segments(ngx_connection_t *c)
335 { 314 {
336 size_t len, segsize; 315 size_t len, segsize;
337 ssize_t n; 316 ssize_t n;
338 u_char *p, *end; 317 u_char *p, *end;
339 uint64_t preserved_pnum; 318 uint64_t preserved_pnum;
344 ngx_quic_connection_t *qc; 323 ngx_quic_connection_t *qc;
345 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; 324 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];
346 325
347 qc = ngx_quic_get_connection(c); 326 qc = ngx_quic_get_connection(c);
348 cg = &qc->congestion; 327 cg = &qc->congestion;
349 path = qsock->path; 328 path = qc->socket->path;
350 329
351 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); 330 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
352 331
353 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { 332 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
354 return NGX_ERROR; 333 return NGX_ERROR;
367 346
368 len = ngx_min(segsize, (size_t) (end - p)); 347 len = ngx_min(segsize, (size_t) (end - p));
369 348
370 if (len && cg->in_flight < cg->window) { 349 if (len && cg->in_flight < cg->window) {
371 350
372 n = ngx_quic_output_packet(c, ctx, p, len, len, qsock); 351 n = ngx_quic_output_packet(c, ctx, p, len, len);
373 if (n == NGX_ERROR) { 352 if (n == NGX_ERROR) {
374 return NGX_ERROR; 353 return NGX_ERROR;
375 } 354 }
376 355
377 if (n) { 356 if (n) {
522 } 501 }
523 502
524 503
525 static ssize_t 504 static ssize_t
526 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, 505 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
527 u_char *data, size_t max, size_t min, ngx_quic_socket_t *qsock) 506 u_char *data, size_t max, size_t min)
528 { 507 {
529 size_t len, pad, min_payload, max_payload; 508 size_t len, pad, min_payload, max_payload;
530 u_char *p; 509 u_char *p;
531 ssize_t flen; 510 ssize_t flen;
532 ngx_str_t res; 511 ngx_str_t res;
540 519
541 if (ngx_queue_empty(&ctx->frames)) { 520 if (ngx_queue_empty(&ctx->frames)) {
542 return 0; 521 return 0;
543 } 522 }
544 523
545 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, 524 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
546 "quic output sock #%uL %s packet max:%uz min:%uz", 525 "quic output %s packet max:%uz min:%uz",
547 qsock->sid.seqnum, ngx_quic_level_name(ctx->level), 526 ngx_quic_level_name(ctx->level), max, min);
548 max, min); 527
549 528 ngx_quic_init_packet(c, ctx, &pkt);
550 ngx_quic_init_packet(c, ctx, qsock, &pkt);
551 529
552 min_payload = ngx_quic_payload_size(&pkt, min); 530 min_payload = ngx_quic_payload_size(&pkt, min);
553 max_payload = ngx_quic_payload_size(&pkt, max); 531 max_payload = ngx_quic_payload_size(&pkt, max);
554 532
555 /* RFC 9001, 5.4.2. Header Protection Sample */ 533 /* RFC 9001, 5.4.2. Header Protection Sample */
688 } 666 }
689 667
690 668
691 static void 669 static void
692 ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, 670 ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
693 ngx_quic_socket_t *qsock, ngx_quic_header_t *pkt) 671 ngx_quic_header_t *pkt)
694 { 672 {
673 ngx_quic_socket_t *qsock;
695 ngx_quic_connection_t *qc; 674 ngx_quic_connection_t *qc;
696 675
697 qc = ngx_quic_get_connection(c); 676 qc = ngx_quic_get_connection(c);
677
678 qsock = qc->socket;
698 679
699 ngx_memzero(pkt, sizeof(ngx_quic_header_t)); 680 ngx_memzero(pkt, sizeof(ngx_quic_header_t));
700 681
701 pkt->flags = NGX_QUIC_PKT_FIXED_BIT; 682 pkt->flags = NGX_QUIC_PKT_FIXED_BIT;
702 683
1219 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; 1200 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1220 1201
1221 qc = ngx_quic_get_connection(c); 1202 qc = ngx_quic_get_connection(c);
1222 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); 1203 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
1223 1204
1224 ngx_quic_init_packet(c, ctx, qc->socket, &pkt); 1205 ngx_quic_init_packet(c, ctx, &pkt);
1225 1206
1226 min = ngx_quic_path_limit(c, path, min); 1207 min = ngx_quic_path_limit(c, path, min);
1227 1208
1228 min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0; 1209 min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0;
1229 1210