gfe-relnote: Allow GFE to perform initial cwnd up and down experiment. Protected by --gfe2_reloadable_flag_quic_gfe_selected_initial_cwnd_experiments.

The minimum cwnd is 10, and the default enabled up and down experiment is 25%.

PiperOrigin-RevId: 248124804
Change-Id: Ie21685f8e35946eaa499dab935b154b928af7318
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc
index 7d7258f..3369876 100644
--- a/quic/core/congestion_control/bbr_sender.cc
+++ b/quic/core/congestion_control/bbr_sender.cc
@@ -340,7 +340,8 @@
 }
 
 void BbrSender::AdjustNetworkParameters(QuicBandwidth bandwidth,
-                                        QuicTime::Delta rtt) {
+                                        QuicTime::Delta rtt,
+                                        bool allow_cwnd_to_decrease) {
   if (!bandwidth.IsZero()) {
     max_bandwidth_.Update(bandwidth, round_trip_count_);
   }
@@ -350,8 +351,13 @@
   if (GetQuicReloadableFlag(quic_fix_bbr_cwnd_in_bandwidth_resumption) &&
       mode_ == STARTUP) {
     const QuicByteCount new_cwnd =
-        std::min(kMaxInitialCongestionWindow * kDefaultTCPMSS,
-                 bandwidth * rtt_stats_->SmoothedOrInitialRtt());
+        std::max(kMinInitialCongestionWindow * kDefaultTCPMSS,
+                 std::min(kMaxInitialCongestionWindow * kDefaultTCPMSS,
+                          bandwidth * rtt_stats_->SmoothedOrInitialRtt()));
+    // Decreases cwnd gain and pacing gain. Please note, if pacing_rate_ has
+    // been calculated, it cannot decrease in STARTUP phase.
+    set_high_gain(kDerivedHighCWNDGain);
+    set_high_cwnd_gain(kDerivedHighCWNDGain);
     if (new_cwnd > congestion_window_) {
       QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_bbr_cwnd_in_bandwidth_resumption, 1,
                                    2);
@@ -359,11 +365,13 @@
       QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_bbr_cwnd_in_bandwidth_resumption, 2,
                                    2);
     }
-    // Decreases cwnd gain and pacing gain. Please note, if pacing_rate_ has
-    // been calculated, it cannot decrease in STARTUP phase.
-    set_high_gain(kDerivedHighCWNDGain);
-    set_high_cwnd_gain(kDerivedHighCWNDGain);
-    congestion_window_ = std::max(new_cwnd, congestion_window_);
+    if (bandwidth.IsZero() ||
+        (new_cwnd < congestion_window_ && !allow_cwnd_to_decrease)) {
+      // Ignore bad bandwidth samples. Only decrease cwnd if
+      // allow_cwnd_to_decrease is true.
+      return;
+    }
+    congestion_window_ = new_cwnd;
   }
 }
 
diff --git a/quic/core/congestion_control/bbr_sender.h b/quic/core/congestion_control/bbr_sender.h
index 843764b..a49a5ef 100644
--- a/quic/core/congestion_control/bbr_sender.h
+++ b/quic/core/congestion_control/bbr_sender.h
@@ -108,7 +108,8 @@
                      Perspective perspective) override;
 
   void AdjustNetworkParameters(QuicBandwidth bandwidth,
-                               QuicTime::Delta rtt) override;
+                               QuicTime::Delta rtt,
+                               bool allow_cwnd_to_decrease) override;
   void SetNumEmulatedConnections(int num_connections) override {}
   void SetInitialCongestionWindowInPackets(
       QuicPacketCount congestion_window) override;
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc
index 1f4c082..be4f291 100644
--- a/quic/core/congestion_control/bbr_sender_test.cc
+++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -1292,7 +1292,7 @@
   CreateDefaultSetup();
 
   bbr_sender_.connection()->AdjustNetworkParameters(kTestLinkBandwidth,
-                                                    kTestRtt);
+                                                    kTestRtt, false);
   EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
   EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
   EXPECT_APPROX_EQ(kTestRtt, sender_->ExportDebugState().min_rtt, 0.01f);
diff --git a/quic/core/congestion_control/send_algorithm_interface.h b/quic/core/congestion_control/send_algorithm_interface.h
index 620b23f..9db67b5 100644
--- a/quic/core/congestion_control/send_algorithm_interface.h
+++ b/quic/core/congestion_control/send_algorithm_interface.h
@@ -120,7 +120,8 @@
   // measurement or prediction.  Either |bandwidth| or |rtt| may be zero if no
   // sample is available.
   virtual void AdjustNetworkParameters(QuicBandwidth bandwidth,
-                                       QuicTime::Delta rtt) = 0;
+                                       QuicTime::Delta rtt,
+                                       bool allow_cwnd_to_decrease) = 0;
 
   // Retrieves debugging information about the current state of the
   // send algorithm.
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index fde8d75..7cbf332 100644
--- a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -105,8 +105,10 @@
   }
 }
 
-void TcpCubicSenderBytes::AdjustNetworkParameters(QuicBandwidth bandwidth,
-                                                  QuicTime::Delta rtt) {
+void TcpCubicSenderBytes::AdjustNetworkParameters(
+    QuicBandwidth bandwidth,
+    QuicTime::Delta rtt,
+    bool /*allow_cwnd_to_decrease*/) {
   if (bandwidth.IsZero() || rtt.IsZero()) {
     return;
   }
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index a437426..dd8be12 100644
--- a/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -47,7 +47,8 @@
   void SetFromConfig(const QuicConfig& config,
                      Perspective perspective) override;
   void AdjustNetworkParameters(QuicBandwidth bandwidth,
-                               QuicTime::Delta rtt) override;
+                               QuicTime::Delta rtt,
+                               bool allow_cwnd_to_decrease) override;
   void SetNumEmulatedConnections(int num_connections) override;
   void SetInitialCongestionWindowInPackets(
       QuicPacketCount congestion_window) override;
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 5eb6226..32451a5 100644
--- a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -677,11 +677,11 @@
   const QuicBandwidth kBandwidthEstimate =
       QuicBandwidth::FromBytesPerSecond(kNumberOfPackets * kDefaultTCPMSS);
   const QuicTime::Delta kRttEstimate = QuicTime::Delta::FromSeconds(1);
-  sender_->AdjustNetworkParameters(kBandwidthEstimate, kRttEstimate);
+  sender_->AdjustNetworkParameters(kBandwidthEstimate, kRttEstimate, false);
   EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
 
   // Resume with an illegal value of 0 and verify the server ignores it.
-  sender_->AdjustNetworkParameters(QuicBandwidth::Zero(), kRttEstimate);
+  sender_->AdjustNetworkParameters(QuicBandwidth::Zero(), kRttEstimate, false);
   EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
 
   // Resumed CWND is limited to be in a sensible range.
@@ -689,7 +689,7 @@
       QuicBandwidth::FromBytesPerSecond((kMaxCongestionWindowPackets + 1) *
                                         kDefaultTCPMSS);
   sender_->AdjustNetworkParameters(kUnreasonableBandwidth,
-                                   QuicTime::Delta::FromSeconds(1));
+                                   QuicTime::Delta::FromSeconds(1), false);
   EXPECT_EQ(kMaxCongestionWindowPackets * kDefaultTCPMSS,
             sender_->GetCongestionWindow());
 }
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 6873e0f..a3abb33 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -192,6 +192,7 @@
 const QuicTag kBWS2 = TAG('B', 'W', 'S', '2');  // Server bw resumption v2.
 const QuicTag kBWS3 = TAG('B', 'W', 'S', '3');  // QUIC Initial CWND - Control.
 const QuicTag kBWS4 = TAG('B', 'W', 'S', '4');  // QUIC Initial CWND - Enabled.
+const QuicTag kBWS5 = TAG('B', 'W', 'S', '5');  // QUIC Initial CWND up and down
 
 // Enable path MTU discovery experiment.
 const QuicTag kMTUH = TAG('M', 'T', 'U', 'H');  // High-target MTU discovery.
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index eea8618..6798f63 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -548,8 +548,10 @@
 }
 
 void QuicConnection::AdjustNetworkParameters(QuicBandwidth bandwidth,
-                                             QuicTime::Delta rtt) {
-  sent_packet_manager_.AdjustNetworkParameters(bandwidth, rtt);
+                                             QuicTime::Delta rtt,
+                                             bool allow_cwnd_to_decrease) {
+  sent_packet_manager_.AdjustNetworkParameters(bandwidth, rtt,
+                                               allow_cwnd_to_decrease);
 }
 
 QuicBandwidth QuicConnection::MaxPacingRate() const {
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index ea12d71..47816de 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -374,7 +374,9 @@
 
   // Allows the client to adjust network parameters based on external
   // information.
-  void AdjustNetworkParameters(QuicBandwidth bandwidth, QuicTime::Delta rtt);
+  void AdjustNetworkParameters(QuicBandwidth bandwidth,
+                               QuicTime::Delta rtt,
+                               bool allow_cwnd_to_decrease);
 
   // Returns the max pacing rate for the connection.
   virtual QuicBandwidth MaxPacingRate() const;
diff --git a/quic/core/quic_constants.h b/quic/core/quic_constants.h
index 939f746..caac2c7 100644
--- a/quic/core/quic_constants.h
+++ b/quic/core/quic_constants.h
@@ -61,6 +61,9 @@
 // Do not allow initial congestion window to be greater than 200 packets.
 const QuicPacketCount kMaxInitialCongestionWindow = 200;
 
+// Do not allow initial congestion window to be smaller than 10 packets.
+const QuicPacketCount kMinInitialCongestionWindow = 10;
+
 // Minimum size of initial flow control window, for both stream and session.
 // This is only enforced when version.AllowsLowFlowControlLimits() is false.
 const uint32_t kMinimumFlowControlSendWindow = 16 * 1024;  // 16 KB
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index 061ebac..202a8d8 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -264,11 +264,13 @@
           : cached_network_params.bandwidth_estimate_bytes_per_second());
   QuicTime::Delta rtt =
       QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
-  AdjustNetworkParameters(bandwidth, rtt);
+  AdjustNetworkParameters(bandwidth, rtt, /*allow_cwnd_to_decrease=*/false);
 }
 
-void QuicSentPacketManager::AdjustNetworkParameters(QuicBandwidth bandwidth,
-                                                    QuicTime::Delta rtt) {
+void QuicSentPacketManager::AdjustNetworkParameters(
+    QuicBandwidth bandwidth,
+    QuicTime::Delta rtt,
+    bool allow_cwnd_to_decrease) {
   if (!rtt.IsZero()) {
     SetInitialRtt(rtt);
   }
@@ -277,7 +279,8 @@
     QUIC_RELOADABLE_FLAG_COUNT(quic_conservative_bursts);
     pacing_sender_.SetBurstTokens(kConservativeUnpacedBurst);
   }
-  send_algorithm_->AdjustNetworkParameters(bandwidth, rtt);
+  send_algorithm_->AdjustNetworkParameters(bandwidth, rtt,
+                                           allow_cwnd_to_decrease);
   if (debug_delegate_ != nullptr) {
     debug_delegate_->OnAdjustNetworkParameters(
         bandwidth, rtt.IsZero() ? rtt_stats_.SmoothedOrInitialRtt() : rtt,
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index 04fab58..3df874d 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -130,7 +130,9 @@
 
   // Notify the sent packet manager of an external network measurement or
   // prediction for either |bandwidth| or |rtt|; either can be empty.
-  void AdjustNetworkParameters(QuicBandwidth bandwidth, QuicTime::Delta rtt);
+  void AdjustNetworkParameters(QuicBandwidth bandwidth,
+                               QuicTime::Delta rtt,
+                               bool allow_cwnd_to_decrease);
 
   // Retransmits the oldest pending packet there is still a tail loss probe
   // pending.  Invoked after OnRetransmissionTimeout.
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index 6a641fe..c508cca 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -2371,7 +2371,7 @@
   cached_network_params.set_min_rtt_ms(kRtt.ToMilliseconds());
 
   EXPECT_CALL(*send_algorithm_,
-              AdjustNetworkParameters(QuicBandwidth::Zero(), kRtt));
+              AdjustNetworkParameters(QuicBandwidth::Zero(), kRtt, false));
   EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
       .Times(testing::AnyNumber());
   manager_.ResumeConnectionState(cached_network_params, false);
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 643291e..f64ddbd 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -917,7 +917,8 @@
   MOCK_CONST_METHOD0(ShouldSendProbingPacket, bool());
   MOCK_CONST_METHOD0(GetSlowStartThreshold, QuicByteCount());
   MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
-  MOCK_METHOD2(AdjustNetworkParameters, void(QuicBandwidth, QuicTime::Delta));
+  MOCK_METHOD3(AdjustNetworkParameters,
+               void(QuicBandwidth, QuicTime::Delta, bool));
   MOCK_METHOD1(OnApplicationLimited, void(QuicByteCount));
 };