Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce an API that lets the user get the current datagram size #4294

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nanokatze
Copy link
Contributor

@nanokatze nanokatze commented Jan 31, 2024

@nanokatze
Copy link
Contributor Author

nanokatze commented Jan 31, 2024

I'm having trouble generating mocks using the latest https://github.com/uber-go/mock: running
mockgen -typed -build_flags=-tags=gomock -package quic -self_package github.com/quic-go/quic-go -destination mock_packer_test.go github.com/quic-go/quic-go Packer as it says in the comment on top of packet_packer_test.go, if I look at the diff, some types get a Mock prefix they previously didn't, e.g.:

-// PackerAppendPacketCall wrap *gomock.Call
-type PackerAppendPacketCall struct {
+// MockPackerAppendPacketCall wrap *gomock.Call
+type MockPackerAppendPacketCall struct {
 	*gomock.Call
 }

which breaks lots of other code. Is this expected, and the other code using current names should be adjusted to use new names with Mock prefix or am I invoking it incorrectly?

@marten-seemann
Copy link
Member

You should only need to run go generate ./....

Copy link

codecov bot commented Jan 31, 2024

Codecov Report

Attention: 15 lines in your changes are missing coverage. Please review.

Comparison is base (0582e93) 84.17% compared to head (48bc3df) 84.01%.

❗ Current head 48bc3df differs from pull request most recent head 3d7ebd4. Consider uploading reports for the commit 3d7ebd4 to get more accurate results

Files Patch % Lines
packet_packer.go 0.00% 9 Missing ⚠️
connection.go 57.14% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4294      +/-   ##
==========================================
- Coverage   84.17%   84.01%   -0.15%     
==========================================
  Files         149      150       +1     
  Lines       15397    15450      +53     
==========================================
+ Hits        12959    12980      +21     
- Misses       1939     1967      +28     
- Partials      499      503       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

maxDatagramDataSize := (&wire.DatagramFrame{DataLenPresent: true}).MaxDataLen(maxDatagramFrameSize, s.version)

s.connStateMutex.Lock()
s.connState.MaxDatagramSize = int(maxDatagramDataSize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we consider using atomic uint32?

Copy link
Contributor Author

@nanokatze nanokatze Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced focusing on this is worthwhile right now. There are more important things to address first (which would likely affect whatever performance impact of updateMaxDatagramDataSize has), and if connStateMutex contention turns out to be a problem in the end, I think we might want to revisit how all of ConnectionState is accessed, not just this field.

connection.go Outdated
@@ -527,6 +527,8 @@ runLoop:
default:
}

s.updateMaxDatagramDataSize()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be smarter than running this once per runLoop iteration? This is the hot path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean this should be moved to the end of runLoop body? I wasn't sure under which conditions end of the runLoop body is or isn't reachable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. runLoop iterates once per (batch of) packets received and sent. Which is a lot on an active QUIC connection.

The available space in the packet however only changes under 2 conditions (I think):

  1. When we update the connection ID.
  2. When we discover a new MTU.

Copy link
Contributor Author

@nanokatze nanokatze Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's another reason: encoded packet number length increases, which IIUC grows with RTT and how fast we send packets (as in, packets per unit of time.)

I also just realized I misread and misunderstood your initial comment, oops.

The simplest way I can think of would be just to rate limit updateMaxDatagramSize. A more "precise" solution I can think of would be to run it in response to the 3 events that can change the available space: connection ID changed, PMTU changed, packet number length changed. Packet number length can change after every packet we send and on every ACK we receive. This reasoning is in fact why I initially went with running updateMaxDatagramSize every runLoop, as it runs in response to all of these events. In any case, do you think just rate limiting so that updateMaxDatagramSize runs once in a while, e.g. every 10 ms or every N iterations of runLoop, would be good enough solution, or should we instead try to run updateMaxDatagramSize in response to 3 events listed above? If we go with "every once in a while" solution, the users could be advised to underutilize the available space by 1-2 bytes to allow for growth if they start sending datagrams after a period of inactivity. We could also trigger updateMaxDatagramSize in response to discarding datagrams when sending.

//
// MaxDatagramSize is zero if datagrams are not supported on this
// connection.
MaxDatagramSize int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint16?

Copy link
Contributor Author

@nanokatze nanokatze Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind making it uint16, but I don't see what improvement this would have. At worst I believe this would, in some cases, cause the users to perform additional conversion in their code, as dealing with sizes of things that fit in core in Go conventionally is done in ints.

@nanokatze nanokatze force-pushed the maxdatagramsize branch 2 times, most recently from 30dfde0 to c037a37 Compare February 1, 2024 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants