From 5740afa0a453474ccb49470a42ec9b7f8ee4e128 Mon Sep 17 00:00:00 2001 From: Sebastian Jansson Date: Thu, 13 Jun 2019 16:03:37 +0200 Subject: [PATCH] Removes SimulatedTimeClient Bug: webrtc:9883 Change-Id: Id6e760b37360e7dafc67ded99e06128be20797d1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/141417 Commit-Queue: Sebastian Jansson Reviewed-by: Jonas Olsson Cr-Commit-Position: refs/heads/master@{#28269} --- .../goog_cc_network_control_unittest.cc | 83 ++-- .../pcc/pcc_network_controller_unittest.cc | 24 +- test/scenario/BUILD.gn | 2 - test/scenario/scenario.cc | 28 -- test/scenario/scenario.h | 9 - test/scenario/scenario_config.h | 8 - test/scenario/simulated_time.cc | 392 ------------------ test/scenario/simulated_time.h | 168 -------- 8 files changed, 61 insertions(+), 653 deletions(-) delete mode 100644 test/scenario/simulated_time.cc delete mode 100644 test/scenario/simulated_time.h diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc index 227052a257..5bb3491e0e 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc @@ -59,10 +59,23 @@ const uint32_t kInitialBitrateKbps = 60; const DataRate kInitialBitrate = DataRate::kbps(kInitialBitrateKbps); const float kDefaultPacingRate = 2.5f; +CallClient* CreateVideoSendingClient( + Scenario* s, + CallClientConfig config, + std::vector send_link, + std::vector return_link) { + auto* client = s->CreateClient("send", std::move(config)); + auto* route = s->CreateRoutes(client, send_link, + s->CreateClient("return", CallClientConfig()), + return_link); + s->CreateVideoStream(route->forward(), VideoStreamConfig()); + return client; +} + void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") { auto factory = CreateFeedbackOnlyFactory(); Scenario s("googcc_unit/target_capacity" + test_name, false); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.cc_factory = &factory; config.transport.rates.min_rate = DataRate::kbps(10); config.transport.rates.max_rate = DataRate::kbps(1500); @@ -76,14 +89,14 @@ void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") { [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); }); StatesPrinter* truth = s.CreatePrinter( "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()}); - SimulatedTimeClient* client = - s.CreateSimulatedTimeClient("send", config, {PacketStreamConfig()}, - {send_net->node()}, {ret_net->node()}); + + auto* client = CreateVideoSendingClient(&s, config, {send_net->node()}, + {ret_net->node()}); truth->PrintRow(); s.RunFor(TimeDelta::seconds(25)); truth->PrintRow(); - EXPECT_NEAR(client->target_rate_kbps(), 450, 100); + EXPECT_NEAR(client->target_rate().kbps(), 450, 100); send_net->UpdateConfig([](NetworkSimulationConfig* c) { c->bandwidth = DataRate::kbps(800); @@ -93,7 +106,7 @@ void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") { truth->PrintRow(); s.RunFor(TimeDelta::seconds(20)); truth->PrintRow(); - EXPECT_NEAR(client->target_rate_kbps(), 750, 150); + EXPECT_NEAR(client->target_rate().kbps(), 750, 150); send_net->UpdateConfig([](NetworkSimulationConfig* c) { c->bandwidth = DataRate::kbps(100); @@ -105,7 +118,7 @@ void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") { truth->PrintRow(); s.RunFor(TimeDelta::seconds(50)); truth->PrintRow(); - EXPECT_NEAR(client->target_rate_kbps(), 90, 20); + EXPECT_NEAR(client->target_rate().kbps(), 90, 20); } } // namespace @@ -252,14 +265,15 @@ TEST_F(GoogCcNetworkControllerTest, CongestionWindowPushbackOnNetworkDelay) { }); auto ret_net = s.CreateSimulationNode( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); }); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.cc_factory = &factory; // Start high so bandwidth drop has max effect. config.transport.rates.start_rate = DataRate::kbps(300); config.transport.rates.max_rate = DataRate::kbps(2000); config.transport.rates.min_rate = DataRate::kbps(10); - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net->node()}, {ret_net}); + + auto* client = CreateVideoSendingClient(&s, std::move(config), + {send_net->node()}, {ret_net}); s.RunFor(TimeDelta::seconds(10)); send_net->PauseTransmissionUntil(s.Now() + TimeDelta::seconds(10)); @@ -269,7 +283,7 @@ TEST_F(GoogCcNetworkControllerTest, CongestionWindowPushbackOnNetworkDelay) { // target rate is reduced to the minimum pushback threshold // kDefaultMinPushbackTargetBitrateBps, which is defined as 30 kbps in // congestion_window_pushback_controller. - EXPECT_LT(client->target_rate_kbps(), 40); + EXPECT_LT(client->target_rate().kbps(), 40); } TEST_F(GoogCcNetworkControllerTest, OnNetworkRouteChanged) { @@ -338,22 +352,27 @@ TEST_F(GoogCcNetworkControllerTest, }); auto ret_net = s.CreateSimulationNode( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); }); - SimulatedTimeClientConfig config; + CallClientConfig config; // Start high so bandwidth drop has max effect. config.transport.rates.start_rate = DataRate::kbps(1000); config.transport.rates.max_rate = DataRate::kbps(2000); - config.transport.rates.max_padding_rate = config.transport.rates.max_rate; - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net->node()}, {ret_net}); + auto* client = s.CreateClient("send", config); + auto* route = + s.CreateRoutes(client, {send_net->node()}, + s.CreateClient("return", CallClientConfig()), {ret_net}); + VideoStreamConfig video; + video.stream.pad_to_rate = config.transport.rates.max_rate; + s.CreateVideoStream(route->forward(), video); + // Run for a few seconds to allow the controller to stabilize. s.RunFor(TimeDelta::seconds(10)); // Check that padding rate matches target rate. - EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate_kbps(), 1); + EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate().kbps(), 1); // Check this is also the case when congestion window pushback kicks in. send_net->PauseTransmissionUntil(s.Now() + TimeDelta::seconds(1)); - EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate_kbps(), 1); + EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate().kbps(), 1); } TEST_F(GoogCcNetworkControllerTest, LimitsToFloorIfRttIsHighInTrial) { @@ -376,10 +395,10 @@ TEST_F(GoogCcNetworkControllerTest, LimitsToFloorIfRttIsHighInTrial) { }); auto ret_net = s.CreateSimulationNode( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); }); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.rates.start_rate = kLinkCapacity; - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net}, {ret_net}); + + auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net}); // Run for a few seconds to allow the controller to stabilize. s.RunFor(TimeDelta::seconds(10)); const DataSize kBloatPacketSize = DataSize::bytes(1000); @@ -390,7 +409,7 @@ TEST_F(GoogCcNetworkControllerTest, LimitsToFloorIfRttIsHighInTrial) { // Wait to allow the high RTT to be detected and acted upon. s.RunFor(TimeDelta::seconds(4)); // By now the target rate should have dropped to the minimum configured rate. - EXPECT_NEAR(client->target_rate_kbps(), kBandwidthFloor.kbps(), 1); + EXPECT_NEAR(client->target_rate().kbps(), kBandwidthFloor.kbps(), 1); } TEST_F(GoogCcNetworkControllerTest, UpdatesTargetRateBasedOnLinkCapacity) { @@ -401,15 +420,15 @@ TEST_F(GoogCcNetworkControllerTest, DefaultEstimateVariesInSteadyState) { auto factory = CreateFeedbackOnlyFactory(); ScopedFieldTrials trial("WebRTC-Bwe-StableBandwidthEstimate/Disabled/"); Scenario s("googcc_unit/no_stable_varies", false); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.cc_factory = &factory; NetworkSimulationConfig net_conf; net_conf.bandwidth = DataRate::kbps(500); net_conf.delay = TimeDelta::ms(100); auto send_net = s.CreateSimulationNode(net_conf); auto ret_net = s.CreateSimulationNode(net_conf); - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net}, {ret_net}); + + auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net}); // Run for a while to allow the estimate to stabilize. s.RunFor(TimeDelta::seconds(20)); DataRate min_estimate = DataRate::PlusInfinity(); @@ -428,15 +447,15 @@ TEST_F(GoogCcNetworkControllerTest, StableEstimateDoesNotVaryInSteadyState) { auto factory = CreateFeedbackOnlyFactory(); ScopedFieldTrials trial("WebRTC-Bwe-StableBandwidthEstimate/Enabled/"); Scenario s("googcc_unit/stable_is_stable", false); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.cc_factory = &factory; NetworkSimulationConfig net_conf; net_conf.bandwidth = DataRate::kbps(500); net_conf.delay = TimeDelta::ms(100); auto send_net = s.CreateSimulationNode(net_conf); auto ret_net = s.CreateSimulationNode(net_conf); - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net}, {ret_net}); + + auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net}); // Run for a while to allow the estimate to stabilize. s.RunFor(TimeDelta::seconds(30)); DataRate min_estimate = DataRate::PlusInfinity(); @@ -460,11 +479,9 @@ TEST_F(GoogCcNetworkControllerTest, TEST_F(GoogCcNetworkControllerTest, LossBasedControlDoesModestBackoffToHighLoss) { - auto factory = CreateFeedbackOnlyFactory(); ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/"); Scenario s("googcc_unit/high_loss_channel", false); - SimulatedTimeClientConfig config; - config.transport.cc_factory = &factory; + CallClientConfig config; config.transport.rates.min_rate = DataRate::kbps(10); config.transport.rates.max_rate = DataRate::kbps(1500); config.transport.rates.start_rate = DataRate::kbps(300); @@ -475,12 +492,12 @@ TEST_F(GoogCcNetworkControllerTest, }); auto ret_net = s.CreateSimulationNode( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(200); }); - SimulatedTimeClient* client = s.CreateSimulatedTimeClient( - "send", config, {PacketStreamConfig()}, {send_net}, {ret_net}); + + auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net}); s.RunFor(TimeDelta::seconds(120)); // Without LossBasedControl trial, bandwidth drops to ~10 kbps. - EXPECT_GT(client->target_rate_kbps(), 100); + EXPECT_GT(client->target_rate().kbps(), 100); } TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) { diff --git a/modules/congestion_controller/pcc/pcc_network_controller_unittest.cc b/modules/congestion_controller/pcc/pcc_network_controller_unittest.cc index 6c870c1fdd..ae6ff7ceea 100644 --- a/modules/congestion_controller/pcc/pcc_network_controller_unittest.cc +++ b/modules/congestion_controller/pcc/pcc_network_controller_unittest.cc @@ -75,7 +75,7 @@ TEST(PccNetworkControllerTest, SendsConfigurationOnFirstProcess) { TEST(PccNetworkControllerTest, UpdatesTargetSendRate) { PccNetworkControllerFactory factory; Scenario s("pcc_unit/updates_rate", false); - SimulatedTimeClientConfig config; + CallClientConfig config; config.transport.cc_factory = &factory; config.transport.rates.min_rate = DataRate::kbps(10); config.transport.rates.max_rate = DataRate::kbps(1500); @@ -86,30 +86,28 @@ TEST(PccNetworkControllerTest, UpdatesTargetSendRate) { }); auto ret_net = s.CreateMutableSimulationNode( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); }); - SimulatedTimeClient* client = - s.CreateSimulatedTimeClient("send", config, {PacketStreamConfig()}, - {send_net->node()}, {ret_net->node()}); - - s.RunFor(TimeDelta::seconds(25)); - EXPECT_NEAR(client->target_rate_kbps(), 450, 100); + auto* client = s.CreateClient("send", config); + auto* route = s.CreateRoutes(client, {send_net->node()}, + s.CreateClient("return", CallClientConfig()), + {ret_net->node()}); + s.CreateVideoStream(route->forward(), VideoStreamConfig()); + s.RunFor(TimeDelta::seconds(30)); + EXPECT_NEAR(client->target_rate().kbps(), 450, 100); send_net->UpdateConfig([](NetworkSimulationConfig* c) { c->bandwidth = DataRate::kbps(800); c->delay = TimeDelta::ms(100); }); - s.RunFor(TimeDelta::seconds(20)); - EXPECT_NEAR(client->target_rate_kbps(), 750, 150); - + EXPECT_NEAR(client->target_rate().kbps(), 750, 150); send_net->UpdateConfig([](NetworkSimulationConfig* c) { c->bandwidth = DataRate::kbps(200); c->delay = TimeDelta::ms(200); }); ret_net->UpdateConfig( [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(200); }); - - s.RunFor(TimeDelta::seconds(20)); - EXPECT_NEAR(client->target_rate_kbps(), 200, 40); + s.RunFor(TimeDelta::seconds(35)); + EXPECT_NEAR(client->target_rate().kbps(), 180, 40); } } // namespace test diff --git a/test/scenario/BUILD.gn b/test/scenario/BUILD.gn index be559dbf87..b8b4e77130 100644 --- a/test/scenario/BUILD.gn +++ b/test/scenario/BUILD.gn @@ -65,8 +65,6 @@ if (rtc_include_tests) { "scenario.h", "scenario_config.cc", "scenario_config.h", - "simulated_time.cc", - "simulated_time.h", "stats_collection.cc", "stats_collection.h", "video_frame_matcher.cc", diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc index e469fc6944..b430ea1d77 100644 --- a/test/scenario/scenario.cc +++ b/test/scenario/scenario.cc @@ -166,34 +166,6 @@ void Scenario::ChangeRoute(std::pair clients, clients.first->transport_->Connect(over_nodes.front(), route_ip, overhead); } -SimulatedTimeClient* Scenario::CreateSimulatedTimeClient( - std::string name, - SimulatedTimeClientConfig config, - std::vector stream_configs, - std::vector send_link, - std::vector return_link) { - rtc::IPAddress send_ip(next_route_id_++); - rtc::IPAddress return_ip(next_route_id_++); - SimulatedTimeClient* client = new SimulatedTimeClient( - time_controller_.get(), GetLogWriterFactory(name), config, stream_configs, - send_link, return_link, send_ip, return_ip, Now()); - if (log_writer_factory_ && !name.empty() && - config.transport.state_log_interval.IsFinite()) { - Every(config.transport.state_log_interval, [this, client]() { - client->network_controller_factory_.LogCongestionControllerStats(Now()); - }); - } - if (client->GetNetworkControllerProcessInterval().IsFinite()) { - Every(client->GetNetworkControllerProcessInterval(), - [this, client] { client->CongestionProcess(Now()); }); - } else { - task_queue_.PostTask([this, client] { client->CongestionProcess(Now()); }); - } - Every(TimeDelta::ms(5), [this, client] { client->PacerProcess(Now()); }); - simulated_time_clients_.emplace_back(client); - return client; -} - EmulatedNetworkNode* Scenario::CreateSimulationNode( std::function config_modifier) { NetworkSimulationConfig config; diff --git a/test/scenario/scenario.h b/test/scenario/scenario.h index 1799ef38fb..c4e672ed41 100644 --- a/test/scenario/scenario.h +++ b/test/scenario/scenario.h @@ -26,7 +26,6 @@ #include "test/scenario/network/network_emulation_manager.h" #include "test/scenario/network_node.h" #include "test/scenario/scenario_config.h" -#include "test/scenario/simulated_time.h" #include "test/scenario/video_stream.h" #include "test/time_controller/time_controller.h" @@ -83,13 +82,6 @@ class Scenario { std::vector over_nodes, DataSize overhead); - SimulatedTimeClient* CreateSimulatedTimeClient( - std::string name, - SimulatedTimeClientConfig config, - std::vector stream_configs, - std::vector send_link, - std::vector return_link); - VideoStreamPair* CreateVideoStream( std::pair clients, std::function config_modifier); @@ -171,7 +163,6 @@ class Scenario { std::vector> client_pairs_; std::vector> video_streams_; std::vector> audio_streams_; - std::vector> simulated_time_clients_; std::vector> simulation_nodes_; std::vector> printers_; diff --git a/test/scenario/scenario_config.h b/test/scenario/scenario_config.h index e82ab98d1a..151e9f1d1b 100644 --- a/test/scenario/scenario_config.h +++ b/test/scenario/scenario_config.h @@ -47,7 +47,6 @@ struct TransportControllerConfig { DataRate min_rate = DataRate::kbps(30); DataRate max_rate = DataRate::kbps(3000); DataRate start_rate = DataRate::kbps(300); - DataRate max_padding_rate = DataRate::Zero(); } rates; NetworkControllerFactoryInterface* cc_factory = nullptr; TimeDelta state_log_interval = TimeDelta::ms(100); @@ -57,13 +56,6 @@ struct CallClientConfig { TransportControllerConfig transport; }; -struct SimulatedTimeClientConfig { - TransportControllerConfig transport; - struct Feedback { - TimeDelta interval = TimeDelta::ms(100); - } feedback; -}; - struct PacketStreamConfig { PacketStreamConfig(); PacketStreamConfig(const PacketStreamConfig&); diff --git a/test/scenario/simulated_time.cc b/test/scenario/simulated_time.cc deleted file mode 100644 index fa3ab3907f..0000000000 --- a/test/scenario/simulated_time.cc +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2018 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include "test/scenario/simulated_time.h" - -#include -#include -#include -#include -#include - -#include "absl/memory/memory.h" -#include "absl/types/optional.h" -#include "api/rtc_event_log/rtc_event_log_factory.h" -#include "rtc_base/checks.h" -#include "rtc_base/socket_address.h" - -namespace webrtc { -namespace test { -namespace { -constexpr int kEventLogOutputIntervalMs = 5000; -struct RawFeedbackReportPacket { - static constexpr int MAX_FEEDBACKS = 10; - struct Feedback { - int16_t seq_offset; - int32_t recv_offset_ms; - }; - uint8_t count; - int64_t first_seq_num; - int64_t first_recv_time_ms; - Feedback feedbacks[MAX_FEEDBACKS - 1]; -}; - -std::unique_ptr CreateEventLog( - TaskQueueFactory* task_queue_factory, - LogWriterFactoryInterface* log_writer_factory) { - if (!log_writer_factory) { - return absl::make_unique(); - } - auto event_log = RtcEventLogFactory(task_queue_factory) - .CreateRtcEventLog(RtcEventLog::EncodingType::NewFormat); - bool success = event_log->StartLogging(log_writer_factory->Create(".rtc.dat"), - kEventLogOutputIntervalMs); - RTC_CHECK(success); - return event_log; -} -} // namespace - -PacketStream::PacketStream(PacketStreamConfig config) : config_(config) {} - -std::vector PacketStream::PullPackets(Timestamp at_time) { - if (next_frame_time_.IsInfinite()) - next_frame_time_ = at_time; - - TimeDelta frame_interval = TimeDelta::seconds(1) / config_.frame_rate; - int64_t frame_allowance = (frame_interval * target_rate_).bytes(); - - if (next_frame_is_keyframe_) { - frame_allowance *= config_.keyframe_multiplier; - next_frame_is_keyframe_ = false; - } - - std::vector packets; - while (at_time >= next_frame_time_) { - next_frame_time_ += frame_interval; - - int64_t frame_size = budget_ + frame_allowance; - frame_size = std::max(frame_size, config_.min_frame_size.bytes()); - budget_ += frame_allowance - frame_size; - - int64_t packet_budget = frame_size; - int64_t max_packet_size = config_.max_packet_size.bytes(); - while (packet_budget > max_packet_size) { - packets.push_back(max_packet_size); - packet_budget -= max_packet_size; - } - packets.push_back(packet_budget); - } - for (int64_t& packet : packets) - packet += config_.packet_overhead.bytes(); - return packets; -} - -void PacketStream::OnTargetRateUpdate(DataRate target_rate) { - target_rate_ = std::min(target_rate, config_.max_data_rate); -} - -SimpleFeedbackReportPacket FeedbackFromBuffer( - rtc::CopyOnWriteBuffer raw_buffer) { - RTC_CHECK_LE(sizeof(RawFeedbackReportPacket), raw_buffer.size()); - const RawFeedbackReportPacket& raw_packet = - *reinterpret_cast(raw_buffer.cdata()); - RTC_CHECK_GE(raw_packet.count, 1); - SimpleFeedbackReportPacket packet; - packet.receive_times.emplace_back(SimpleFeedbackReportPacket::ReceiveInfo{ - raw_packet.first_seq_num, Timestamp::ms(raw_packet.first_recv_time_ms)}); - for (int i = 1; i < raw_packet.count; ++i) - packet.receive_times.emplace_back(SimpleFeedbackReportPacket::ReceiveInfo{ - raw_packet.first_seq_num + raw_packet.feedbacks[i - 1].seq_offset, - Timestamp::ms(raw_packet.first_recv_time_ms + - raw_packet.feedbacks[i - 1].recv_offset_ms)}); - return packet; -} - -rtc::CopyOnWriteBuffer FeedbackToBuffer( - const SimpleFeedbackReportPacket packet) { - RTC_CHECK_LE(packet.receive_times.size(), - RawFeedbackReportPacket::MAX_FEEDBACKS); - RawFeedbackReportPacket report; - report.count = packet.receive_times.size(); - RTC_CHECK(!packet.receive_times.empty()); - report.first_seq_num = packet.receive_times.front().sequence_number; - report.first_recv_time_ms = packet.receive_times.front().receive_time.ms(); - - for (int i = 1; i < report.count; ++i) { - report.feedbacks[i - 1].seq_offset = static_cast( - packet.receive_times[i].sequence_number - report.first_seq_num); - report.feedbacks[i - 1].recv_offset_ms = static_cast( - packet.receive_times[i].receive_time.ms() - report.first_recv_time_ms); - } - return rtc::CopyOnWriteBuffer(reinterpret_cast(&report), - sizeof(RawFeedbackReportPacket)); -} - -SimulatedSender::SimulatedSender(EmulatedNetworkNode* send_node, - rtc::IPAddress send_receiver_ip) - : send_node_(send_node), send_receiver_address_(send_receiver_ip, 0) {} - -SimulatedSender::~SimulatedSender() {} - -TransportPacketsFeedback SimulatedSender::PullFeedbackReport( - SimpleFeedbackReportPacket packet, - Timestamp at_time) { - TransportPacketsFeedback report; - report.prior_in_flight = data_in_flight_; - report.feedback_time = at_time; - - for (auto& receive_info : packet.receive_times) { - // Look up sender side information for all packets up to and including each - // packet with feedback in the report. - for (; next_feedback_seq_num_ <= receive_info.sequence_number; - ++next_feedback_seq_num_) { - PacketResult feedback; - if (next_feedback_seq_num_ == receive_info.sequence_number) { - feedback.receive_time = receive_info.receive_time; - } else { - // If we did not get any feedback for this packet, mark it as lost by - // setting receive time to infinity. Note that this can also happen due - // to reordering, we will newer send feedback out of order. In this case - // the packet was not really lost, but we don't have that information. - feedback.receive_time = Timestamp::PlusInfinity(); - } - - // Looking up send side information. - for (auto it = sent_packets_.begin(); it != sent_packets_.end(); ++it) { - if (it->sequence_number == next_feedback_seq_num_) { - feedback.sent_packet = *it; - if (feedback.receive_time.IsFinite()) - sent_packets_.erase(it); - break; - } - } - - data_in_flight_ -= feedback.sent_packet.size; - report.packet_feedbacks.push_back(feedback); - } - } - report.data_in_flight = data_in_flight_; - return report; -} - -// Applies pacing and congetsion window based on the configuration from the -// congestion controller. This is not a complete implementation of the real -// pacer but useful for unit tests since it isn't limited to real time. -std::vector -SimulatedSender::PaceAndPullSendPackets(Timestamp at_time) { - // TODO(srte): Extract the behavior of PacedSender to a threading and time - // independent component and use that here to allow a truthful simulation. - if (last_update_.IsInfinite()) { - pacing_budget_ = 0; - } else { - TimeDelta delta = at_time - last_update_; - pacing_budget_ += (delta * pacer_config_.data_rate()).bytes(); - } - std::vector to_send; - while (data_in_flight_ <= max_in_flight_ && pacing_budget_ >= 0 && - !packet_queue_.empty()) { - PendingPacket pending = packet_queue_.front(); - pacing_budget_ -= pending.size; - packet_queue_.pop_front(); - SentPacket sent; - sent.sequence_number = next_sequence_number_++; - sent.size = DataSize::bytes(pending.size); - data_in_flight_ += sent.size; - sent.data_in_flight = data_in_flight_; - sent.pacing_info = PacedPacketInfo(); - sent.send_time = at_time; - sent_packets_.push_back(sent); - rtc::CopyOnWriteBuffer packet( - std::max(pending.size, sizeof(sent.sequence_number))); - memcpy(packet.data(), &sent.sequence_number, sizeof(sent.sequence_number)); - to_send.emplace_back(PacketReadyToSend{sent, packet}); - } - pacing_budget_ = std::min(pacing_budget_, 0); - last_update_ = at_time; - return to_send; -} - -void SimulatedSender::Update(NetworkControlUpdate update) { - if (update.pacer_config) - pacer_config_ = *update.pacer_config; - if (update.congestion_window) - max_in_flight_ = *update.congestion_window; -} - -SimulatedFeedback::SimulatedFeedback(SimulatedTimeClientConfig config, - rtc::IPAddress return_receiver_ip, - EmulatedNetworkNode* return_node) - : config_(config), - return_receiver_address_(return_receiver_ip, 0), - return_node_(return_node) {} - -// Polls receiver side for a feedback report and sends it to the stream sender -// via return_node_, -void SimulatedFeedback::OnPacketReceived(EmulatedIpPacket packet) { - int64_t sequence_number; - memcpy(&sequence_number, packet.cdata(), sizeof(sequence_number)); - receive_times_.insert({sequence_number, packet.arrival_time}); - if (last_feedback_time_.IsInfinite()) - last_feedback_time_ = packet.arrival_time; - if (packet.arrival_time >= last_feedback_time_ + config_.feedback.interval) { - SimpleFeedbackReportPacket report; - for (; next_feedback_seq_num_ <= sequence_number; - ++next_feedback_seq_num_) { - auto it = receive_times_.find(next_feedback_seq_num_); - if (it != receive_times_.end()) { - report.receive_times.emplace_back( - SimpleFeedbackReportPacket::ReceiveInfo{next_feedback_seq_num_, - it->second}); - receive_times_.erase(it); - } - if (report.receive_times.size() >= - RawFeedbackReportPacket::MAX_FEEDBACKS) { - return_node_->OnPacketReceived( - EmulatedIpPacket(packet.to, return_receiver_address_, - FeedbackToBuffer(report), packet.arrival_time)); - report = SimpleFeedbackReportPacket(); - } - } - if (!report.receive_times.empty()) - return_node_->OnPacketReceived( - EmulatedIpPacket(packet.to, return_receiver_address_, - FeedbackToBuffer(report), packet.arrival_time)); - last_feedback_time_ = packet.arrival_time; - } -} - -SimulatedTimeClient::SimulatedTimeClient( - TimeController* time_controller, - std::unique_ptr log_writer_factory, - SimulatedTimeClientConfig config, - std::vector stream_configs, - std::vector send_link, - std::vector return_link, - rtc::IPAddress send_receiver_ip, - rtc::IPAddress return_receiver_ip, - Timestamp at_time) - : log_writer_factory_(std::move(log_writer_factory)), - event_log_(CreateEventLog(time_controller->GetTaskQueueFactory(), - log_writer_factory_.get())), - network_controller_factory_(log_writer_factory_.get(), config.transport), - send_link_(send_link), - return_link_(return_link), - sender_(send_link.front(), send_receiver_ip), - feedback_(config, return_receiver_ip, return_link.front()) { - current_contraints_.at_time = at_time; - current_contraints_.starting_rate = config.transport.rates.start_rate; - current_contraints_.min_data_rate = config.transport.rates.min_rate; - current_contraints_.max_data_rate = config.transport.rates.max_rate; - NetworkControllerConfig initial_config; - initial_config.constraints = current_contraints_; - initial_config.stream_based_config.max_padding_rate = - config.transport.rates.max_padding_rate; - initial_config.event_log = event_log_.get(); - congestion_controller_ = network_controller_factory_.Create(initial_config); - for (auto& stream_config : stream_configs) - packet_streams_.emplace_back(new PacketStream(stream_config)); - EmulatedNetworkNode::CreateRoute(send_receiver_ip, send_link, &feedback_); - EmulatedNetworkNode::CreateRoute(return_receiver_ip, return_link, this); - - CongestionProcess(at_time); - network_controller_factory_.LogCongestionControllerStats(at_time); - if (log_writer_factory_) { - packet_log_ = log_writer_factory_->Create(".packets.txt"); - packet_log_->Write( - "transport_seq packet_size send_time recv_time feed_time\n"); - } -} - -// Pulls feedback reports from sender side based on the recieved feedback -// packet. Updates congestion controller with the resulting report. -void SimulatedTimeClient::OnPacketReceived(EmulatedIpPacket packet) { - auto report = sender_.PullFeedbackReport(FeedbackFromBuffer(packet.data), - packet.arrival_time); - for (PacketResult& feedback : report.packet_feedbacks) { - if (packet_log_) - LogWriteFormat(packet_log_.get(), - "%" PRId64 " %" PRId64 " %.3lf %.3lf %.3lf\n", - feedback.sent_packet.sequence_number, - feedback.sent_packet.size.bytes(), - feedback.sent_packet.send_time.seconds(), - feedback.receive_time.seconds(), - packet.arrival_time.seconds()); - } - Update(congestion_controller_->OnTransportPacketsFeedback(report)); -} -SimulatedTimeClient::~SimulatedTimeClient() { -} - -void SimulatedTimeClient::Update(NetworkControlUpdate update) { - sender_.Update(update); - if (update.target_rate) { - // TODO(srte): Implement more realistic distribution of bandwidths between - // streams. Either using BitrateAllocationStrategy directly or using - // BitrateAllocation. - double ratio_per_stream = 1.0 / packet_streams_.size(); - DataRate rate_per_stream = - update.target_rate->target_rate * ratio_per_stream; - target_rate_ = update.target_rate->target_rate; - link_capacity_ = update.target_rate->network_estimate.bandwidth; - for (auto& stream : packet_streams_) - stream->OnTargetRateUpdate(rate_per_stream); - } -} - -void SimulatedTimeClient::CongestionProcess(Timestamp at_time) { - ProcessInterval msg; - msg.at_time = at_time; - Update(congestion_controller_->OnProcessInterval(msg)); -} - -void SimulatedTimeClient::PacerProcess(Timestamp at_time) { - ProcessFrames(at_time); - for (const auto& to_send : sender_.PaceAndPullSendPackets(at_time)) { - sender_.send_node_->OnPacketReceived(EmulatedIpPacket( - /*from=*/rtc::SocketAddress(), sender_.send_receiver_address_, - to_send.data, at_time)); - Update(congestion_controller_->OnSentPacket(to_send.send_info)); - } -} - -void SimulatedTimeClient::ProcessFrames(Timestamp at_time) { - for (auto& stream : packet_streams_) { - for (int64_t packet_size : stream->PullPackets(at_time)) { - sender_.packet_queue_.push_back( - SimulatedSender::PendingPacket{packet_size}); - } - } -} - -void SimulatedTimeClient::TriggerFakeReroute(Timestamp at_time) { - NetworkRouteChange msg; - msg.at_time = at_time; - msg.constraints = current_contraints_; - msg.constraints.at_time = at_time; - Update(congestion_controller_->OnNetworkRouteChange(msg)); -} - -TimeDelta SimulatedTimeClient::GetNetworkControllerProcessInterval() const { - return network_controller_factory_.GetProcessInterval(); -} - -DataRate SimulatedTimeClient::link_capacity() const { - return link_capacity_; -} - -double SimulatedTimeClient::target_rate_kbps() const { - return target_rate_.kbps(); -} - -DataRate SimulatedTimeClient::padding_rate() const { - return sender_.pacer_config_.pad_rate(); -} - -} // namespace test -} // namespace webrtc diff --git a/test/scenario/simulated_time.h b/test/scenario/simulated_time.h deleted file mode 100644 index 7f8315717a..0000000000 --- a/test/scenario/simulated_time.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2018 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#ifndef TEST_SCENARIO_SIMULATED_TIME_H_ -#define TEST_SCENARIO_SIMULATED_TIME_H_ - -#include -#include -#include -#include -#include -#include - -#include "api/transport/network_control.h" -#include "api/transport/network_types.h" -#include "api/units/data_rate.h" -#include "api/units/data_size.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "rtc_base/copy_on_write_buffer.h" -#include "test/logging/log_writer.h" -#include "test/scenario/call_client.h" -#include "test/scenario/network_node.h" -#include "test/scenario/scenario_config.h" - -namespace webrtc { -namespace test { -class PacketStream { - public: - explicit PacketStream(PacketStreamConfig config); - - private: - std::vector PullPackets(Timestamp at_time); - void OnTargetRateUpdate(DataRate target_rate); - - friend class SimulatedTimeClient; - PacketStreamConfig config_; - bool next_frame_is_keyframe_ = true; - Timestamp next_frame_time_ = Timestamp::MinusInfinity(); - DataRate target_rate_ = DataRate::Zero(); - int64_t budget_ = 0; -}; - -class SimulatedFeedback : EmulatedNetworkReceiverInterface { - public: - SimulatedFeedback(SimulatedTimeClientConfig config, - rtc::IPAddress return_receiver_ip, - EmulatedNetworkNode* return_node); - - void OnPacketReceived(EmulatedIpPacket packet) override; - - private: - friend class SimulatedTimeClient; - const SimulatedTimeClientConfig config_; - const rtc::SocketAddress return_receiver_address_; - EmulatedNetworkNode* return_node_; - Timestamp last_feedback_time_ = Timestamp::MinusInfinity(); - int32_t next_feedback_seq_num_ = 1; - std::map receive_times_; -}; - -struct SimpleFeedbackReportPacket { - struct ReceiveInfo { - int64_t sequence_number; - Timestamp receive_time; - }; - std::vector receive_times; -}; - -SimpleFeedbackReportPacket FeedbackFromBuffer( - rtc::CopyOnWriteBuffer raw_buffer); -rtc::CopyOnWriteBuffer FeedbackToBuffer( - const SimpleFeedbackReportPacket packet); - -class SimulatedSender { - public: - struct PacketReadyToSend { - SentPacket send_info; - rtc::CopyOnWriteBuffer data; - }; - struct PendingPacket { - int64_t size; - }; - - SimulatedSender(EmulatedNetworkNode* send_node, - rtc::IPAddress send_receiver_ip); - SimulatedSender(const SimulatedSender&) = delete; - ~SimulatedSender(); - TransportPacketsFeedback PullFeedbackReport(SimpleFeedbackReportPacket report, - Timestamp at_time); - std::vector PaceAndPullSendPackets(Timestamp at_time); - void Update(NetworkControlUpdate update); - - private: - friend class SimulatedTimeClient; - EmulatedNetworkNode* send_node_; - const rtc::SocketAddress send_receiver_address_; - PacerConfig pacer_config_; - DataSize max_in_flight_ = DataSize::Infinity(); - - std::deque packet_queue_; - std::vector sent_packets_; - - Timestamp last_update_ = Timestamp::MinusInfinity(); - int64_t pacing_budget_ = 0; - int64_t next_sequence_number_ = 1; - int64_t next_feedback_seq_num_ = 1; - DataSize data_in_flight_ = DataSize::Zero(); -}; - -// SimulatedTimeClient emulates core parts of the behavior of WebRTC from the -// perspective of congestion controllers. This is intended for use in functional -// unit tests to ensure that congestion controllers behave in a reasonable way. -// It does not, however, completely simulate the actual behavior of WebRTC. For -// a more accurate simulation, use the real time only CallClient. -class SimulatedTimeClient : EmulatedNetworkReceiverInterface { - public: - SimulatedTimeClient( - TimeController* time_controller, - std::unique_ptr log_writer_factory, - SimulatedTimeClientConfig config, - std::vector stream_configs, - std::vector send_link, - std::vector return_link, - rtc::IPAddress send_receiver_ip, - rtc::IPAddress return_receiver_ip, - Timestamp at_time); - SimulatedTimeClient(const SimulatedTimeClient&) = delete; - ~SimulatedTimeClient(); - void Update(NetworkControlUpdate update); - void CongestionProcess(Timestamp at_time); - void PacerProcess(Timestamp at_time); - void ProcessFrames(Timestamp at_time); - void TriggerFakeReroute(Timestamp at_time); - TimeDelta GetNetworkControllerProcessInterval() const; - double target_rate_kbps() const; - DataRate link_capacity() const; - DataRate padding_rate() const; - - void OnPacketReceived(EmulatedIpPacket packet) override; - - private: - friend class Scenario; - std::unique_ptr log_writer_factory_; - std::unique_ptr event_log_; - LoggingNetworkControllerFactory network_controller_factory_; - std::unique_ptr congestion_controller_; - std::vector send_link_; - std::vector return_link_; - SimulatedSender sender_; - SimulatedFeedback feedback_; - TargetRateConstraints current_contraints_; - DataRate target_rate_ = DataRate::Infinity(); - DataRate link_capacity_ = DataRate::Infinity(); - std::unique_ptr packet_log_; - - std::vector> packet_streams_; -}; -} // namespace test -} // namespace webrtc - -#endif // TEST_SCENARIO_SIMULATED_TIME_H_