gfe-relnote: In QuicPacketReader, change the use of QuicSocketUtils to QuicUdpSocketApi. Protected by --gfe2_restart_flag_quic_remove_quic_socket_utils_from_packet_reader. PiperOrigin-RevId: 291783340 Change-Id: I66bf260d8d963a8b362f5ffefd96b7a16f7c6c24
diff --git a/quic/core/quic_packet_reader.cc b/quic/core/quic_packet_reader.cc index 81d2a7d..95cc4e4 100644 --- a/quic/core/quic_packet_reader.cc +++ b/quic/core/quic_packet_reader.cc
@@ -17,10 +17,10 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/impl/quic_socket_utils.h" #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h" #ifndef SO_RXQ_OVFL @@ -29,8 +29,26 @@ namespace quic { -QuicPacketReader::QuicPacketReader() { - Initialize(); +QuicPacketReader::QuicPacketReader() + : read_buffers_(kNumPacketsPerReadMmsgCall), + read_results_(kNumPacketsPerReadMmsgCall) { + if (!remove_quic_socket_utils_from_packet_reader_) { + Initialize(); + return; + } + + QUIC_RESTART_FLAG_COUNT_N(quic_remove_quic_socket_utils_from_packet_reader, 1, + 5); + DCHECK_EQ(read_buffers_.size(), read_results_.size()); + for (size_t i = 0; i < read_results_.size(); ++i) { + read_results_[i].packet_buffer.buffer = read_buffers_[i].packet_buffer; + read_results_[i].packet_buffer.buffer_len = + sizeof(read_buffers_[i].packet_buffer); + + read_results_[i].control_buffer.buffer = read_buffers_[i].control_buffer; + read_results_[i].control_buffer.buffer_len = + sizeof(read_buffers_[i].control_buffer); + } } void QuicPacketReader::Initialize() { @@ -65,13 +83,114 @@ const QuicClock& clock, ProcessPacketInterface* processor, QuicPacketCount* packets_dropped) { + if (!remove_quic_socket_utils_from_packet_reader_) { #if MMSG_MORE_NO_ANDROID - return ReadAndDispatchManyPackets(fd, port, clock, processor, - packets_dropped); + return ReadAndDispatchManyPackets(fd, port, clock, processor, + packets_dropped); #else - return ReadAndDispatchSinglePacket(fd, port, clock, processor, - packets_dropped); + return ReadAndDispatchSinglePacket(fd, port, clock, processor, + packets_dropped); #endif + } + + // Reset all read_results for reuse. + for (size_t i = 0; i < read_results_.size(); ++i) { + read_results_[i].Reset( + /*packet_buffer_length=*/sizeof(read_buffers_[i].packet_buffer)); + } + QuicWallTime wallnow = clock.WallNow(); + size_t packets_read = socket_api_.ReadMultiplePackets( + fd, + BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS, + QuicUdpPacketInfoBit::PEER_ADDRESS, + QuicUdpPacketInfoBit::V4_SELF_IP, + QuicUdpPacketInfoBit::V6_SELF_IP, + QuicUdpPacketInfoBit::RECV_TIMESTAMP, QuicUdpPacketInfoBit::TTL, + QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER), + &read_results_); + for (size_t i = 0; i < packets_read; ++i) { + auto& result = read_results_[i]; + if (!result.ok) { + QUIC_RESTART_FLAG_COUNT_N( + quic_remove_quic_socket_utils_from_packet_reader, 2, 5); + continue; + } + + if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) { + QUIC_BUG << "Unable to get peer socket address."; + continue; + } + + QuicSocketAddress peer_address = + result.packet_info.peer_address().Normalized(); + + QuicIpAddress self_ip = GetSelfIpFromPacketInfo( + result.packet_info, peer_address.host().IsIPv6()); + if (!self_ip.IsInitialized()) { + QUIC_BUG << "Unable to get self IP address."; + continue; + } + + QuicWallTime walltimestamp = + result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP) + ? result.packet_info.receive_timestamp() + : wallnow; + if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP)) { + QUIC_RESTART_FLAG_COUNT_N( + quic_remove_quic_socket_utils_from_packet_reader, 3, 5); + } + + bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL); + int ttl = has_ttl ? result.packet_info.ttl() : 0; + if (!has_ttl) { + QUIC_RESTART_FLAG_COUNT_N( + quic_remove_quic_socket_utils_from_packet_reader, 4, 5); + } + + char* headers = nullptr; + size_t headers_length = 0; + if (result.packet_info.HasValue( + QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) { + headers = result.packet_info.google_packet_headers().buffer; + headers_length = result.packet_info.google_packet_headers().buffer_len; + } else { + QUIC_RESTART_FLAG_COUNT_N( + quic_remove_quic_socket_utils_from_packet_reader, 5, 5); + } + + QuicReceivedPacket packet( + result.packet_buffer.buffer, result.packet_buffer.buffer_len, + clock.ConvertWallTimeToQuicTime(walltimestamp), /*owns_buffer=*/false, + ttl, has_ttl, headers, headers_length, /*owns_header_buffer=*/false); + + QuicSocketAddress self_address(self_ip, port); + processor->ProcessPacket(self_address, peer_address, packet); + } + + // We may not have read all of the packets available on the socket. + return packets_read == kNumPacketsPerReadMmsgCall; +} + +// static +QuicIpAddress QuicPacketReader::GetSelfIpFromPacketInfo( + const QuicUdpPacketInfo& packet_info, + bool prefer_v6_ip) { + if (prefer_v6_ip) { + if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) { + return packet_info.self_v6_ip(); + } + if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) { + return packet_info.self_v4_ip(); + } + } else { + if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) { + return packet_info.self_v4_ip(); + } + if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) { + return packet_info.self_v6_ip(); + } + } + return QuicIpAddress(); } bool QuicPacketReader::ReadAndDispatchManyPackets( @@ -80,6 +199,7 @@ const QuicClock& clock, ProcessPacketInterface* processor, QuicPacketCount* packets_dropped) { + DCHECK(!remove_quic_socket_utils_from_packet_reader_); #if MMSG_MORE_NO_ANDROID // Re-set the length fields in case recvmmsg has changed them. for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) { @@ -196,6 +316,7 @@ const QuicClock& clock, ProcessPacketInterface* processor, QuicPacketCount* packets_dropped) { + DCHECK(!GetQuicRestartFlag(quic_remove_quic_socket_utils_from_packet_reader)); char buf[kMaxV4PacketSize]; QuicSocketAddress peer_address;
diff --git a/quic/core/quic_packet_reader.h b/quic/core/quic_packet_reader.h index 1e644aa..3c6d928 100644 --- a/quic/core/quic_packet_reader.h +++ b/quic/core/quic_packet_reader.h
@@ -14,7 +14,10 @@ #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h" +#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h" #include "net/third_party/quiche/src/quic/platform/api/quic_clock.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/impl/quic_socket_utils.h" @@ -64,6 +67,14 @@ ProcessPacketInterface* processor, QuicPacketCount* packets_dropped); + // Return the self ip from |packet_info|. + // For dual stack sockets, |packet_info| may contain both a v4 and a v6 ip, in + // that case, |prefer_v6_ip| is used to determine which one is used as the + // return value. If neither v4 nor v6 ip exists, return an uninitialized ip. + static QuicIpAddress GetSelfIpFromPacketInfo( + const QuicUdpPacketInfo& packet_info, + bool prefer_v6_ip); + #if MMSG_MORE // Storage only used when recvmmsg is available. // TODO(danzh): change it to be a pointer to avoid the allocation on the stack @@ -83,6 +94,17 @@ PacketData packets_[kNumPacketsPerReadMmsgCall]; mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall]; #endif + struct QUIC_EXPORT_PRIVATE ReadBuffer { + QUIC_CACHELINE_ALIGNED char + control_buffer[kCmsgSpaceForReadPacket]; // For ancillary data. + QUIC_CACHELINE_ALIGNED char packet_buffer[kMaxIncomingPacketSize]; + }; + // Latched value of --quic_remove_quic_socket_utils_from_packet_reader. + const bool remove_quic_socket_utils_from_packet_reader_ = + GetQuicRestartFlag(quic_remove_quic_socket_utils_from_packet_reader); + QuicUdpSocketApi socket_api_; + std::vector<ReadBuffer> read_buffers_; + QuicUdpSocketApi::ReadPacketResults read_results_; }; } // namespace quic
diff --git a/quic/core/quic_udp_socket.h b/quic/core/quic_udp_socket.h index b60386f..8be9e57 100644 --- a/quic/core/quic_udp_socket.h +++ b/quic/core/quic_udp_socket.h
@@ -59,6 +59,8 @@ public: BitMask64 bitmask() const { return bitmask_; } + void Reset() { bitmask_.ClearAll(); } + bool HasValue(QuicUdpPacketInfoBit bit) const { return bitmask_.IsSet(bit); } QuicPacketCount dropped_packets() const { @@ -129,6 +131,11 @@ bitmask_.Set(QuicUdpPacketInfoBit::TTL); } + BufferSpan google_packet_headers() const { + DCHECK(HasValue(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)); + return google_packet_headers_; + } + void SetGooglePacketHeaders(BufferSpan google_packet_headers) { google_packet_headers_ = google_packet_headers; bitmask_.Set(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER); @@ -183,15 +190,26 @@ QuicUdpPacketInfo packet_info; BufferSpan packet_buffer; BufferSpan control_buffer; + + void Reset(size_t packet_buffer_length) { + ok = false; + packet_info.Reset(); + packet_buffer.buffer_len = packet_buffer_length; + } }; // Read a packet from |fd|: // packet_info_interested: Bitmask indicating what information caller wants to // receive into |result->packet_info|. // result->packet_info: Received per packet information. // result->packet_buffer: The packet buffer, to be filled with packet data. + // |result->packet_buffer.buffer_len| is set to the + // packet length on a successful return. // result->control_buffer: The control buffer, used by ReadPacket internally. // It is recommended to be at least 512 bytes. // result->ok: True iff a packet is successfully received. + // + // If |*result| is reused for subsequent ReadPacket() calls, caller needs to + // call result->Reset() before each ReadPacket(). void ReadPacket(QuicUdpSocketFd fd, BitMask64 packet_info_interested, ReadPacketResult* result);
diff --git a/quic/core/quic_udp_socket_test.cc b/quic/core/quic_udp_socket_test.cc index eaa9f4c..e43fb10 100644 --- a/quic/core/quic_udp_socket_test.cc +++ b/quic/core/quic_udp_socket_test.cc
@@ -123,6 +123,20 @@ char server_control_buffer_[512] = {0}; }; +TEST_F(QuicUdpSocketTest, ReadPacketResultReset) { + QuicUdpSocketApi::ReadPacketResult result; + result.packet_info.SetDroppedPackets(100); + result.packet_buffer.buffer_len = 100; + result.ok = true; + + result.Reset(/*packet_buffer_length=*/200); + + EXPECT_FALSE(result.ok); + EXPECT_FALSE( + result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS)); + EXPECT_EQ(200u, result.packet_buffer.buffer_len); +} + TEST_F(QuicUdpSocketTest, ReadPacketOnly) { const size_t kPacketSize = 512; memset(client_packet_buffer_, '-', kPacketSize);
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h index a0e0452..04858f0 100644 --- a/quic/core/quic_utils.h +++ b/quic/core/quic_utils.h
@@ -243,6 +243,8 @@ return (MakeMask(bit) & mask_) != 0; } + void ClearAll() { mask_ = 0; } + static constexpr size_t NumBits() { return 8 * sizeof(Mask); } friend bool operator==(const BitMask& lhs, const BitMask& rhs) {
diff --git a/quic/core/quic_utils_test.cc b/quic/core/quic_utils_test.cc index aac0fd8..e6fe1a2 100644 --- a/quic/core/quic_utils_test.cc +++ b/quic/core/quic_utils_test.cc
@@ -288,6 +288,11 @@ EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_ZERO)); EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE)); EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_TWO)); + + mask.ClearAll(); + EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ZERO)); + EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE)); + EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_TWO)); } TEST(QuicBitMaskTest, Enum) { @@ -295,6 +300,11 @@ EXPECT_FALSE(mask.IsSet(TEST_BIT_0)); EXPECT_TRUE(mask.IsSet(TEST_BIT_1)); EXPECT_TRUE(mask.IsSet(TEST_BIT_2)); + + mask.ClearAll(); + EXPECT_FALSE(mask.IsSet(TEST_BIT_0)); + EXPECT_FALSE(mask.IsSet(TEST_BIT_1)); + EXPECT_FALSE(mask.IsSet(TEST_BIT_2)); } TEST(QuicBitMaskTest, Integer) {