gfe-relnote: In QUIC, add anti-amplification limit. Protected by version T099.
Anti-amplification limit kicks in before address validation. Now, server can only validate address by processing HANDSHAKE encrypted packet since address validation via token is not implemented.
In T099, deprecate HANDSHAKE_MODE and PTO is armed when 1) handshake is not confirmed 2) or there is packets in flight. Such that when PTO fires, at least 1 packet is sent to avoid handshake deadlock due to anti-amplification limit in case of packet losses.
PiperOrigin-RevId: 264960590
Change-Id: Ib2d9749b773af9328f96c176a49b2505be006b00
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index 025962a..a70dd01 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -122,7 +122,8 @@
GetQuicReloadableFlag(quic_loss_removes_from_inflight)),
ignore_tlpr_if_no_pending_stream_data_(
GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)),
- fix_rto_retransmission_(false) {
+ fix_rto_retransmission_(false),
+ handshake_mode_disabled_(false) {
if (loss_removes_from_inflight_) {
QUIC_RELOADABLE_FLAG_COUNT(quic_loss_removes_from_inflight);
}
@@ -726,7 +727,8 @@
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::OnRetransmissionTimeout() {
- DCHECK(unacked_packets_.HasInFlightPackets());
+ DCHECK(unacked_packets_.HasInFlightPackets() ||
+ (handshake_mode_disabled_ && !handshake_confirmed_));
DCHECK_EQ(0u, pending_timer_transmission_count_);
// Handshake retransmission, timer based loss detection, TLP, and RTO are
// implemented with a single alarm. The handshake alarm is set when the
@@ -735,6 +737,7 @@
// The TLP alarm is always set to run for under an RTO.
switch (GetRetransmissionMode()) {
case HANDSHAKE_MODE:
+ DCHECK(!handshake_mode_disabled_);
++stats_->crypto_retransmit_count;
RetransmitCryptoPackets();
return HANDSHAKE_MODE;
@@ -918,10 +921,19 @@
pending_timer_transmission_count_ = 1;
}
+void QuicSentPacketManager::DisableHandshakeMode() {
+ DCHECK(session_decides_what_to_write());
+ fix_rto_retransmission_ = true;
+ pto_enabled_ = true;
+ handshake_mode_disabled_ = true;
+}
+
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::GetRetransmissionMode() const {
- DCHECK(unacked_packets_.HasInFlightPackets());
- if (!handshake_confirmed_ && unacked_packets_.HasPendingCryptoPackets()) {
+ DCHECK(unacked_packets_.HasInFlightPackets() ||
+ (handshake_mode_disabled_ && !handshake_confirmed_));
+ if (!handshake_mode_disabled_ && !handshake_confirmed_ &&
+ unacked_packets_.HasPendingCryptoPackets()) {
return HANDSHAKE_MODE;
}
if (loss_algorithm_->GetLossTimeout() != QuicTime::Zero()) {
@@ -1007,10 +1019,17 @@
}
const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
- // Don't set the timer if there is nothing to retransmit or we've already
- // queued a tlp transmission and it hasn't been sent yet.
- if (!unacked_packets_.HasInFlightPackets() ||
- pending_timer_transmission_count_ > 0) {
+ if (!unacked_packets_.HasInFlightPackets() &&
+ (!handshake_mode_disabled_ || handshake_confirmed_ ||
+ unacked_packets_.perspective() == Perspective::IS_SERVER)) {
+ // Do not set the timer if there is nothing in flight. However, to avoid
+ // handshake deadlock due to anti-amplification limit, client needs to set
+ // PTO timer when the handshake is not confirmed even there is nothing in
+ // flight.
+ return QuicTime::Zero();
+ }
+ if (pending_timer_transmission_count_ > 0) {
+ // Do not set the timer if there is any credit left.
return QuicTime::Zero();
}
if (!fix_rto_retransmission_ &&
@@ -1044,6 +1063,13 @@
return std::max(tlp_time, rto_time);
}
case PTO_MODE: {
+ if (handshake_mode_disabled_ && !handshake_confirmed_ &&
+ !unacked_packets_.HasInFlightPackets()) {
+ DCHECK_EQ(Perspective::IS_CLIENT, unacked_packets_.perspective());
+ return std::max(clock_->ApproximateNow(),
+ unacked_packets_.GetLastCryptoPacketSentTime() +
+ GetProbeTimeoutDelay());
+ }
// Ensure PTO never gets set to a time in the past.
return std::max(
clock_->ApproximateNow(),