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) {