In quic, include minplaintextpacketsize when deterine whether removing soft limit for crypto frames. protected by enabled gfe2_reloadable_flag_quic_fix_min_crypto_frame_size. PiperOrigin-RevId: 317743102 Change-Id: I43d56a2b3daea603cac4d2746f58426610875b0f
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index affd89f..d0f38a5 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -11345,6 +11345,44 @@ } } +// Regresstion test for b/156232673. +TEST_P(QuicConnectionTest, CoalescePacketOfLowerEncryptionLevel) { + if (!connection_.version().CanSendCoalescedPackets()) { + return; + } + if (GetQuicReloadableFlag(quic_fix_min_crypto_frame_size)) { + EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1); + } else { + EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(0); + } + { + QuicConnection::ScopedPacketFlusher flusher(&connection_); + use_tagging_decrypter(); + connection_.SetEncrypter(ENCRYPTION_HANDSHAKE, + std::make_unique<TaggingEncrypter>(0x01)); + connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<TaggingEncrypter>(0x02)); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); + SendStreamDataToPeer(2, string(1286, 'a'), 0, NO_FIN, nullptr); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE); + // Try to coalesce a HANDSHAKE packet after 1-RTT packet. + if (GetQuicReloadableFlag(quic_fix_min_crypto_frame_size)) { + // Verify soft max packet length gets resumed and handshake packet gets + // successfully sent. + connection_.SendCryptoDataWithString("a", 0, ENCRYPTION_HANDSHAKE); + } else { + // Problematic: creator thinks there is space to consume 1-byte, however, + // extra paddings make the serialization fail because of + // MinPlaintextPacketSize. + EXPECT_CALL(visitor_, + OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); + EXPECT_QUIC_BUG( + connection_.SendCryptoDataWithString("a", 0, ENCRYPTION_HANDSHAKE), + "AppendPaddingFrame of 3 failed"); + } + } +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc index 82b4a27..7672a37 100644 --- a/quic/core/quic_packet_creator.cc +++ b/quic/core/quic_packet_creator.cc
@@ -198,6 +198,8 @@ } if (framer_->GetMaxPlaintextSize(length) < PacketHeaderSize() + MinPlaintextPacketSize(framer_->version())) { + // Please note: this would not guarantee to fit next packet if the size of + // packet header increases (e.g., encryption level changes). QUIC_DLOG(INFO) << length << " is too small to fit packet header"; return; } @@ -423,8 +425,17 @@ QuicFrame* frame) { size_t min_frame_size = QuicFramer::GetMinCryptoFrameSize(write_length, offset); - if (BytesFree() <= min_frame_size && - (!RemoveSoftMaxPacketLength() || BytesFree() <= min_frame_size)) { + size_t min_plaintext_bytes = min_frame_size; + if (fix_min_crypto_frame_size_ && queued_frames_.empty()) { + // TODO(fayang): to make this more general, we need to move the checking + // when trying to add a frame when GetSerializedFrameLength. Remove soft + // limit if current packet needs extra padding and the space is too small. + QUIC_RELOADABLE_FLAG_COUNT(quic_fix_min_crypto_frame_size); + min_plaintext_bytes = + std::max(min_frame_size, MinPlaintextPacketSize(framer_->version())); + } + if (BytesFree() <= min_plaintext_bytes && + (!RemoveSoftMaxPacketLength() || BytesFree() <= min_plaintext_bytes)) { return false; } size_t max_write_length = BytesFree() - min_frame_size;
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h index c25d8f6..743e46e 100644 --- a/quic/core/quic_packet_creator.h +++ b/quic/core/quic_packet_creator.h
@@ -601,6 +601,9 @@ const bool avoid_leak_writer_buffer_ = GetQuicReloadableFlag(quic_avoid_leak_writer_buffer); + + const bool fix_min_crypto_frame_size_ = + GetQuicReloadableFlag(quic_fix_min_crypto_frame_size); }; } // namespace quic