Welcome! Log In Create A New Profile

Advanced

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Sergey Kandaurov
May 09, 2023 09:00AM
> On 9 May 2023, at 14:11, Sergey Kandaurov <pluknet@nginx.com> wrote:
>
>>
>> On 3 May 2023, at 17:00, Roman Arutyunyan <arut@nginx.com> wrote:
>>
>> Hi,
>>
>> On Mon, Apr 24, 2023 at 04:15:21PM +0400, Sergey Kandaurov wrote:
>>>
>>>
>>>> On 28 Mar 2023, at 18:51, Roman Arutyunyan <arut@nginx.com> wrote:
>>>>
>>>> # HG changeset patch
>>>> # User Roman Arutyunyan <arut@nginx.com>
>>>> # Date 1679925333 -14400
>>>> # Mon Mar 27 17:55:33 2023 +0400
>>>> # Branch quic
>>>> # Node ID f76e83412133085a6c82fce2c3e15b2c34a6e959
>>>> # Parent 5fd628b89bb7fb5c95afa1dc914385f7ab79f6a3
>>>> QUIC: changed path validation timeout.
>>>>
>>>> Path validation packets containing PATH_CHALLENGE frames are sent separately
>>>> from regular frame queue, because of the need to use a decicated path and
>>>> pad the packets. The packets are also resent separately from the regular
>>>> probe/lost detection mechanism. A path validation packet is resent 3 times,
>>>> each time after PTO expiration. Assuming constant PTO, the overall maximum
>>>> waiting time is 3 * PTO. According to RFC 9000, 8.2.4. Failed Path Validation,
>>>> the following value is recommended as a validation timeout:
>>>>
>>>> A value of three times the larger of the current PTO
>>>> or the PTO for the new path (using kInitialRtt, as
>>>> defined in [QUIC-RECOVERY]) is RECOMMENDED.
>>>>
>>>> The change adds PTO of the new path to the equation as the lower bound.
>>>> Also, max_ack_delay is now always accounted for, unlike previously, when
>>>> it was only used when there are packets in flight. As mentioned before,
>>>> PACH_CHALLENGE is not considered in-flight by nginx since it's processed
>>>> separately, but technically it is.
>>>
>>> I don't like an idea to make a separate function to calculate
>>> time for path validation retransmits. It looks like an existing
>>> function could be reused.
>>>
>>> I tend to think checking for inflight packets in ngx_quic_pto()
>>> isn't correct at the first place. The condition comes from
>>> the GetPtoTimeAndSpace example in 9002, A.8:
>>>
>>> : GetPtoTimeAndSpace():
>>> : duration = (smoothed_rtt + max(4 * rttvar, kGranularity))
>>> : * (2 ^ pto_count)
>>> : // Anti-deadlock PTO starts from the current time
>>> : if (no ack-eliciting packets in flight):
>>> : assert(!PeerCompletedAddressValidation())
>>> : if (has handshake keys):
>>> : return (now() + duration), Handshake
>>> : else:
>>> : return (now() + duration), Initial
>>> : <..>
>>> : return pto_timeout, pto_space
>>>
>>> But PeerCompletedAddressValidation is always true for the server.
>>> The above anti-deadlock measure seems to only make sense for a client
>>> when it has no new data to send, but forced to send something to rise
>>> an anti-amplification limit for the server. This thought is supported
>>> by commentaries in places of GetPtoTimeAndSpace use.
>>>
>>> Removing the condition from ngx_quic_pto() makes possible to unify
>>> the function to use it for both regular PTO and path validation.
>>>
>>> Next is to make retransmits similar to a new connection establishment.
>>> Per RFC 9000, 8.2.1:
>>> : An endpoint SHOULD NOT probe a new path with packets containing a
>>> : PATH_CHALLENGE frame more frequently than it would send an Initial packet.
>>>
>>> I think we can improve path validation to use a separate backoff,
>>> path->tries can be used to base a backoff upon it.
>>>
>>> Since PATH_CHALLENGE are resent separately from the regular probe/lost
>>> detection mechanism, this needs to be moved out from ngx_quic_pto().
>>>
>>> This makes the following series based on your patch.
>>> We could set an overall maximum waiting time of 3 * PTO and test it
>>> in pv handler in addition to the check for NGX_QUIC_PATH_RETRIES.
>>
>> Jftr, discussed all of the above in person. Agreed to implement that.
>>
>>> [..]
>>> # HG changeset patch
>>> # User Sergey Kandaurov <pluknet@nginx.com>
>>> # Date 1682338151 -14400
>>> # Mon Apr 24 16:09:11 2023 +0400
>>> # Branch quic
>>> # Node ID 808fe808e276496a9b026690c141201720744ab3
>>> # Parent f49aba6e3fb54843d3e3bd5df26dbb45f5d3d687
>>> QUIC: separated path validation retransmit backoff.
>>>
>>> Path validation packets containing PATH_CHALLENGE frames are sent separately
>>> from regular frame queue, because of the need to use a decicated path and pad
>>> the packets. The packets are sent periodically, separately from the regular
>>> probe/lost detection mechanism. A path validation packet is resent up to 3
>>> times, each time after PTO expiration, with increasing per-path PTO backoff.
>>>
>>> diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c
>>> --- a/src/event/quic/ngx_event_quic_ack.c
>>> +++ b/src/event/quic/ngx_event_quic_ack.c
>>> @@ -736,7 +736,8 @@ ngx_quic_set_lost_timer(ngx_connection_t
>>>
>>> q = ngx_queue_last(&ctx->sent);
>>> f = ngx_queue_data(q, ngx_quic_frame_t, queue);
>>> - w = (ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now);
>>> + w = (ngx_msec_int_t) (f->last + (ngx_quic_pto(c, ctx) << qc->pto_count)
>>> + - now);
>>>
>>> if (w < 0) {
>>> w = 0;
>>> @@ -785,10 +786,9 @@ ngx_quic_pto(ngx_connection_t *c, ngx_qu
>>>
>>> duration = qc->avg_rtt;
>>> duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
>>> - duration <<= qc->pto_count;
>>>
>>> if (ctx->level == ssl_encryption_application && c->ssl->handshaked) {
>>> - duration += qc->ctp.max_ack_delay << qc->pto_count;
>>> + duration += qc->ctp.max_ack_delay;
>>> }
>>>
>>> return duration;
>>> @@ -846,7 +846,9 @@ ngx_quic_pto_handler(ngx_event_t *ev)
>>> continue;
>>> }
>>>
>>> - if ((ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now) > 0) {
>>> + if ((ngx_msec_int_t) (f->last + (ngx_quic_pto(c, ctx) << qc->pto_count)
>>> + - now) > 0)
>>> + {
>>> continue;
>>> }
>>>
>>> diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c
>>> --- a/src/event/quic/ngx_event_quic_migration.c
>>> +++ b/src/event/quic/ngx_event_quic_migration.c
>>> @@ -496,6 +496,7 @@ ngx_quic_validate_path(ngx_connection_t
>>> "quic initiated validation of path seq:%uL", path->seqnum);
>>>
>>> path->validating = 1;
>>> + path->tries = 0;
>>>
>>> if (RAND_bytes(path->challenge1, 8) != 1) {
>>> return NGX_ERROR;
>>> @@ -513,7 +514,6 @@ ngx_quic_validate_path(ngx_connection_t
>>> pto = ngx_quic_pto(c, ctx);
>>>
>>> path->expires = ngx_current_msec + pto;
>>> - path->tries = NGX_QUIC_PATH_RETRIES;
>>>
>>> if (!qc->path_validation.timer_set) {
>>> ngx_add_timer(&qc->path_validation, pto);
>>> @@ -578,7 +578,6 @@ ngx_quic_path_validation_handler(ngx_eve
>>> qc = ngx_quic_get_connection(c);
>>>
>>> ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
>>> - pto = ngx_quic_pto(c, ctx);
>>>
>>> next = -1;
>>> now = ngx_current_msec;
>>> @@ -605,7 +604,9 @@ ngx_quic_path_validation_handler(ngx_eve
>>> continue;
>>> }
>>>
>>> - if (--path->tries) {
>>> + if (++path->tries < NGX_QUIC_PATH_RETRIES) {
>>> + pto = ngx_quic_pto(c, ctx) << path->tries;
>>
>> Here we schedule a timer for 2 * PTO or 4 * PTO. Technically, our path
>> validation code allows several paths to be validated at the same time. If that
>> happens, 2 * PTO and 4 * PTO will be too much for the first attempt for the new
>> path, where the timeout is just PTO. As a result, the last path may wait 2x
>> or 4x longer than needed.
>
> Agree it needs to be addressed.
>
> Below is the first glance to set the next available pv timer:
> 1) in ngx_quic_validate_path(), a new path may own a shorter timer
> than already established, especially after several timeouts
> Previously, new path validation could be scheduled late.
> 2) in ngx_quic_handle_path_response_frame(), a validated path
> might left a spurious timer, while nothing more to validate
> or remaining paths have more distant timer
> This one is less severe, just extra work added.
>
> Unlike the two above, pv handler has a more complex
> logic I decided not to touch it.
>

Updated patch, with timers logic moved inside
similar to ngx_quic_set_lost_timer().

# HG changeset patch
# User Sergey Kandaurov <pluknet@nginx.com>
# Date 1683636833 -14400
# Tue May 09 16:53:53 2023 +0400
# Branch quic
# Node ID a40ce69032547110b1a10e953ca55dfc684f131d
# Parent c9a6960c548501b5234ca7f7ff5ae23fad75b023
QUIC: reschedule path validation on path insertion/removal.

Two issues fixed:
- new path validation could be scheduled late
- a validated path could leave a spurious timer

diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c
--- a/src/event/quic/ngx_event_quic_migration.c
+++ b/src/event/quic/ngx_event_quic_migration.c
@@ -16,6 +16,7 @@ static ngx_int_t ngx_quic_validate_path(
ngx_quic_path_t *path);
static ngx_int_t ngx_quic_send_path_challenge(ngx_connection_t *c,
ngx_quic_path_t *path);
+static void ngx_quic_set_path_timer(ngx_connection_t *c);
static ngx_quic_path_t *ngx_quic_get_path(ngx_connection_t *c, ngx_uint_t tag);


@@ -169,6 +170,8 @@ valid:
path->validating = 0;
path->limited = 0;

+ ngx_quic_set_path_timer(c);
+
return NGX_OK;
}

@@ -515,9 +518,7 @@ ngx_quic_validate_path(ngx_connection_t

path->expires = ngx_current_msec + pto;

- if (!qc->path_validation.timer_set) {
- ngx_add_timer(&qc->path_validation, pto);
- }
+ ngx_quic_set_path_timer(c);

return NGX_OK;
}
@@ -563,6 +564,46 @@ ngx_quic_send_path_challenge(ngx_connect
}


+static void
+ngx_quic_set_path_timer(ngx_connection_t *c)
+{
+ ngx_msec_t now;
+ ngx_queue_t *q;
+ ngx_msec_int_t left, next;
+ ngx_quic_path_t *path;
+ ngx_quic_connection_t *qc;
+
+ qc = ngx_quic_get_connection(c);
+
+ now = ngx_current_msec;
+ next = -1;
+
+ for (q = ngx_queue_head(&qc->paths);
+ q != ngx_queue_sentinel(&qc->paths);
+ q = ngx_queue_next(q))
+ {
+ path = ngx_queue_data(q, ngx_quic_path_t, queue);
+
+ if (!path->validating) {
+ continue;
+ }
+
+ left = path->expires - now;
+
+ if (next == -1 || left < next) {
+ next = left;
+ }
+ }
+
+ if (next == -1) {
+ ngx_del_timer(&qc->path_validation);
+
+ } else {
+ ngx_add_timer(&qc->path_validation, next);
+ }
+}
+
+
void
ngx_quic_path_validation_handler(ngx_event_t *ev)
{

--
Sergey Kandaurov
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH 0 of 3] QUIC path MTU discovery

Roman Arutyunyan 1020 March 28, 2023 10:52AM

[PATCH 1 of 3] QUIC: changed path validation timeout

Roman Arutyunyan 191 March 28, 2023 10:52AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Sergey Kandaurov 194 April 24, 2023 08:16AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Roman Arutyunyan 159 May 03, 2023 09:02AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Sergey Kandaurov 137 May 09, 2023 06:12AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Sergey Kandaurov 151 May 09, 2023 09:00AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Sergey Kandaurov 145 May 09, 2023 11:08AM

Re: [PATCH 1 of 3] QUIC: changed path validation timeout

Roman Arutyunyan 159 May 09, 2023 11:30AM

[PATCH 2 of 3] QUIC: allowed ngx_quic_frame_sendto() to return NGX_AGAIN

Roman Arutyunyan 182 March 28, 2023 10:52AM

[PATCH 3 of 3] QUIC: path MTU discovery

Roman Arutyunyan 275 March 28, 2023 11:00AM

Re: [PATCH 3 of 3] QUIC: path MTU discovery

Sergey Kandaurov 182 May 01, 2023 01:00PM

Re: [PATCH 3 of 3] QUIC: path MTU discovery

Maxim Dounin 165 May 01, 2023 04:42PM

Re: [PATCH 3 of 3] QUIC: path MTU discovery

Roman Arutyunyan 167 May 08, 2023 08:16AM

Re: [PATCH 3 of 3] QUIC: path MTU discovery

Sergey Kandaurov 145 May 08, 2023 11:12AM

[PATCH 0 of 4] QUIC path MTU discovery

Roman Arutyunyan 118 July 06, 2023 09:58AM

[PATCH 1 of 4] QUIC: removed path->limited flag

Roman Arutyunyan 129 July 06, 2023 09:58AM

Re: [PATCH 1 of 4] QUIC: removed path->limited flag

Sergey Kandaurov 131 July 28, 2023 11:52AM

[PATCH 2 of 4] QUIC: removed explicit packet padding for certain frames

Roman Arutyunyan 123 July 06, 2023 09:58AM

Re: [PATCH 2 of 4] QUIC: removed explicit packet padding for certain frames

Sergey Kandaurov 131 July 28, 2023 11:52AM

[PATCH 3 of 4] QUIC: allowed ngx_quic_frame_sendto() to return NGX_AGAIN

Roman Arutyunyan 125 July 06, 2023 09:58AM

Re: [PATCH 3 of 4] QUIC: allowed ngx_quic_frame_sendto() to return NGX_AGAIN

Sergey Kandaurov 120 July 28, 2023 11:52AM

[PATCH 4 of 4] QUIC: path MTU discovery

Roman Arutyunyan 133 July 06, 2023 09:58AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Roman Arutyunyan 127 July 07, 2023 04:00AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Sergey Kandaurov 142 July 28, 2023 11:54AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Roman Arutyunyan 131 July 31, 2023 01:36PM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Sergey Kandaurov 165 August 08, 2023 05:50AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Roman Arutyunyan 131 August 10, 2023 06:22AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Sergey Kandaurov 135 August 10, 2023 10:20AM

Re: [PATCH 4 of 4] QUIC: path MTU discovery

Roman Arutyunyan 150 August 14, 2023 09:54AM

Re: [PATCH 0 of 4] QUIC path MTU discovery

Sergey Kandaurov 119 July 28, 2023 11:52AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 154
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready