chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_simulator_test.cc

// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <array>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/str_cat.h"
#include "quiche/quic/core/congestion_control/bbr2_misc.h"
#include "quiche/quic/core/congestion_control/bbr2_sender.h"
#include "quiche/quic/core/congestion_control/bbr_sender.h"
#include "quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h"
#include "quiche/quic/core/quic_bandwidth.h"
#include "quiche/quic/core/quic_packet_number.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_config_peer.h"
#include "quiche/quic/test_tools/quic_connection_peer.h"
#include "quiche/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
#include "quiche/quic/test_tools/send_algorithm_test_result.pb.h"
#include "quiche/quic/test_tools/send_algorithm_test_utils.h"
#include "quiche/quic/test_tools/simulator/link.h"
#include "quiche/quic/test_tools/simulator/quic_endpoint.h"
#include "quiche/quic/test_tools/simulator/simulator.h"
#include "quiche/quic/test_tools/simulator/switch.h"
#include "quiche/quic/test_tools/simulator/traffic_policer.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"

AllOf;
Ge;
Le;

DEFINE_QUICHE_COMMAND_LINE_FLAG();

namespace quic {

CyclePhase;

namespace test {

// Use the initial CWND of 10, as 32 is too much for the test network.
const uint32_t kDefaultInitialCwndPackets =;
const uint32_t kDefaultInitialCwndBytes =;

struct LinkParams {};

struct TrafficPolicerParams {};

// All Bbr2DefaultTopologyTests uses the default network topology:
//
//            Sender
//               |
//               |  <-- local_link
//               |
//        Network switch
//               *  <-- the bottleneck queue in the direction
//               |          of the receiver
//               |
//               |  <-- test_link
//               |
//               |
//           Receiver
class DefaultTopologyParams {};

class Bbr2SimulatorTest : public QuicTest {};

class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {};

TEST_F(Bbr2DefaultTopologyTest, NormalStartup) {}

TEST_F(Bbr2DefaultTopologyTest, NormalStartupB207) {}

// Add extra_acked to CWND in STARTUP and exit STARTUP on a persistent queue.
TEST_F(Bbr2DefaultTopologyTest, NormalStartupB207andB205) {}

// Add extra_acked to CWND in STARTUP and exit STARTUP on a persistent queue.
TEST_F(Bbr2DefaultTopologyTest, NormalStartupBB2S) {}

// Test a simple long data transfer in the default setup.
TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB2RC) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB201) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB206) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB207) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferBBRB) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferBBR4) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferBBR5) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferBBQ1) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferSmallBuffer) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferSmallBufferB2H2) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytes) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytesB201) {}

TEST_F(Bbr2DefaultTopologyTest, SimpleTransferAckDecimation) {}

// Test Bbr2's reaction to a 100x bandwidth decrease during a transfer.
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthDecrease)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B203
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseB203)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BBQ0
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseBBQ0)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BBQ0
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseBBQ0Aggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B202
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseB202)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B202
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseB202Aggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer.
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncrease)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer in the
// presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseAggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BBHI
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseBBHI)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BBHI
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseBBHIAggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BBHI
// and B202, which changes the exit criteria to be based on
// min_bytes_in_flight_in_round, in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseBBHI_B202Aggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B204
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseB204)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B204
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseB204Aggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B205
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseB205)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with B205
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseB205Aggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BB2U
TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncreaseBB2U)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BB2U
// in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseBB2UAggregation)) {}

// Test Bbr2's reaction to a 100x bandwidth increase during a transfer with BB2U
// and BBHI in the presence of ACK aggregation.
TEST_F(Bbr2DefaultTopologyTest,
       QUIC_SLOW_TEST(BandwidthIncreaseBB2UandBBHIAggregation)) {}

// Test the number of losses incurred by the startup phase in a situation when
// the buffer is less than BDP.
TEST_F(Bbr2DefaultTopologyTest, PacketLossOnSmallBufferStartup) {}

// Test the number of losses decreases with packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ6SmallBufferStartup) {}

// Test the number of losses decreases with min_rtt packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ7SmallBufferStartup) {}

// Test the number of losses decreases with Inflight packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ8SmallBufferStartup) {}

// Test the number of losses decreases with CWND packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ9SmallBufferStartup) {}

// Verify the behavior of the algorithm in the case when the connection sends
// small bursts of data after sending continuously for a while.
TEST_F(Bbr2DefaultTopologyTest, ApplicationLimitedBursts) {}

// Verify the behavior of the algorithm in the case when the connection sends
// small bursts of data and then starts sending continuously.
TEST_F(Bbr2DefaultTopologyTest, ApplicationLimitedBurstsWithoutPrior) {}

// Verify that the DRAIN phase works correctly.
TEST_F(Bbr2DefaultTopologyTest, Drain) {}

// Ensure that a connection that is app-limited and is at sufficiently low
// bandwidth will not exit high gain phase, and similarly ensure that the
// connection will exit low gain early if the number of bytes in flight is low.
TEST_F(Bbr2DefaultTopologyTest, InFlightAwareGainCycling) {}

// Test exiting STARTUP earlier upon loss due to loss.
TEST_F(Bbr2DefaultTopologyTest, ExitStartupDueToLoss) {}

// Test exiting STARTUP earlier upon loss due to loss when connection option
// B2SL is used.
TEST_F(Bbr2DefaultTopologyTest, ExitStartupDueToLossB2SL) {}

// Verifies that in STARTUP, if we exceed loss threshold in a round, we exit
// STARTUP at the end of the round even if there's enough bandwidth growth.
TEST_F(Bbr2DefaultTopologyTest, ExitStartupDueToLossB2NE) {}

TEST_F(Bbr2DefaultTopologyTest, SenderPoliced) {}

// TODO(wub): Add other slowstart stats to BBRv2.
TEST_F(Bbr2DefaultTopologyTest, StartupStats) {}

TEST_F(Bbr2DefaultTopologyTest, ProbeUpAdaptInflightHiGradually) {}

// Ensures bandwidth estimate does not change after a loss only event.
TEST_F(Bbr2DefaultTopologyTest, LossOnlyCongestionEvent) {}

// Simulate the case where a packet is considered lost but then acked.
TEST_F(Bbr2DefaultTopologyTest, SpuriousLossEvent) {}

// After quiescence, if the sender is in PROBE_RTT, it should transition to
// PROBE_BW immediately on the first sent packet after quiescence.
TEST_F(Bbr2DefaultTopologyTest, ProbeRttAfterQuiescenceImmediatelyExits) {}

TEST_F(Bbr2DefaultTopologyTest, ProbeBwAfterQuiescencePostponeMinRttTimestamp) {}

TEST_F(Bbr2DefaultTopologyTest, SwitchToBbr2MidConnection) {}

TEST_F(Bbr2DefaultTopologyTest, AdjustNetworkParameters) {}

TEST_F(Bbr2DefaultTopologyTest,
       200InitialCongestionWindowWithNetworkParameterAdjusted) {}

TEST_F(Bbr2DefaultTopologyTest,
       100InitialCongestionWindowFromNetworkParameter) {}

TEST_F(Bbr2DefaultTopologyTest,
       100InitialCongestionWindowWithNetworkParameterAdjusted) {}

// All Bbr2MultiSenderTests uses the following network topology:
//
//   Sender 0  (A Bbr2Sender)
//       |
//       | <-- local_links[0]
//       |
//       |  Sender N (1 <= N < kNumLocalLinks) (May or may not be a Bbr2Sender)
//       |      |
//       |      | <-- local_links[N]
//       |      |
//    Network switch
//           *  <-- the bottleneck queue in the direction
//           |          of the receiver
//           |
//           |  <-- test_link
//           |
//           |
//       Receiver
class MultiSenderTopologyParams {};

class Bbr2MultiSenderTest : public Bbr2SimulatorTest {};

TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr2) {}

TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr2BBPD) {}

TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(MultipleBbr2s)) {}

/* The first 11 packets are sent at the same time, but the duration between the
 * acks of the 1st and the 11th packet is 49 milliseconds, causing very low bw
 * samples. This happens for both large and small buffers.
 */
/*
TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr2LargeRttTinyBuffer) {
  SetupBbr2Sender(sender_endpoints_[1].get());

  MultiSenderTopologyParams params;
  params.switch_queue_capacity_in_bdp = 0.05;
  params.test_link.delay = QuicTime::Delta::FromSeconds(1);
  CreateNetwork(params);

  const QuicByteCount transfer_size = 10 * 1024 * 1024;
  const QuicTime::Delta transfer_time =
      params.BottleneckBandwidth().TransferTime(transfer_size);
  QUIC_LOG(INFO) << "Single flow transfer time: " << transfer_time;

  // Transfer 10% of data in first transfer.
  sender_endpoints_[0]->AddBytesToTransfer(transfer_size);
  bool simulator_result = simulator_.RunUntilOrTimeout(
      [this]() {
        return receiver_endpoints_[0]->bytes_received() >= 0.1 * transfer_size;
      },
      transfer_time);
  ASSERT_TRUE(simulator_result);

  // Start the second transfer and wait until both finish.
  sender_endpoints_[1]->AddBytesToTransfer(transfer_size);
  simulator_result = simulator_.RunUntilOrTimeout(
      [this]() {
        return receiver_endpoints_[0]->bytes_received() == transfer_size &&
               receiver_endpoints_[1]->bytes_received() == transfer_size;
      },
      3 * transfer_time);
  ASSERT_TRUE(simulator_result);
}
*/

TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr1) {}

TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(Bbr2VsReno)) {}

TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(Bbr2VsRenoB2RC)) {}

TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(Bbr2VsCubic)) {}

TEST(MinRttFilter, BadRttSample) {}

}  // namespace test
}  // namespace quic