-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
quic: prioritise listen connections for reuse #2262
Conversation
Does this PR fix #1534? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in the following scenario?
- We dial a QUIC connection to a remote node. We don't have any existing connections, so we listen on :0, and get assinged
:port1
. - Now we start a listener on
0.0.0.0:port2
.
With this PR, we'd ignore port2
, and just reuse the connection that's listening on port1
, right?
The :port1 will go in to
The :port2 will go in to
No, we will prioritise :port2 because it is in the I added a test case for this. |
I think so. comments below
Yes this is exactly what i've implemented. The fallback map is
In the original description This is fixed by this PR. First we check Update: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried this out using the following code: https://gist.github.com/marten-seemann/c221eed357fc14e15f26d066380c5c44
It seems to work! Just left some comments regarding naming, and a question regarding listening on port 0.
p2p/transport/quicreuse/reuse.go
Outdated
|
||
// reuse the fallback connection if we've dialed out from this port already | ||
if laddr.IP.IsUnspecified() { | ||
if _, ok := r.globalFallback[laddr.Port]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to handle listening on port 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. An entry in the map(listeners or dialers) will never have port 0 because we add the finally assigned listener port to the map and not 0. So if a listen call happens with port 0 and there is an entry in globalDialers map, we will not find a match and then net.ListenUDP will give use a new port which is not in the globalDialers map.
Do you think this makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if a listen call happens with port 0 and there is an entry in globalDialers map, we will not find a match and then net.ListenUDP will give use a new port which is not in the globalDialers map.
That's what I meant. If the port is 0, the user doesn't care which port is assigned. So we might as well reuse a connection that we used before, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, that's a nice idea. will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed this. updated the test TestReuseConnectionWhenDialBeforeListen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic LGTM. Just suggesting to add another comment, to make the code easier to understand when we come back to it later.
Co-authored-by: Marten Seemann <[email protected]>
Currently there is a race in kubo between the first dial made by a node on startup and starting to listen on a quic address.
If the dial happens first, this places an entry in the
reuse.global
map. This entry will stay in the map till we get a period of 30 seconds where we make no new dials. In my experiments this entry is removed after 15 minutes of starting the node. This dial happens before listening 5-10% of the times on my machine.The impact of this is on holepunching. While this entry is in the map, the function
reuse.Dial
inp2p/transport/quicreuse/reuse.go
can return either this connection that we dialed out of but are not listening on, or it can return the correct connection the one on which we are listening.