-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
BIO_dgram support for BIO_sendmmsg/BIO_recvmmsg #18270
Conversation
The errno packing thing is a bit goofy. Could just add an WSASendMsg requires Vista so needs |
It turns out WSASendMsg and WSARecvMsg, which were introduced in Vista, are not exported as normal symbols by Windows. Instead, you have to use them by obtaining function pointers to them, by creating a socket and calling ioctl on it. What. In any case, this does have the advantage that we probe for this functionality at runtime and will fall back on platforms without it (XP, etc.). When a datagram is sent from the local machine, Windows doesn't provide source/destination information in the control message received from WSARecvMsg even if IP_PKTINFO is enabled. Instead, Control.len is just set to 0 when WSARecvMsg returns. The API as documented in BIO_sendmmsg(3) has been updated to reflect this OS-specific quirk. In this case we zero the output BIO_ADDR. BIO_DONTWAIT was dropped due to lack of Windows support. |
@mattcaswell I think this is ready for review now. |
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.
Great work!
test/bio_dgram_test.c
Outdated
|
||
/* First effort should fail due to missing destination address */ | ||
ret = BIO_sendmmsg(b1, tx_msg, sizeof(BIO_MSG), 1, 0); | ||
if (!TEST_int_le((int)ret, -32)) |
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.
Should you use BIO_IS_ERRNO()?
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.
0x5d8ef03273C8274A1588BAccDC6A13e52aE9Bda4
crypto/bio/bss_dgram.c
Outdated
# else | ||
# define M_METHOD M_METHOD_NONE | ||
# endif | ||
#endif |
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.
Not sure I'm too keen on the result preprocessing condition salad... We have done things like this differently before, see for example crypto/threads_*.c
I'm not going to be very pushy on this, though...
Updated. |
ping for second review |
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 think this functionality justifies a mention in CHANGES.md
include/internal/e_os.h
Outdated
@@ -96,7 +96,7 @@ | |||
* might be possible to achieve the goal by /DELAYLOAD-ing .DLLs | |||
* and check for current OS version instead. | |||
*/ | |||
# define _WIN32_WINNT 0x0501 | |||
# define _WIN32_WINNT 0x0600 |
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.
This is a breaking change. Or at least potentially it is. It explicitly drops support for Windows XP and Windows Server 2003. I'm not aware of anyone actually building OpenSSL 3.x on those platforms, so I would not be surprised if we're broken there anyway - but this explicit dropping of support is not to be taken lightly. It would require an OTC decision IMO.
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.
My understanding is that increasing _WIN32_WINNT
allows us to use newer features, but it does not automatically break compatibility. The availability of WSARecvMsg is probed at runtime and there is a fallback if it is not available.
By bumping this there is a risk we accidentially start depending on APIs not supported on XP. I guess maybe we should support a build with version 0x0501, maybe in CI.
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.
My code as stands detects availability of WSARecvMsg-related definitions by whether WSAID_WSARECVMSG is defined. So we could make _WIN32_WINNT configurable and the code would automatically use the best function available, whether it's set to 0x0501 or 0x0600. We could discuss what we want to do about evolving _WIN32_WINNT, though it feels like a separate discussion.
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.
we could make _WIN32_WINNT configurable
I think it should already be configurable, i.e. you can pass -D_WIN32_WINNT=...
at configure time. Does your code require _WIN32_WINNT to be 0x0600 before it will work?
The change here changes the default value for _WIN32_WINNT
which I don't think we can do without some agreement that it is ok to do so.
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.
As things stand, if we leave _WIN32_WINNT as 0x0501 by default, the WSARecvMsg code is going to be a dead code path. Do we really want to ship code that will never be used unless people compile OpenSSL in an undocumented way?
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 suppose we should document it in the NOTES.windows then? And possibly also change the default to 0x0600 if OMC agrees so (supposedly the override with 0x0501 should be kept working).
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 raised this at the OMC meeting today, and it led to this proposal:
So, currently, the API isn't required to try and send multiple messages. Meaning an implementation that always returns 1 is permissible. My thinking here is that callers need to handle the case where BIO_sendmmsg doesn't send all messages and call it again anyway. This is consistent with the semantics for sendmmsg(2):
Based on this, I'm thinking it might actually be better to remove the sendmmsg emulation loop from the sendmsg case, so that it's similar to the sendto case. So the options are:
I am leaning towards the second option, which would have me remove the loop for the sendmsg(2) case. Thoughts? |
I'd be ok with the second option. As you say the caller still has to be able to handle the case when less than the number of requested messages is sent anyway so it doesn't add much for the BIO to emulate it. |
Assorted updates. Now the sendmsg cases etc. send one message. Repeated sendmmsg calls have also been removed. |
CI is relevant |
return num_done > 0 ? num_done : -1; | ||
} | ||
} | ||
if (num_msg > BIO_MAX_MSGS_PER_CALL) |
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.
Should the BIO_MAX_MSGS_PER_CALL be a public define so the callers won't needlessly attempt to batch more messages? And document that BIO_MAX_MSGS_PER_CALL is a recommended limit on the BIO_sendmmsg call.
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 we should make any specific promises about the behaviour of this API in terms of the number of messages it handles at this time. There can be other implementations like BIO_dgram_pair and third party implementations which can do what they want.
Maybe a BIO_ctrl to query a suggested batching factor would be something worth considering, rather than a constant.
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.
Maybe a BIO_ctrl to query a suggested batching factor would be something worth considering, rather than a constant.
Yep, that seems to me as something very useful for callers.
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'd be a little wary about specifically documenting this as a "recommended" batching factor -- there are a lot of topics that influence the best batching factor and depending on the NIC and network hardware trying to batch too much at once can reduce performance.
I'd rather see this documented as a limit or cap on the batching factor achievable, ideally with a note that the optimal batching factor will be highly context dependent.
OSX failure is going to be annoying to figure out, but thinking about it. |
… BIO_dgram support for BIO_sendmmsg/BIO_recvmmsg
Updated and rebased, now that the API is merged. Also addressed (I believe) all outstanding comments. Unsure what's going on with doc-nits. This PR doesn't change the file it's complaining about. |
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.
Subject to the few nits being fixed.
I've also asked a question about the test case not indicating a reason for failure but I don't think it's a blocker.
Updated. |
Updated. |
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.
Approved. @paulidale - still 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.
Still good.
This pull request is ready to merge |
Merged, finally! |
Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Paul Dale <[email protected]> (Merged from #18270)
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.
Sorry that this comes so late
|
||
/* See comment above. */ | ||
if (local->s_in.sin_port != 0 | ||
&& data->local_addr.s_in.sin_port != local->s_in.sin_port) { |
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 just discovered, through a build on FreeBSD, that this is untested code. The error I got is this:
crypto/bio/bss_dgram.c:1165:16: error: use of undeclared identifier 'data'
&& data->local_addr.s_in.sin_port != local->s_in.sin_port) {
^
Through this, I see the following declaration sprinkled into all different variants of code in this function:
CMSGHDR_TYPE *cmsg;
bio_dgram_data *data = b->ptr;
Since those are common for all variants, it would probably be safer if they were declared once and for all at the beginning of this function.
Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Paul Dale <[email protected]> (Merged from openssl#18270)
Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Paul Dale <[email protected]> (Merged from openssl#18270)
Flags like
BIO_DONTWAIT
ended up getting dropped because Windows can't support it.There is a new API which must be used to enable local address specification/detection explicitly.
Some previous discussion in #18238.