Latest update - GitHub 020b1db7e

This commit is contained in:
2025-04-22 21:10:22 +09:00
parent f35d500e17
commit 5a9ef13268
31 changed files with 683 additions and 162 deletions
+30 -5
View File
@@ -5079,7 +5079,8 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
#ifdef SSL_get_negotiated_group
int nid;
int nid;
const char *name;
nid = SSL_get_negotiated_group(c->ssl->connection);
@@ -5091,14 +5092,24 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
return NGX_OK;
}
s->len = sizeof("0x0000") - 1;
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
name = SSL_group_to_name(c->ssl->connection, nid);
#else
name = NULL;
#endif
s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1;
s->data = ngx_pnalloc(pool, s->len);
if (s->data == NULL) {
return NGX_ERROR;
}
ngx_sprintf(s->data, "0x%04xd", nid & 0xffff);
if (name) {
ngx_memcpy(s->data, name, s->len);
} else {
ngx_sprintf(s->data, "0x%04xd", nid & 0xffff);
}
return NGX_OK;
}
@@ -5118,6 +5129,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
int *curves, n, i, nid;
u_char *p;
size_t len;
const char *name;
n = SSL_get1_curves(c->ssl->connection, NULL);
@@ -5138,7 +5150,13 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
nid = curves[i];
if (nid & TLSEXT_nid_unknown) {
len += sizeof("0x0000") - 1;
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
name = SSL_group_to_name(c->ssl->connection, nid);
#else
name = NULL;
#endif
len += name ? ngx_strlen(name) : sizeof("0x0000") - 1;
} else {
len += ngx_strlen(OBJ_nid2sn(nid));
@@ -5158,7 +5176,14 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
nid = curves[i];
if (nid & TLSEXT_nid_unknown) {
p = ngx_sprintf(p, "0x%04xd", nid & 0xffff);
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
name = SSL_group_to_name(c->ssl->connection, nid);
#else
name = NULL;
#endif
p = name ? ngx_cpymem(p, name, ngx_strlen(name))
: ngx_sprintf(p, "0x%04xd", nid & 0xffff);
} else {
p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid));
+8 -3
View File
@@ -308,11 +308,16 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;
qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
ngx_max(2 * qc->tp.max_udp_payload_size,
qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE,
ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE,
14720));
qc->congestion.ssthresh = (size_t) -1;
qc->congestion.recovery_start = ngx_current_msec;
qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE;
qc->congestion.recovery_start = ngx_current_msec - 1;
qc->max_frames = (conf->max_concurrent_streams_uni
+ conf->max_concurrent_streams_bidi)
* conf->stream_buffer_size / 2000;
if (pkt->validated && pkt->retried) {
qc->tp.retry_scid.len = pkt->dcid.len;
+315 -46
View File
@@ -20,6 +20,10 @@
/* RFC 9002, 7.6.1. Duration: kPersistentCongestionThreshold */
#define NGX_QUIC_PERSISTENT_CONGESTION_THR 3
/* CUBIC parameters x10 */
#define NGX_QUIC_CUBIC_BETA 7
#define MGX_QUIC_CUBIC_C 4
/* send time of ACK'ed packets */
typedef struct {
@@ -29,18 +33,22 @@ typedef struct {
} ngx_quic_ack_stat_t;
static ngx_inline ngx_msec_t ngx_quic_lost_threshold(ngx_quic_connection_t *qc);
static ngx_inline ngx_msec_t ngx_quic_time_threshold(ngx_quic_connection_t *qc);
static uint64_t ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx);
static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
enum ssl_encryption_level_t level, ngx_msec_t send_time);
static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max,
ngx_quic_ack_stat_t *st);
static size_t ngx_quic_congestion_cubic(ngx_connection_t *c);
static void ngx_quic_drop_ack_ranges(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx, uint64_t pn);
static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c,
ngx_quic_ack_stat_t *st);
static ngx_msec_t ngx_quic_congestion_cubic_time(ngx_connection_t *c);
static ngx_msec_t ngx_quic_pcg_duration(ngx_connection_t *c);
static void ngx_quic_persistent_congestion(ngx_connection_t *c);
static ngx_msec_t ngx_quic_oldest_sent_packet(ngx_connection_t *c);
static void ngx_quic_congestion_lost(ngx_connection_t *c,
ngx_quic_frame_t *frame);
static void ngx_quic_lost_handler(ngx_event_t *ev);
@@ -48,7 +56,7 @@ static void ngx_quic_lost_handler(ngx_event_t *ev);
/* RFC 9002, 6.1.2. Time Threshold: kTimeThreshold, kGranularity */
static ngx_inline ngx_msec_t
ngx_quic_lost_threshold(ngx_quic_connection_t *qc)
ngx_quic_time_threshold(ngx_quic_connection_t *qc)
{
ngx_msec_t thr;
@@ -59,6 +67,29 @@ ngx_quic_lost_threshold(ngx_quic_connection_t *qc)
}
static uint64_t
ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx)
{
uint64_t pkt_thr;
ngx_queue_t *q;
ngx_quic_frame_t *f;
if (ngx_queue_empty(&ctx->sent)) {
return NGX_QUIC_PKT_THR;
}
q = ngx_queue_head(&ctx->sent);
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
pkt_thr = (ctx->pnum - f->pnum) / 2;
if (pkt_thr <= NGX_QUIC_PKT_THR) {
return NGX_QUIC_PKT_THR;
}
return pkt_thr;
}
ngx_int_t
ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *f)
@@ -313,8 +344,9 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
void
ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
{
size_t w_cubic;
ngx_uint_t blocked;
ngx_msec_t timer;
ngx_msec_t now, timer;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
@@ -329,16 +361,34 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
return;
}
now = ngx_current_msec;
blocked = (cg->in_flight >= cg->window) ? 1 : 0;
cg->in_flight -= f->plen;
/* prevent recovery_start from wrapping */
timer = now - cg->recovery_start;
if ((ngx_msec_int_t) timer < 0) {
cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1;
}
timer = f->send_time - cg->recovery_start;
if ((ngx_msec_int_t) timer <= 0) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack recovery win:%uz ss:%z if:%uz",
cg->window, cg->ssthresh, cg->in_flight);
"quic congestion ack rec t:%M win:%uz if:%uz",
now, cg->window, cg->in_flight);
goto done;
}
if (cg->idle) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack idle t:%M win:%uz if:%uz",
now, cg->window, cg->in_flight);
goto done;
}
@@ -346,24 +396,51 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
if (cg->window < cg->ssthresh) {
cg->window += f->plen;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion slow start win:%uz ss:%z if:%uz",
cg->window, cg->ssthresh, cg->in_flight);
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack ss t:%M win:%uz ss:%z if:%uz",
now, cg->window, cg->ssthresh, cg->in_flight);
} else {
cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion avoidance win:%uz ss:%z if:%uz",
cg->window, cg->ssthresh, cg->in_flight);
}
/* RFC 9438, 4.2. Window Increase Function */
/* prevent recovery_start from wrapping */
w_cubic = ngx_quic_congestion_cubic(c);
timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2;
if (cg->window < cg->w_prior) {
cg->w_est += (uint64_t) cg->mtu * f->plen
* 3 * (10 - NGX_QUIC_CUBIC_BETA)
/ (10 + NGX_QUIC_CUBIC_BETA) / cg->window;
if ((ngx_msec_int_t) timer < 0) {
cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
} else {
cg->w_est += (uint64_t) cg->mtu * f->plen / cg->window;
}
if (w_cubic < cg->w_est) {
cg->window = cg->w_est;
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack reno t:%M win:%uz c:%uz if:%uz",
now, cg->window, w_cubic, cg->in_flight);
} else if (w_cubic > cg->window) {
if (w_cubic >= cg->window * 3 / 2) {
cg->window += cg->mtu / 2;
} else {
cg->window += (uint64_t) cg->mtu * (w_cubic - cg->window)
/ cg->window;
}
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack cubic t:%M win:%uz c:%uz if:%uz",
now, cg->window, w_cubic, cg->in_flight);
} else {
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion ack skip t:%M win:%uz c:%uz if:%uz",
now, cg->window, w_cubic, cg->in_flight);
}
}
done:
@@ -374,6 +451,87 @@ done:
}
static size_t
ngx_quic_congestion_cubic(ngx_connection_t *c)
{
int64_t w, t, cc;
ngx_msec_t now;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
ngx_quic_congestion_idle(c, cg->idle);
now = ngx_current_msec;
t = (ngx_msec_int_t) (now - cg->k);
if (t > 1000000) {
w = NGX_MAX_SIZE_T_VALUE;
goto done;
}
if (t < -1000000) {
w = 0;
goto done;
}
/*
* RFC 9438, Figure 1
*
* w_cubic = C * (t_msec / 1000) ^ 3 * mtu + w_max
*/
cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C;
w = t * t * t / cc + (int64_t) cg->w_max;
if (w > NGX_MAX_SIZE_T_VALUE) {
w = NGX_MAX_SIZE_T_VALUE;
}
if (w < 0) {
w = 0;
}
done:
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic cubic t:%L w:%L wm:%uz", t, w, cg->w_max);
return w;
}
void
ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle)
{
ngx_msec_t now;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion idle:%ui", idle);
if (cg->window >= cg->ssthresh) {
/* RFC 9438, 5.8. Behavior for Application-Limited Flows */
now = ngx_current_msec;
if (cg->idle) {
cg->k += now - cg->idle_start;
}
cg->idle_start = now;
}
cg->idle = idle;
}
static void
ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
uint64_t pn)
@@ -435,6 +593,7 @@ ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
static ngx_int_t
ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
{
uint64_t pkt_thr;
ngx_uint_t i, nlost;
ngx_msec_t now, wait, thr, oldest, newest;
ngx_queue_t *q;
@@ -444,11 +603,12 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
qc = ngx_quic_get_connection(c);
now = ngx_current_msec;
thr = ngx_quic_lost_threshold(qc);
thr = ngx_quic_time_threshold(qc);
/* send time of lost packets across all send contexts */
oldest = NGX_TIMER_INFINITE;
newest = NGX_TIMER_INFINITE;
#if (NGX_SUPPRESS_WARN)
oldest = now;
newest = now;
#endif
nlost = 0;
@@ -460,6 +620,8 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
continue;
}
pkt_thr = ngx_quic_packet_threshold(ctx);
while (!ngx_queue_empty(&ctx->sent)) {
q = ngx_queue_head(&ctx->sent);
@@ -471,23 +633,27 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
wait = start->send_time + thr - now;
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic detect_lost pnum:%uL thr:%M wait:%i level:%d",
start->pnum, thr, (ngx_int_t) wait, start->level);
ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic detect_lost pnum:%uL thr:%M pthr:%uL wait:%i level:%d",
start->pnum, thr, pkt_thr, (ngx_int_t) wait, start->level);
if ((ngx_msec_int_t) wait > 0
&& ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR)
&& ctx->largest_ack - start->pnum < pkt_thr)
{
break;
}
if (start->send_time > qc->first_rtt) {
if ((ngx_msec_int_t) (start->send_time - qc->first_rtt) > 0) {
if (oldest == NGX_TIMER_INFINITE || start->send_time < oldest) {
if (nlost == 0
|| (ngx_msec_int_t) (start->send_time - oldest) < 0)
{
oldest = start->send_time;
}
if (newest == NGX_TIMER_INFINITE || start->send_time > newest) {
if (nlost == 0
|| (ngx_msec_int_t) (start->send_time - newest) > 0)
{
newest = start->send_time;
}
@@ -508,8 +674,9 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
* latest ACK frame.
*/
if (st && nlost >= 2 && (st->newest < oldest || st->oldest > newest)) {
if (st && nlost >= 2 && ((ngx_msec_int_t) (st->newest - oldest) < 0
|| (ngx_msec_int_t) (st->oldest - newest) > 0))
{
if (newest - oldest > ngx_quic_pcg_duration(c)) {
ngx_quic_persistent_congestion(c);
}
@@ -547,11 +714,43 @@ ngx_quic_persistent_congestion(ngx_connection_t *c)
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
cg->recovery_start = ngx_current_msec;
cg->window = qc->tp.max_udp_payload_size * 2;
cg->mtu = qc->path->mtu;
cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1;
cg->window = cg->mtu * 2;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic persistent congestion win:%uz", cg->window);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion persistent t:%M win:%uz",
ngx_current_msec, cg->window);
}
static ngx_msec_t
ngx_quic_oldest_sent_packet(ngx_connection_t *c)
{
ngx_msec_t oldest;
ngx_uint_t i;
ngx_queue_t *q;
ngx_quic_frame_t *start;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
oldest = ngx_current_msec;
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ctx = &qc->send_ctx[i];
if (!ngx_queue_empty(&ctx->sent)) {
q = ngx_queue_head(&ctx->sent);
start = ngx_queue_data(q, ngx_quic_frame_t, queue);
if ((ngx_msec_int_t) (start->send_time - oldest) < 0) {
oldest = start->send_time;
}
}
}
return oldest;
}
@@ -659,7 +858,7 @@ static void
ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
{
ngx_uint_t blocked;
ngx_msec_t timer;
ngx_msec_t now, timer;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
@@ -681,26 +880,41 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
timer = f->send_time - cg->recovery_start;
now = ngx_current_msec;
if ((ngx_msec_int_t) timer <= 0) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion lost recovery win:%uz ss:%z if:%uz",
cg->window, cg->ssthresh, cg->in_flight);
"quic congestion lost rec t:%M win:%uz if:%uz",
now, cg->window, cg->in_flight);
goto done;
}
cg->recovery_start = ngx_current_msec;
cg->window /= 2;
if (f->ignore_loss) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion lost ignore t:%M win:%uz if:%uz",
now, cg->window, cg->in_flight);
if (cg->window < qc->tp.max_udp_payload_size * 2) {
cg->window = qc->tp.max_udp_payload_size * 2;
goto done;
}
cg->ssthresh = cg->window;
/* RFC 9438, 4.6. Multiplicative Decrease */
cg->mtu = qc->path->mtu;
cg->recovery_start = now;
cg->w_prior = cg->window;
/* RFC 9438, 4.7. Fast Convergence */
cg->w_max = (cg->window < cg->w_max)
? cg->window * (10 + NGX_QUIC_CUBIC_BETA) / 20 : cg->window;
cg->ssthresh = cg->in_flight * NGX_QUIC_CUBIC_BETA / 10;
cg->window = ngx_max(cg->ssthresh, cg->mtu * 2);
cg->w_est = cg->window;
cg->k = now + ngx_quic_congestion_cubic_time(c);
cg->idle_start = now;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion lost win:%uz ss:%z if:%uz",
cg->window, cg->ssthresh, cg->in_flight);
"quic congestion lost t:%M win:%uz if:%uz",
now, cg->window, cg->in_flight);
done:
@@ -710,9 +924,62 @@ done:
}
static ngx_msec_t
ngx_quic_congestion_cubic_time(ngx_connection_t *c)
{
int64_t v, x, d, cc;
ngx_uint_t n;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
/*
* RFC 9438, Figure 2
*
* k_msec = ((w_max - cwnd_epoch) / C / mtu) ^ 1/3 * 1000
*/
if (cg->w_max <= cg->window) {
return 0;
}
cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C;
v = (int64_t) (cg->w_max - cg->window) * cc;
/*
* Newton-Raphson method for x ^ 3 = v:
*
* x_next = (2 * x_prev + v / x_prev ^ 2) / 3
*/
x = 5000;
for (n = 1; n <= 10; n++) {
d = (v / x / x - x) / 3;
x += d;
if (ngx_abs(d) <= 100) {
break;
}
}
if (x > NGX_MAX_SIZE_T_VALUE) {
return NGX_MAX_SIZE_T_VALUE;
}
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic cubic time:%L n:%ui", x, n);
return x;
}
void
ngx_quic_set_lost_timer(ngx_connection_t *c)
{
uint64_t pkt_thr;
ngx_uint_t i;
ngx_msec_t now;
ngx_queue_t *q;
@@ -738,10 +1005,12 @@ ngx_quic_set_lost_timer(ngx_connection_t *c)
q = ngx_queue_head(&ctx->sent);
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
w = (ngx_msec_int_t)
(f->send_time + ngx_quic_lost_threshold(qc) - now);
(f->send_time + ngx_quic_time_threshold(qc) - now);
if (f->pnum <= ctx->largest_ack) {
if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) {
pkt_thr = ngx_quic_packet_threshold(ctx);
if (w < 0 || ctx->largest_ack - f->pnum >= pkt_thr) {
w = 0;
}
+1
View File
@@ -17,6 +17,7 @@ ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
void ngx_quic_congestion_ack(ngx_connection_t *c,
ngx_quic_frame_t *frame);
void ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle);
void ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx);
void ngx_quic_set_lost_timer(ngx_connection_t *c);
void ngx_quic_pto_handler(ngx_event_t *ev);
@@ -168,7 +168,14 @@ typedef struct {
size_t in_flight;
size_t window;
size_t ssthresh;
size_t w_max;
size_t w_est;
size_t w_prior;
size_t mtu;
ngx_msec_t recovery_start;
ngx_msec_t idle_start;
ngx_msec_t k;
ngx_uint_t idle; /* unsigned idle:1; */
} ngx_quic_congestion_t;
@@ -254,6 +261,7 @@ struct ngx_quic_connection_s {
ngx_buf_t *free_shadow_bufs;
ngx_uint_t nframes;
ngx_uint_t max_frames;
#ifdef NGX_QUIC_DEBUG_ALLOC
ngx_uint_t nbufs;
ngx_uint_t nshadowbufs;
+1 -1
View File
@@ -214,7 +214,7 @@ ngx_quic_alloc_frame(ngx_connection_t *c)
"quic reuse frame n:%ui", qc->nframes);
#endif
} else if (qc->nframes < 10000) {
} else if (qc->nframes < qc->max_frames) {
frame = ngx_palloc(c->pool, sizeof(ngx_quic_frame_t));
if (frame == NULL) {
return NULL;
+6 -3
View File
@@ -182,11 +182,12 @@ valid:
ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t));
qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
ngx_max(2 * qc->tp.max_udp_payload_size,
qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE,
ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE,
14720));
qc->congestion.ssthresh = (size_t) -1;
qc->congestion.recovery_start = ngx_current_msec;
qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE;
qc->congestion.recovery_start = ngx_current_msec - 1;
ngx_quic_init_rtt(qc);
}
@@ -923,6 +924,8 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_PING;
frame->ignore_loss = 1;
frame->ignore_congestion = 1;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
+62 -42
View File
@@ -45,9 +45,9 @@
static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c);
static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx);
static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
uint64_t pnum);
static void ngx_quic_commit_send(ngx_connection_t *c);
static void ngx_quic_revert_send(ngx_connection_t *c,
uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]);
#if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c);
static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c);
@@ -127,6 +127,10 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
cg = &qc->congestion;
path = qc->path;
#if (NGX_SUPPRESS_WARN)
ngx_memzero(preserved_pnum, sizeof(preserved_pnum));
#endif
while (cg->in_flight < cg->window) {
p = dst;
@@ -150,12 +154,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
if (min > len) {
/* padding can't be applied - avoid sending the packet */
while (i-- > 0) {
ctx = &qc->send_ctx[i];
ngx_quic_revert_send(c, ctx, preserved_pnum[i]);
}
ngx_quic_revert_send(c, preserved_pnum);
return NGX_OK;
}
@@ -180,17 +179,12 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
}
if (n == NGX_AGAIN) {
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ngx_quic_revert_send(c, &qc->send_ctx[i], preserved_pnum[i]);
}
ngx_quic_revert_send(c, preserved_pnum);
ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY);
break;
}
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ngx_quic_commit_send(c, &qc->send_ctx[i]);
}
ngx_quic_commit_send(c);
path->sent += len;
}
@@ -200,53 +194,79 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
static void
ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
ngx_quic_commit_send(ngx_connection_t *c)
{
ngx_uint_t i, idle;
ngx_queue_t *q;
ngx_quic_frame_t *f;
ngx_quic_send_ctx_t *ctx;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
while (!ngx_queue_empty(&ctx->sending)) {
idle = 1;
q = ngx_queue_head(&ctx->sending);
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ctx = &qc->send_ctx[i];
ngx_queue_remove(q);
if (!ngx_queue_empty(&ctx->frames)) {
idle = 0;
}
if (f->pkt_need_ack && !qc->closing) {
ngx_queue_insert_tail(&ctx->sent, q);
while (!ngx_queue_empty(&ctx->sending)) {
cg->in_flight += f->plen;
q = ngx_queue_head(&ctx->sending);
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
} else {
ngx_quic_free_frame(c, f);
ngx_queue_remove(q);
if (f->pkt_need_ack && !qc->closing) {
ngx_queue_insert_tail(&ctx->sent, q);
cg->in_flight += f->plen;
} else {
ngx_quic_free_frame(c, f);
}
}
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic congestion send if:%uz", cg->in_flight);
ngx_quic_congestion_idle(c, idle);
}
static void
ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
uint64_t pnum)
ngx_quic_revert_send(ngx_connection_t *c, uint64_t pnum[NGX_QUIC_SEND_CTX_LAST])
{
ngx_queue_t *q;
ngx_uint_t i;
ngx_queue_t *q;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
while (!ngx_queue_empty(&ctx->sending)) {
qc = ngx_quic_get_connection(c);
q = ngx_queue_last(&ctx->sending);
ngx_queue_remove(q);
ngx_queue_insert_head(&ctx->frames, q);
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ctx = &qc->send_ctx[i];
if (ngx_queue_empty(&ctx->sending)) {
continue;
}
do {
q = ngx_queue_last(&ctx->sending);
ngx_queue_remove(q);
ngx_queue_insert_head(&ctx->frames, q);
} while (!ngx_queue_empty(&ctx->sending));
ctx->pnum = pnum[i];
}
ctx->pnum = pnum;
ngx_quic_congestion_idle(c, 1);
}
@@ -311,13 +331,13 @@ ngx_quic_create_segments(ngx_connection_t *c)
size_t len, segsize;
ssize_t n;
u_char *p, *end;
uint64_t preserved_pnum;
ngx_uint_t nseg;
ngx_uint_t nseg, level;
ngx_quic_path_t *path;
ngx_quic_send_ctx_t *ctx;
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];
static uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST];
qc = ngx_quic_get_connection(c);
cg = &qc->congestion;
@@ -335,7 +355,8 @@ ngx_quic_create_segments(ngx_connection_t *c)
nseg = 0;
preserved_pnum = ctx->pnum;
level = ctx - qc->send_ctx;
preserved_pnum[level] = ctx->pnum;
for ( ;; ) {
@@ -369,19 +390,18 @@ ngx_quic_create_segments(ngx_connection_t *c)
}
if (n == NGX_AGAIN) {
ngx_quic_revert_send(c, ctx, preserved_pnum);
ngx_quic_revert_send(c, preserved_pnum);
ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY);
break;
}
ngx_quic_commit_send(c, ctx);
ngx_quic_commit_send(c);
path->sent += n;
p = dst;
nseg = 0;
preserved_pnum = ctx->pnum;
preserved_pnum[level] = ctx->pnum;
}
}
+7 -5
View File
@@ -125,9 +125,10 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
ngx_quic_secret_t *client, *server;
ngx_quic_ciphers_t ciphers;
static const uint8_t salt[20] =
"\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17"
"\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a";
static const uint8_t salt[20] = {
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
};
client = &keys->secrets[ssl_encryption_initial].client;
server = &keys->secrets[ssl_encryption_initial].server;
@@ -958,8 +959,9 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res)
/* 5.8. Retry Packet Integrity */
static ngx_quic_md_t key = ngx_quic_md(
"\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e");
static const u_char nonce[NGX_QUIC_IV_LEN] =
"\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb";
static const u_char nonce[NGX_QUIC_IV_LEN] = {
0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb
};
static ngx_str_t in = ngx_string("");
ad.data = res->data;
+1 -1
View File
@@ -1773,7 +1773,7 @@ ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp,
}
if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_INFO, log, 0,
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
"quic %s transport param id:0x%xL, skipped",
(id % 31 == 27) ? "reserved" : "unknown", id);
}
@@ -271,6 +271,7 @@ struct ngx_quic_frame_s {
unsigned need_ack:1;
unsigned pkt_need_ack:1;
unsigned ignore_congestion:1;
unsigned ignore_loss:1;
ngx_chain_t *data;
union {