gfe-relnote: In QUIC, check nonretransmittable_frames, instead of packet length, to determine if a serialized packet is a MTU probe or not. Protected by --gfe2_reloadable_flag_quic_better_mtu_packet_check.
PiperOrigin-RevId: 292604133
Change-Id: I14e54f30af8d8a42c205809f5424a9c76a9eeccb
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 9d9f1fc..9ad0190 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -339,7 +339,9 @@
check_handshake_timeout_before_idle_timeout_(GetQuicReloadableFlag(
quic_check_handshake_timeout_before_idle_timeout)),
batch_writer_flush_after_mtu_probe_(
- GetQuicReloadableFlag(quic_batch_writer_flush_after_mtu_probe)) {
+ GetQuicReloadableFlag(quic_batch_writer_flush_after_mtu_probe)),
+ better_mtu_packet_check_(
+ GetQuicReloadableFlag(quic_better_mtu_packet_check)) {
QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
<< server_connection_id
<< " and version: " << ParsedQuicVersionToString(version());
@@ -358,6 +360,10 @@
quic_check_handshake_timeout_before_idle_timeout);
}
+ if (better_mtu_packet_check_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_better_mtu_packet_check);
+ }
+
framer_.set_visitor(this);
stats_.connection_creation_time = clock_->ApproximateNow();
// TODO(ianswett): Supply the NetworkChangeVisitor as a constructor argument
@@ -2196,7 +2202,14 @@
}
const bool looks_like_mtu_probe = packet->retransmittable_frames.empty() &&
packet->encrypted_length > long_term_mtu_;
- SerializedPacketFate fate = DeterminePacketFate(looks_like_mtu_probe);
+ const bool is_mtu_discovery =
+ better_mtu_packet_check_
+ ? QuicUtils::ContainsFrameType(packet->nonretransmittable_frames,
+ MTU_DISCOVERY_FRAME)
+ : looks_like_mtu_probe;
+ DCHECK_EQ(looks_like_mtu_probe, is_mtu_discovery);
+
+ SerializedPacketFate fate = DeterminePacketFate(is_mtu_discovery);
// Termination packets are encrypted and saved, so don't exit early.
const bool is_termination_packet = IsTerminationPacket(*packet);
QuicPacketNumber packet_number = packet->packet_number;
@@ -2215,7 +2228,7 @@
}
DCHECK_LE(encrypted_length, kMaxOutgoingPacketSize);
- if (!looks_like_mtu_probe) {
+ if (!is_mtu_discovery) {
DCHECK_LE(encrypted_length, packet_creator_.max_packet_length());
}
QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
@@ -2293,7 +2306,7 @@
// be closed. By manually flush the writer here, the MTU probe is sent in
// a normal(non-GSO) packet, so the kernel can return EMSGSIZE and we will
// not close the connection.
- if (batch_writer_flush_after_mtu_probe_ && looks_like_mtu_probe &&
+ if (batch_writer_flush_after_mtu_probe_ && is_mtu_discovery &&
writer_->IsBatchMode()) {
QUIC_RELOADABLE_FLAG_COUNT(quic_batch_writer_flush_after_mtu_probe);
result = writer_->Flush();
@@ -2332,7 +2345,7 @@
// In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
// MTU discovery is permanently unsuccessful.
- if (IsMsgTooBig(result) && looks_like_mtu_probe) {
+ if (IsMsgTooBig(result) && is_mtu_discovery) {
// When MSG_TOO_BIG is returned, the system typically knows what the
// actual MTU is, so there is no need to probe further.
// TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 12a899f..6a4d007 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1523,6 +1523,9 @@
// Latched value of quic_batch_writer_flush_after_mtu_probe.
const bool batch_writer_flush_after_mtu_probe_;
+
+ // Latched value of quic_better_mtu_packet_check.
+ const bool better_mtu_packet_check_;
};
} // namespace quic
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc
index 733ee39..f5eecd7 100644
--- a/quic/core/quic_utils.cc
+++ b/quic/core/quic_utils.cc
@@ -321,6 +321,17 @@
}
// static
+bool QuicUtils::ContainsFrameType(const QuicFrames& frames,
+ QuicFrameType type) {
+ for (const QuicFrame& frame : frames) {
+ if (frame.type == type) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
SentPacketState QuicUtils::RetransmissionTypeToPacketState(
TransmissionType retransmission_type) {
switch (retransmission_type) {
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h
index 04858f0..c143154 100644
--- a/quic/core/quic_utils.h
+++ b/quic/core/quic_utils.h
@@ -101,6 +101,9 @@
static bool IsHandshakeFrame(const QuicFrame& frame,
QuicTransportVersion transport_version);
+ // Return true if any frame in |frames| is of |type|.
+ static bool ContainsFrameType(const QuicFrames& frames, QuicFrameType type);
+
// Returns packet state corresponding to |retransmission_type|.
static SentPacketState RetransmissionTypeToPacketState(
TransmissionType retransmission_type);