blob: 37226196ce1265662befc8b7c23df017f54d53a2 [file] [log] [blame]
// Copyright (c) 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 "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
#include "net/third_party/quiche/src/quic/quartc/test/bidi_test_runner.h"
#include "net/third_party/quiche/src/quic/quartc/test/quartc_competing_endpoint.h"
#include "net/third_party/quiche/src/quic/quartc/test/quic_trace_interceptor.h"
#include "net/third_party/quiche/src/quic/quartc/test/random_packet_filter.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
namespace quic {
namespace test {
namespace {
class QuartcBidiTest : public QuicTest {
protected:
QuartcBidiTest() {
uint64_t seed = QuicRandom::GetInstance()->RandUint64();
QUIC_LOG(INFO) << "Setting random seed to " << seed;
random_.set_seed(seed);
simulator_.set_random_generator(&random_);
client_trace_interceptor_ = QuicMakeUnique<QuicTraceInterceptor>("client");
server_trace_interceptor_ = QuicMakeUnique<QuicTraceInterceptor>("server");
}
void CreateTransports(QuicBandwidth bandwidth,
QuicTime::Delta propagation_delay,
QuicByteCount queue_length,
int loss_percent) {
// Endpoints which serve as the transports for client and server.
client_transport_ =
QuicMakeUnique<simulator::SimulatedQuartcPacketTransport>(
&simulator_, "client_transport", "server_transport", queue_length);
server_transport_ =
QuicMakeUnique<simulator::SimulatedQuartcPacketTransport>(
&simulator_, "server_transport", "client_transport", queue_length);
// Filters on each of the endpoints facilitate random packet loss.
client_filter_ = QuicMakeUnique<simulator::RandomPacketFilter>(
&simulator_, "client_filter", client_transport_.get());
server_filter_ = QuicMakeUnique<simulator::RandomPacketFilter>(
&simulator_, "server_filter", server_transport_.get());
client_filter_->set_loss_percent(loss_percent);
server_filter_->set_loss_percent(loss_percent);
// Each endpoint connects directly to a switch.
client_switch_ = QuicMakeUnique<simulator::Switch>(
&simulator_, "client_switch", /*port_count=*/8, 2 * queue_length);
server_switch_ = QuicMakeUnique<simulator::Switch>(
&simulator_, "server_switch", /*port_count=*/8, 2 * queue_length);
// Links to the switch have significantly higher bandwidth than the
// bottleneck and insignificant propagation delay.
client_link_ = QuicMakeUnique<simulator::SymmetricLink>(
client_filter_.get(), client_switch_->port(1), 10 * bandwidth,
QuicTime::Delta::FromMicroseconds(1));
server_link_ = QuicMakeUnique<simulator::SymmetricLink>(
server_filter_.get(), server_switch_->port(1), 10 * bandwidth,
QuicTime::Delta::FromMicroseconds(1));
// The bottleneck link connects the two switches with the bandwidth and
// propagation delay specified by the test case.
bottleneck_link_ = QuicMakeUnique<simulator::SymmetricLink>(
client_switch_->port(2), server_switch_->port(2), bandwidth,
propagation_delay);
}
void SetupCompetingEndpoints(QuicBandwidth bandwidth,
QuicTime::Delta send_interval,
QuicByteCount bytes_per_interval) {
competing_client_ = QuicMakeUnique<QuartcCompetingEndpoint>(
&simulator_, send_interval, bytes_per_interval, "competing_client",
"competing_server", quic::Perspective::IS_CLIENT,
quic::test::TestConnectionId(3));
competing_server_ = QuicMakeUnique<QuartcCompetingEndpoint>(
&simulator_, send_interval, bytes_per_interval, "competing_server",
"competing_client", quic::Perspective::IS_SERVER,
quic::test::TestConnectionId(3));
competing_client_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>(
competing_client_->endpoint(), client_switch_->port(3), 10 * bandwidth,
QuicTime::Delta::FromMicroseconds(1));
competing_server_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>(
competing_server_->endpoint(), server_switch_->port(3), 10 * bandwidth,
QuicTime::Delta::FromMicroseconds(1));
}
simulator::Simulator simulator_;
SimpleRandom random_;
std::unique_ptr<simulator::SimulatedQuartcPacketTransport> client_transport_;
std::unique_ptr<simulator::SimulatedQuartcPacketTransport> server_transport_;
std::unique_ptr<simulator::RandomPacketFilter> client_filter_;
std::unique_ptr<simulator::RandomPacketFilter> server_filter_;
std::unique_ptr<simulator::Switch> client_switch_;
std::unique_ptr<simulator::Switch> server_switch_;
std::unique_ptr<simulator::SymmetricLink> client_link_;
std::unique_ptr<simulator::SymmetricLink> server_link_;
std::unique_ptr<simulator::SymmetricLink> bottleneck_link_;
std::unique_ptr<QuartcCompetingEndpoint> competing_client_;
std::unique_ptr<QuartcCompetingEndpoint> competing_server_;
std::unique_ptr<simulator::SymmetricLink> competing_client_link_;
std::unique_ptr<simulator::SymmetricLink> competing_server_link_;
std::unique_ptr<QuicTraceInterceptor> client_trace_interceptor_;
std::unique_ptr<QuicTraceInterceptor> server_trace_interceptor_;
};
TEST_F(QuartcBidiTest, Basic300kbps200ms) {
CreateTransports(QuicBandwidth::FromKBitsPerSecond(300),
QuicTime::Delta::FromMilliseconds(200),
10 * kDefaultMaxPacketSize, /*loss_percent=*/0);
BidiTestRunner runner(&simulator_, client_transport_.get(),
server_transport_.get());
runner.set_client_interceptor(client_trace_interceptor_.get());
runner.set_server_interceptor(server_trace_interceptor_.get());
EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30)));
}
TEST_F(QuartcBidiTest, 300kbps200ms2PercentLoss) {
CreateTransports(QuicBandwidth::FromKBitsPerSecond(300),
QuicTime::Delta::FromMilliseconds(200),
10 * kDefaultMaxPacketSize, /*loss_percent=*/2);
BidiTestRunner runner(&simulator_, client_transport_.get(),
server_transport_.get());
runner.set_client_interceptor(client_trace_interceptor_.get());
runner.set_server_interceptor(server_trace_interceptor_.get());
EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30)));
}
TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossCompetingBurst) {
QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300);
CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200),
10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2);
SetupCompetingEndpoints(bandwidth, QuicTime::Delta::FromSeconds(15),
/*bytes_per_interval=*/50 * 1024);
quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(),
server_transport_.get());
runner.set_client_interceptor(client_trace_interceptor_.get());
runner.set_server_interceptor(server_trace_interceptor_.get());
EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30)));
}
TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossSmallCompetingSpikes) {
QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300);
CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200),
10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2);
// Competition sends a small amount of data (10 kb) every 2 seconds.
SetupCompetingEndpoints(bandwidth, QuicTime::Delta::FromSeconds(2),
/*bytes_per_interval=*/10 * 1024);
quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(),
server_transport_.get());
runner.set_client_interceptor(client_trace_interceptor_.get());
runner.set_server_interceptor(server_trace_interceptor_.get());
EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30)));
}
TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossAggregation) {
QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300);
CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200),
10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2);
// Set aggregation on the queues at either end of the bottleneck.
client_switch_->port_queue(2)->EnableAggregation(
10 * 1024, QuicTime::Delta::FromMilliseconds(100));
server_switch_->port_queue(2)->EnableAggregation(
10 * 1024, QuicTime::Delta::FromMilliseconds(100));
quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(),
server_transport_.get());
runner.set_client_interceptor(client_trace_interceptor_.get());
runner.set_server_interceptor(server_trace_interceptor_.get());
EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30)));
}
} // namespace
} // namespace test
} // namespace quic