webrtc_m130/api/transport/test/network_control_tester.cc
Sebastian Jansson 535bde3752 Adds data in flight information on send packet updates.
This prepares for making the BBR implementation more identical to the
implementation in Quic, this is to ensure that results are comparable.

Bug: webrtc:8415
Change-Id: I7b7e4769772d67cc5112969fefd4e56c6c72432e
Reviewed-on: https://webrtc-review.googlesource.com/76600
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23419}
2018-05-28 15:33:39 +00:00

148 lines
5.8 KiB
C++

/*
* Copyright (c) 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 "api/transport/test/network_control_tester.h"
#include <algorithm>
#include "api/transport/network_control.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace test {
namespace {
void Update(NetworkControlUpdate* target, const NetworkControlUpdate& update) {
if (update.congestion_window) {
RTC_LOG(LS_INFO) << "Received window="
<< ToString(*update.congestion_window);
target->congestion_window = update.congestion_window;
}
if (update.pacer_config) {
RTC_LOG(LS_INFO) << "Received pacing at:"
<< ToString(update.pacer_config->at_time)
<< ": rate=" << ToString(update.pacer_config->data_rate())
<< ", pad=" << ToString(update.pacer_config->pad_rate());
target->pacer_config = update.pacer_config;
}
if (update.target_rate) {
RTC_LOG(LS_INFO)
<< "Received target at:" << ToString(update.target_rate->at_time)
<< ": rate=" << ToString(update.target_rate->target_rate) << ", rtt="
<< ToString(update.target_rate->network_estimate.round_trip_time);
target->target_rate = update.target_rate;
}
for (const auto& probe : update.probe_cluster_configs) {
target->probe_cluster_configs.push_back(probe);
RTC_LOG(LS_INFO) << "Received probe at:" << ToString(probe.at_time)
<< ": target=" << ToString(probe.target_data_rate);
}
}
} // namespace
SentPacket SimpleTargetRateProducer::ProduceNext(
const NetworkControlUpdate& cache,
Timestamp current_time,
TimeDelta time_delta) {
DataRate actual_send_rate =
std::max(cache.target_rate->target_rate, cache.pacer_config->pad_rate());
SentPacket packet;
packet.send_time = current_time;
packet.size = time_delta * actual_send_rate;
return packet;
}
NetworkControllerTester::NetworkControllerTester(
NetworkControllerFactoryInterface* factory,
NetworkControllerConfig initial_config)
: current_time_(Timestamp::seconds(100000)),
packet_sequence_number_(1),
accumulated_buffer_(DataSize::Zero()) {
initial_config.constraints.at_time = current_time_;
controller_ = factory->Create(initial_config);
process_interval_ = factory->GetProcessInterval();
ProcessInterval interval_msg;
interval_msg.at_time = current_time_;
Update(&state_, controller_->OnProcessInterval(interval_msg));
}
NetworkControllerTester::~NetworkControllerTester() = default;
void NetworkControllerTester::RunSimulation(TimeDelta duration,
TimeDelta packet_interval,
DataRate actual_bandwidth,
TimeDelta propagation_delay,
PacketProducer next_packet) {
Timestamp start_time = current_time_;
Timestamp last_process_time = current_time_;
while (current_time_ - start_time < duration) {
bool send_packet = true;
if (state_.congestion_window && state_.congestion_window->IsFinite()) {
DataSize data_in_flight = DataSize::Zero();
for (PacketResult& packet : outstanding_packets_)
data_in_flight += packet.sent_packet->size;
if (data_in_flight > *state_.congestion_window)
send_packet = false;
}
if (send_packet) {
SentPacket sent_packet;
sent_packet = next_packet(state_, current_time_, packet_interval);
sent_packet.sequence_number = packet_sequence_number_++;
sent_packet.data_in_flight = sent_packet.size;
for (PacketResult& packet : outstanding_packets_)
sent_packet.data_in_flight += packet.sent_packet->size;
Update(&state_, controller_->OnSentPacket(sent_packet));
accumulated_buffer_ += sent_packet.size;
TimeDelta buffer_delay = accumulated_buffer_ / actual_bandwidth;
TimeDelta total_delay = propagation_delay + buffer_delay;
PacketResult result;
result.sent_packet = sent_packet;
result.receive_time = sent_packet.send_time + total_delay;
outstanding_packets_.push_back(result);
}
DataSize buffer_consumed =
std::min(accumulated_buffer_, packet_interval * actual_bandwidth);
accumulated_buffer_ -= buffer_consumed;
if (outstanding_packets_.size() >= 2 &&
current_time_ >=
outstanding_packets_[1].receive_time + propagation_delay) {
TransportPacketsFeedback feedback;
feedback.prior_in_flight = DataSize::Zero();
for (PacketResult& packet : outstanding_packets_)
feedback.prior_in_flight += packet.sent_packet->size;
while (!outstanding_packets_.empty() &&
current_time_ >= outstanding_packets_.front().receive_time +
propagation_delay) {
feedback.packet_feedbacks.push_back(outstanding_packets_.front());
outstanding_packets_.pop_front();
}
feedback.feedback_time =
feedback.packet_feedbacks.back().receive_time + propagation_delay;
feedback.data_in_flight = DataSize::Zero();
for (PacketResult& packet : outstanding_packets_)
feedback.data_in_flight += packet.sent_packet->size;
Update(&state_, controller_->OnTransportPacketsFeedback(feedback));
}
current_time_ += packet_interval;
if (current_time_ - last_process_time > process_interval_) {
ProcessInterval interval_msg;
interval_msg.at_time = current_time_;
Update(&state_, controller_->OnProcessInterval(interval_msg));
}
}
}
} // namespace test
} // namespace webrtc