Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ minor_behavior_changes:
change: |
Add more conversion in the proxy status utility. It can be disabled by the runtime guard
``envoy.reloadable_features.proxy_status_mapping_more_core_response_flags``.
- area: http3
change: |
Use GRO (Generic Receive Offload) for reading packets from a UDP socket. See
https://www.kernel.org/doc/html/next/networking/segmentation-offloads.html for a description of
GRO. This behavior change can be reverted by setting
``envoy.reloadable_features.prefer_udp_gro`` to ``false``.

bug_fixes:
# *Changes expected to improve the state of the world and are unlikely to have negative effects*
Expand Down
1 change: 0 additions & 1 deletion source/common/network/utility.cc
Comment thread
abeyad marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,6 @@ Api::IoCallUint64Result Utility::readFromSocket(IoHandle& handle,
UdpPacketProcessor& udp_packet_processor,
MonotonicTime receive_time, bool use_gro,
uint32_t* packets_dropped) {

Comment thread
alyssawilk marked this conversation as resolved.
if (use_gro) {
Buffer::InstancePtr buffer = std::make_unique<Buffer::OwnedImpl>();
IoHandle::RecvMsgOutput output(1, packets_dropped);
Expand Down
2 changes: 2 additions & 0 deletions source/common/quic/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ envoy_cc_library(
"//envoy/event:dispatcher_interface",
"//source/common/network:socket_option_factory_lib",
"//source/common/network:udp_packet_writer_handler_lib",
"//source/common/runtime:runtime_lib",
"@com_github_google_quiche//:quic_core_connection_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
Expand Down Expand Up @@ -435,6 +436,7 @@ envoy_cc_library(
"//source/common/network:socket_option_factory_lib",
"//source/common/protobuf:utility_lib",
"//source/common/quic:quic_io_handle_wrapper_lib",
"//source/common/runtime:runtime_lib",
"@com_github_google_quiche//:quic_core_config_lib",
"@com_github_google_quiche//:quic_core_http_header_list_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
Expand Down
5 changes: 4 additions & 1 deletion source/common/quic/envoy_quic_client_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "source/common/network/socket_option_factory.h"
#include "source/common/network/udp_packet_writer_handler_impl.h"
#include "source/common/quic/envoy_quic_utils.h"
#include "source/common/runtime/runtime_features.h"

namespace Envoy {
namespace Quic {
Expand Down Expand Up @@ -229,7 +230,9 @@ void EnvoyQuicClientConnection::onFileEvent(uint32_t events,
if (connected() && (events & Event::FileReadyType::Read)) {
Api::IoErrorPtr err = Network::Utility::readPacketsFromSocket(
connection_socket.ioHandle(), *connection_socket.connectionInfoProvider().localAddress(),
*this, dispatcher_.timeSource(), /*prefer_gro=*/false, packets_dropped_);
*this, dispatcher_.timeSource(),
Runtime::runtimeFeatureEnabled("envoy.reloadable_features.prefer_udp_gro"),
Comment thread
abeyad marked this conversation as resolved.
Outdated
packets_dropped_);
if (err == nullptr) {
// In the case where the path validation fails, the probing socket will be closed and its IO
// events are no longer interesting.
Expand Down
6 changes: 6 additions & 0 deletions source/common/quic/envoy_quic_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#include "envoy/common/platform.h"
#include "envoy/config/core/v3/base.pb.h"

#include "source/common/api/os_sys_calls_impl.h"
#include "source/common/http/utility.h"
#include "source/common/network/socket_option_factory.h"
#include "source/common/network/utility.h"
#include "source/common/protobuf/utility.h"
#include "source/common/runtime/runtime_features.h"

namespace Envoy {
namespace Quic {
Expand Down Expand Up @@ -149,6 +151,10 @@ createConnectionSocket(const Network::Address::InstanceConstSharedPtr& peer_addr
}
connection_socket->addOptions(Network::SocketOptionFactory::buildIpPacketInfoOptions());
connection_socket->addOptions(Network::SocketOptionFactory::buildRxQueueOverFlowOptions());
if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.prefer_udp_gro") &&
Comment thread
abeyad marked this conversation as resolved.
Outdated
Api::OsSysCallsSingleton::get().supportsUdpGro()) {
connection_socket->addOptions(Network::SocketOptionFactory::buildUdpGroOptions());
}
if (options != nullptr) {
connection_socket->addOptions(options);
}
Expand Down
1 change: 1 addition & 0 deletions source/common/runtime/runtime_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ RUNTIME_GUARD(envoy_reloadable_features_oauth_make_token_cookie_httponly);
RUNTIME_GUARD(envoy_reloadable_features_oauth_use_standard_max_age_value);
RUNTIME_GUARD(envoy_reloadable_features_oauth_use_url_encoding);
RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout);
RUNTIME_GUARD(envoy_reloadable_features_prefer_udp_gro);
RUNTIME_GUARD(envoy_reloadable_features_proxy_status_mapping_more_core_response_flags);
RUNTIME_GUARD(envoy_reloadable_features_proxy_status_upstream_request_timeout);
RUNTIME_GUARD(envoy_reloadable_features_quic_fix_filter_manager_uaf);
Expand Down
2 changes: 2 additions & 0 deletions test/common/quic/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ envoy_cc_test(
deps = [
":test_utils_lib",
"//envoy/stats:stats_macros",
"//source/common/api:os_sys_calls_lib",
"//source/common/quic:client_codec_lib",
"//source/common/quic:envoy_quic_alarm_factory_lib",
"//source/common/quic:envoy_quic_client_connection_lib",
Expand All @@ -203,6 +204,7 @@ envoy_cc_test(
"//test/mocks/stats:stats_mocks",
"//test/test_common:logging_lib",
"//test/test_common:simulated_time_system_lib",
"//test/test_common:threadsafe_singleton_injector_lib",
"@com_github_google_quiche//:quic_test_tools_session_peer_lib",
],
)
Expand Down
45 changes: 45 additions & 0 deletions test/common/quic/envoy_quic_client_session_test.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "envoy/stats/stats_macros.h"

#include "source/common/api/os_sys_calls_impl.h"
#include "source/common/network/transport_socket_options_impl.h"
#include "source/common/quic/client_codec_impl.h"
#include "source/common/quic/envoy_quic_alarm_factory.h"
Expand All @@ -18,6 +19,7 @@
#include "test/test_common/logging.h"
#include "test/test_common/network_utility.h"
#include "test/test_common/simulated_time_system.h"
#include "test/test_common/threadsafe_singleton_injector.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
Expand Down Expand Up @@ -472,5 +474,48 @@ TEST_P(EnvoyQuicClientSessionTest, StatelessResetOnProbingSocket) {
EXPECT_EQ(self_addr_->asString(), quic_connection_->self_address().ToString());
}

class MockOsSysCallsImpl : public Api::OsSysCallsImpl {
public:
MOCK_METHOD(Api::SysCallSizeResult, recvmsg, (os_fd_t socket, msghdr* msg, int flags),
(override));
MOCK_METHOD(Api::SysCallIntResult, recvmmsg,
(os_fd_t socket, struct mmsghdr* msgvec, unsigned int vlen, int flags,
struct timespec* timeout),
(override));
};
Comment thread
abeyad marked this conversation as resolved.

// Ensures that the Network::Utility::readFromSocket function uses GRO instead of `recvmmsg`.
// Only Linux platforms support GRO.
#if defined(__linux__)
Comment thread
abeyad marked this conversation as resolved.
Outdated
TEST_P(EnvoyQuicClientSessionTest, UsesUdpGro) {
MockOsSysCallsImpl os_sys_calls_;
TestThreadsafeSingletonInjector<Api::OsSysCallsImpl> singleton_injector_{&os_sys_calls_};

// Have to connect the QUIC session, so that the socket is set up so we can do I/O on it.
envoy_quic_session_.connect();

std::string write_data = "abc";
Buffer::RawSlice slice;
slice.mem_ = write_data.data();
slice.len_ = write_data.length();

// GRO uses `recvmsg`, not `recvmmsg`.
EXPECT_CALL(os_sys_calls_, recvmmsg(_, _, _, _, _)).Times(0);
EXPECT_CALL(os_sys_calls_, recvmsg(_, _, _))
.WillOnce(
Invoke([&](os_fd_t /*socket*/, msghdr* /*msg*/, int /*flags*/) -> Api::SysCallSizeResult {
dispatcher_->exit();
// Return an error so IoSocketHandleImpl::recvmsg() exits early, instead of trying to
// use the msghdr that would normally have been populated by recvmsg but is not
// populated by this mock.
return {-1, SOCKET_ERROR_AGAIN};
}));

peer_socket_->ioHandle().sendmsg(&slice, 1, 0, peer_addr_->ip(), *self_addr_);

dispatcher_->run(Event::Dispatcher::RunType::RunUntilExit);
}
#endif

} // namespace Quic
} // namespace Envoy