-
Notifications
You must be signed in to change notification settings - Fork 5k
Unix: fix UDP ReuseAddress with non .NET Core UDP clients #32046
Conversation
.NET Core sets SO_REUSEPORT to enable reusing the address with other sockets. This works when the other sockets also set SO_REUSEPORT. SO_REUSEADDR can also be used for this. When one application uses SO_REUSEADDR and another uses SO_REUSEPORT, the second application will fail to bind. To implement SocketOptionName.ReuseAddress we need to set both options. This enables sharing with applications that set SO_REUSEPORT, SO_REUSEADDR or both.
Fixes https://github.com/dotnet/corefx/issues/32027 |
@@ -1842,7 +1840,15 @@ SystemNative_SetSockOpt(intptr_t socket, int32_t socketOptionLevel, int32_t sock | |||
} | |||
} | |||
|
|||
// An application that sets SO_REUSEPORT/SO_REUSEADDR can share the with another application |
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.
share the .. ?
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.
"endpoint", pushed a commit to fix this.
I want to take another look at this. We may want to not set SO_REUSEPORT for UDP on Linux because that will load balance datagrams. We may still want to set it for TCP. |
I looked a bit further into the finer details. Typical use-cases work as expected: reuse TCP listen port, share UDP multicast. One case behaves a bit special on Linux: UDP sockets with ReuseAddress set will distribute unicast datagrams accross the different sockets. On Windows/BSD, the last socket that binds 'steals' the port. We can avoid this by not setting SO_REUSEPORT (and only SO_REUSEADDR). It would be nicest if Linux can stay close to the Windows semantics. On the other hand, the implementation will make the code a bit messier (special case for UDP on Linux). Maybe the behavior is good enough and we want to wait until someone considers&reports this as an issue. |
That sounds fine to me. |
Thanks, @tmds. Let's leave it as-is for now to avoid unnecessary churn. |
@stephentoub my comment was about adding additional changes to this PR. The PR in its current state has changes which are necessary to fix https://github.com/dotnet/corefx/issues/32027. |
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.
Can you add a test for this (ideally for all of the modes called out)? From the description of the issue being addressed, it seems like it should be feasible to do. Given the subtleties here, it'll be good to verify that, for example, we get consistent behavior across Linux and macOS.
Otherwise, LGTM.
macOS is unhappy with the new test:
|
@dotnet-bot test Linux x64 Release Build please |
Due to BSD vs Linux differences. I've updated the test. |
@@ -490,6 +490,45 @@ public void ExclusiveAddressUseTcp() | |||
} | |||
} | |||
|
|||
[DllImport("libc", SetLastError = true)] | |||
private unsafe static extern int setsockopt(int socket, int level, int option_name, void* option_value, uint option_len); |
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.
Other places we add Unix-specific DllImports like this to tests, we separated them out into their own, e.g., SocketOptionNameTest.Unix.cs partial file. IIRC, it was because of issues they'd otherwise cause on .NET Native when running tests, though I don't remember for sure. Regardless, can you move this one to be consistent?
|
It looks like the SocketOptionNameTest.Unix.cs isn't included in the project. I thought it might be because I had to update the csproj Configurations with separate Unix and Windows, but it still fails when I build it. I don't know what I'm missing. |
@dotnet-bot test NETFX x86 Release Build please |
@dotnet-bot test UWP NETNative x86 Release Build please |
CI approves. This should be good to merge. |
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.
Thanks.
…efx#32046) * Unix: fix UDP ReuseAddress with non .NET Core UDP clients .NET Core sets SO_REUSEPORT to enable reusing the address with other sockets. This works when the other sockets also set SO_REUSEPORT. SO_REUSEADDR can also be used for this. When one application uses SO_REUSEADDR and another uses SO_REUSEPORT, the second application will fail to bind. To implement SocketOptionName.ReuseAddress we need to set both options. This enables sharing with applications that set SO_REUSEPORT, SO_REUSEADDR or both. * Fix comment * wording: share -> reuse * Add test * Fix test on mac * Move DllImport to separate file * Add separate csproj Configurations for Windows and Unix * Add Windows and Unix to Configurations.props Commit migrated from dotnet/corefx@0ec9c9d
Fixes #32027
.NET Core sets SO_REUSEPORT to enable reusing the address with other
sockets. This works when the other sockets also set SO_REUSEPORT.
SO_REUSEADDR can also be used for this. When one application uses
SO_REUSEADDR and another uses SO_REUSEPORT, the second application
will fail to bind.
To implement SocketOptionName.ReuseAddress we need to set both options.
This enables sharing with applications that set SO_REUSEPORT,
SO_REUSEADDR or both.