-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
quic: move ack_delay_exponent handling out of frame parsing
The ACK Delay field of ACK frames contains a duration. The field contains an integer which is multiplied by two to the power of the sender's ack_delay_exponent transport parameter to arrive at the delay in microseconds. Change the frame parsing and encoding layer to operate on the unscaled field value, rather than passing the ack_delay_exponent and a duration. This better expresses the fact that we may parse an ACK frame without knowing the ack_delay_exponent, if the ACK is received before transport parameters. For golang/go#58547 Change-Id: Ic26256761961ce89aea0618b849e5661b0502b12 Reviewed-on: https://go-review.googlesource.com/c/net/+/504855 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Damien Neil <dneil@google.com> Reviewed-by: Jonathan Amsterdam <jba@google.com>
- Loading branch information
Showing
6 changed files
with
121 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2023 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build go1.21 | ||
|
||
package quic | ||
|
||
import ( | ||
"math" | ||
"time" | ||
) | ||
|
||
// An unscaledAckDelay is an ACK Delay field value from an ACK packet, | ||
// without the ack_delay_exponent scaling applied. | ||
type unscaledAckDelay int64 | ||
|
||
func unscaledAckDelayFromDuration(d time.Duration, ackDelayExponent uint8) unscaledAckDelay { | ||
return unscaledAckDelay(d.Microseconds() >> ackDelayExponent) | ||
} | ||
|
||
func (d unscaledAckDelay) Duration(ackDelayExponent uint8) time.Duration { | ||
if int64(d) > (math.MaxInt64>>ackDelayExponent)/int64(time.Microsecond) { | ||
// If scaling the delay would overflow, ignore the delay. | ||
return 0 | ||
} | ||
return time.Duration(d<<ackDelayExponent) * time.Microsecond | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright 2023 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build go1.21 | ||
|
||
package quic | ||
|
||
import ( | ||
"math" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestAckDelayFromDuration(t *testing.T) { | ||
for _, test := range []struct { | ||
d time.Duration | ||
ackDelayExponent uint8 | ||
want unscaledAckDelay | ||
}{{ | ||
d: 8 * time.Microsecond, | ||
ackDelayExponent: 3, | ||
want: 1, | ||
}, { | ||
d: 1 * time.Nanosecond, | ||
ackDelayExponent: 3, | ||
want: 0, // rounds to zero | ||
}, { | ||
d: 3 * (1 << 20) * time.Microsecond, | ||
ackDelayExponent: 20, | ||
want: 3, | ||
}} { | ||
got := unscaledAckDelayFromDuration(test.d, test.ackDelayExponent) | ||
if got != test.want { | ||
t.Errorf("unscaledAckDelayFromDuration(%v, %v) = %v, want %v", | ||
test.d, test.ackDelayExponent, got, test.want) | ||
} | ||
} | ||
} | ||
|
||
func TestAckDelayToDuration(t *testing.T) { | ||
for _, test := range []struct { | ||
d unscaledAckDelay | ||
ackDelayExponent uint8 | ||
want time.Duration | ||
}{{ | ||
d: 1, | ||
ackDelayExponent: 3, | ||
want: 8 * time.Microsecond, | ||
}, { | ||
d: 0, | ||
ackDelayExponent: 3, | ||
want: 0, | ||
}, { | ||
d: 3, | ||
ackDelayExponent: 20, | ||
want: 3 * (1 << 20) * time.Microsecond, | ||
}, { | ||
d: math.MaxInt64 / 1000, | ||
ackDelayExponent: 0, | ||
want: (math.MaxInt64 / 1000) * time.Microsecond, | ||
}, { | ||
d: (math.MaxInt64 / 1000) + 1, | ||
ackDelayExponent: 0, | ||
want: 0, // return 0 on overflow | ||
}, { | ||
d: math.MaxInt64 / 1000 / 8, | ||
ackDelayExponent: 3, | ||
want: (math.MaxInt64 / 1000 / 8) * 8 * time.Microsecond, | ||
}, { | ||
d: (math.MaxInt64 / 1000 / 8) + 1, | ||
ackDelayExponent: 3, | ||
want: 0, // return 0 on overflow | ||
}} { | ||
got := test.d.Duration(test.ackDelayExponent) | ||
if got != test.want { | ||
t.Errorf("unscaledAckDelay(%v).Duration(%v) = %v, want %v", | ||
test.d, test.ackDelayExponent, int64(got), int64(test.want)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters