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

connection: Add TCP_FASTOPEN listener option #2793

Merged
merged 39 commits into from
Apr 18, 2018
Merged

Conversation

bmetzdorf
Copy link
Contributor

@bmetzdorf bmetzdorf commented Mar 13, 2018

connection: Add TCP_FASTOPEN listener option

This allows accepting TCP_FASTOPEN based connections. Works on both Linux and OSX.

Feedback on this is very welcome. It was tested manually on Linux and OSX.

API Changes: envoyproxy/data-plane-api#539

Signed-off-by: Bjoern Metzdorf bmetzdorf@apple.com
Risk Level: Low

@ggreenway
Copy link
Contributor

@dnoe This is related to the other socket-option work you're looking at.

Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
@mattklein123
Copy link
Member

Per new release note policy please add a release note with any applicable feature docs to https://github.com/envoyproxy/data-plane-api/blob/master/docs/root/intro/version_history.rst. Thank you!

@bmetzdorf
Copy link
Contributor Author

@mattklein123 I've added a note in envoyproxy/data-plane-api#539

@alyssawilk
Copy link
Contributor

@bmetzdorf #2734 is in - are you up for pulling and merging?

@bmetzdorf
Copy link
Contributor Author

@alyssawilk yep! Will do in the next couple of days!

@bmetzdorf
Copy link
Contributor Author

@alyssawilk I think I need to wait for #2719 to be merged.

Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
@@ -32,8 +32,25 @@ bool SocketOptionImpl::setOption(Socket& socket, Socket::SocketState state) cons
return false;
}
}
}
} else if (state == Socket::SocketState::Listening) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please wrap the IP_TRANSPARENT option setting above into if (state != Socket::SocketState::Listening) { ... }.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch!

Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
@ggreenway ggreenway changed the title Work in progress: connection: Add TCP_FASTOPEN listener option connection: Add TCP_FASTOPEN listener option Apr 3, 2018
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>

// Add the options to the socket_ so that SocketState::Listening options can be
// set in the worker after listen()/evconnlistener_new() is called.
socket_->addOption(option);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does adding these options here break anything else?

@ggreenway ggreenway removed their assignment Apr 3, 2018
@ggreenway
Copy link
Contributor

I wrote a lot of this code, so removing myself as reviewer

@bmetzdorf
Copy link
Contributor Author

I've tested this latest commit f2db8640b2e576a4c978f461f936cd6dfeaf43cf on both macOS and Linux successfully.

macOS:
tcp_fast_open_queue_length: 0 == TFO does not work
tcp_fast_open_queue_length: 1 == TFO does work
tcp_fast_open_queue_length: 2 == "Invalid argument"

Linux:
tcp_fast_open_queue_length: 0 == TFO does not work
tcp_fast_open_queue_length: 512 == TFO does work

Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
@@ -31,7 +31,11 @@ class Socket {
*/
virtual void close() PURE;

enum class SocketState { PreBind, PostBind };
enum class SocketState {
PreBind, // after socket creation but before binding the socket to a port
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest moving these to the line previous, e.g.

// Socket options are applied after socket creation but before...
Prebind,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

This looks great, just a few more comments.

#ifdef TCP_FASTOPEN
#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName(TCP_FASTOPEN)
#else
#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName()
Copy link
Member

Choose a reason for hiding this comment

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

Have you tried manually forcing this option and seeing what happens to the tests? In my experience, this is a useful step.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@htuch Do you mean just enforce TCP_FASTOPEN on all listeners by default and then run the tests?

Copy link
Member

Choose a reason for hiding this comment

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

I mean as an experiment in your local client, change that #ifdef line to #if 0 and see if bazel test //test/... passes.


#include "server/configuration_impl.h"

#ifdef TCP_FASTOPEN
Copy link
Member

Choose a reason for hiding this comment

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

I think this can live in socket_option_impl.h alongside the others.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

std::shared_ptr<MockSocketOption> option = std::make_shared<MockSocketOption>();
socket.addOption(option);
EXPECT_CALL(*option, setOption(_, Socket::SocketState::Listening)).WillOnce(Return(false));
EXPECT_THROW(TestListenerImpl(dispatcher, socket, listener_callbacks, true, false),
Copy link
Member

Choose a reason for hiding this comment

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

Could make this EXPECT_THROW_WITH_MESSAGE to get better precision on why we see the exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'm working on this one.

TEST_F(SocketOptionImplTest, SetOptionFreebindPostBind) {
SocketOptionImpl socket_option{{}, true};
EXPECT_TRUE(socket_option.setOption(socket_, Socket::SocketState::PostBind));
testSetSocketOptionSuccess(socket_option, IPPROTO_IP, ENVOY_SOCKET_IP_FREEBIND, 0,
Copy link
Member

Choose a reason for hiding this comment

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

Nice cleanup!

Api::MockOsSysCalls os_sys_calls_;
TestThreadsafeSingletonInjector<Api::OsSysCallsImpl> os_calls{&os_sys_calls_};

void testSetSocketOptionSuccess(ListenerSocketOptionImpl& socket_option, int socket_level,
Copy link
Member

Choose a reason for hiding this comment

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

Could this subclass SocketOptionImplTest and inherit this method?

Copy link
Member

Choose a reason for hiding this comment

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

@bmetzdorf can you give me a quick yes/no on the various feedback? Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'm working on this one.

bmetzdorf and others added 5 commits April 16, 2018 12:59
Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
Signed-off-by: Greg Greenway <ggreenway@apple.com>
#ifdef TCP_FASTOPEN
#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName(TCP_FASTOPEN)
#else
#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@htuch Do you mean just enforce TCP_FASTOPEN on all listeners by default and then run the tests?

ENVOY_LOG(debug, "Successfully set socket option TCP_FASTOPEN to {}", tfo_value);
}
} else {
ENVOY_LOG(warn, "Unsupported socket option TCP_FASTOPEN");
Copy link
Member

Choose a reason for hiding this comment

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

This case is missing coverage.

Signed-off-by: Bjoern Metzdorf <bmetzdorf@apple.com>
@bmetzdorf
Copy link
Contributor Author

@htuch Please let me know if ListenerSocketOptionImplTest is now inheriting the way you envisioned.

namespace Network {
namespace {

class SocketOptionTestHarness : public testing::Test {
Copy link
Member

Choose a reason for hiding this comment

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

Yep, this looks good. As a nit, I would probably call it SocketOptionTestBase or SocketOptionTest.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

Thanks @bmetzdorf. Merging to unblock #3042, @bmetzdorf has signed up to address remaining minor feedback in a followup PR.

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.

6 participants