summaryrefslogtreecommitdiffstats
path: root/chromium/net/quic/congestion_control/inter_arrival_sender.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/quic/congestion_control/inter_arrival_sender.cc')
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_sender.cc529
1 files changed, 0 insertions, 529 deletions
diff --git a/chromium/net/quic/congestion_control/inter_arrival_sender.cc b/chromium/net/quic/congestion_control/inter_arrival_sender.cc
deleted file mode 100644
index 632a41612be..00000000000
--- a/chromium/net/quic/congestion_control/inter_arrival_sender.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-// Copyright (c) 2013 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/quic/congestion_control/inter_arrival_sender.h"
-
-namespace net {
-
-namespace {
-const int64 kProbeBitrateKBytesPerSecond = 1200; // 9.6 Mbit/s
-const float kPacketLossBitrateReduction = 0.7f;
-const float kUncertainSafetyMargin = 0.7f;
-const float kMaxBitrateReduction = 0.9f;
-const float kMinBitrateReduction = 0.05f;
-const uint64 kMinBitrateKbit = 10;
-const int kInitialRttMs = 60; // At a typical RTT 60 ms.
-const float kAlpha = 0.125f;
-const float kOneMinusAlpha = 1 - kAlpha;
-
-static const int kBitrateSmoothingPeriodMs = 1000;
-static const int kMinBitrateSmoothingPeriodMs = 500;
-
-} // namespace
-
-InterArrivalSender::InterArrivalSender(const QuicClock* clock)
- : probing_(true),
- max_segment_size_(kDefaultMaxPacketSize),
- current_bandwidth_(QuicBandwidth::Zero()),
- smoothed_rtt_(QuicTime::Delta::Zero()),
- channel_estimator_(new ChannelEstimator()),
- bitrate_ramp_up_(new InterArrivalBitrateRampUp(clock)),
- overuse_detector_(new InterArrivalOveruseDetector()),
- probe_(new InterArrivalProbe(max_segment_size_)),
- state_machine_(new InterArrivalStateMachine(clock)),
- paced_sender_(new PacedSender(QuicBandwidth::FromKBytesPerSecond(
- kProbeBitrateKBytesPerSecond), max_segment_size_)),
- accumulated_number_of_lost_packets_(0),
- bandwidth_usage_state_(kBandwidthSteady),
- back_down_time_(QuicTime::Zero()),
- back_down_bandwidth_(QuicBandwidth::Zero()),
- back_down_congestion_delay_(QuicTime::Delta::Zero()) {
-}
-
-InterArrivalSender::~InterArrivalSender() {
-}
-
-void InterArrivalSender::SetFromConfig(const QuicConfig& config,
- bool is_server) {
-}
-
-void InterArrivalSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
- max_segment_size_ = max_packet_size;
- paced_sender_->set_max_segment_size(max_segment_size_);
- probe_->set_max_segment_size(max_segment_size_);
-}
-
-// TODO(pwestin): this is really inefficient (4% CPU on the GFE loadtest).
-// static
-QuicBandwidth InterArrivalSender::CalculateSentBandwidth(
- const SendAlgorithmInterface::SentPacketsMap& sent_packets_map,
- QuicTime feedback_receive_time) {
- const QuicTime::Delta kBitrateSmoothingPeriod =
- QuicTime::Delta::FromMilliseconds(kBitrateSmoothingPeriodMs);
- const QuicTime::Delta kMinBitrateSmoothingPeriod =
- QuicTime::Delta::FromMilliseconds(kMinBitrateSmoothingPeriodMs);
-
- QuicByteCount sum_bytes_sent = 0;
-
- // Sum packet from new until they are kBitrateSmoothingPeriod old.
- SendAlgorithmInterface::SentPacketsMap::const_reverse_iterator history_rit =
- sent_packets_map.rbegin();
-
- QuicTime::Delta max_diff = QuicTime::Delta::Zero();
- for (; history_rit != sent_packets_map.rend(); ++history_rit) {
- QuicTime::Delta diff =
- feedback_receive_time.Subtract(history_rit->second->send_timestamp());
- if (diff > kBitrateSmoothingPeriod) {
- break;
- }
- sum_bytes_sent += history_rit->second->bytes_sent();
- max_diff = diff;
- }
- if (max_diff < kMinBitrateSmoothingPeriod) {
- // No estimate.
- return QuicBandwidth::Zero();
- }
- return QuicBandwidth::FromBytesAndTimeDelta(sum_bytes_sent, max_diff);
-}
-
-void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& feedback,
- QuicTime feedback_receive_time,
- const SentPacketsMap& sent_packets) {
- DCHECK(feedback.type == kInterArrival);
-
- if (feedback.type != kInterArrival) {
- return;
- }
-
- QuicBandwidth sent_bandwidth = CalculateSentBandwidth(sent_packets,
- feedback_receive_time);
-
- TimeMap::const_iterator received_it;
- for (received_it = feedback.inter_arrival.received_packet_times.begin();
- received_it != feedback.inter_arrival.received_packet_times.end();
- ++received_it) {
- QuicPacketSequenceNumber sequence_number = received_it->first;
-
- SentPacketsMap::const_iterator sent_it = sent_packets.find(sequence_number);
- if (sent_it == sent_packets.end()) {
- // Too old data; ignore and move forward.
- DVLOG(1) << "Too old feedback move forward, sequence_number:"
- << sequence_number;
- continue;
- }
- QuicTime time_received = received_it->second;
- QuicTime time_sent = sent_it->second->send_timestamp();
- QuicByteCount bytes_sent = sent_it->second->bytes_sent();
-
- channel_estimator_->OnAcknowledgedPacket(
- sequence_number, bytes_sent, time_sent, time_received);
- if (probing_) {
- probe_->OnIncomingFeedback(
- sequence_number, bytes_sent, time_sent, time_received);
- } else {
- bool last_of_send_time = false;
- SentPacketsMap::const_iterator next_sent_it = ++sent_it;
- if (next_sent_it == sent_packets.end()) {
- // No more sent packets; hence this must be the last.
- last_of_send_time = true;
- } else {
- if (time_sent != next_sent_it->second->send_timestamp()) {
- // Next sent packet have a different send time.
- last_of_send_time = true;
- }
- }
- overuse_detector_->OnAcknowledgedPacket(
- sequence_number, time_sent, last_of_send_time, time_received);
- }
- }
- if (probing_) {
- probing_ = ProbingPhase(feedback_receive_time);
- return;
- }
-
- bool packet_loss_event = false;
- if (accumulated_number_of_lost_packets_ !=
- feedback.inter_arrival.accumulated_number_of_lost_packets) {
- accumulated_number_of_lost_packets_ =
- feedback.inter_arrival.accumulated_number_of_lost_packets;
- packet_loss_event = true;
- }
- InterArrivalState state = state_machine_->GetInterArrivalState();
-
- if (state == kInterArrivalStatePacketLoss ||
- state == kInterArrivalStateCompetingTcpFLow) {
- if (packet_loss_event) {
- if (!state_machine_->PacketLossEvent()) {
- // Less than one RTT since last PacketLossEvent.
- return;
- }
- EstimateBandwidthAfterLossEvent(feedback_receive_time);
- } else {
- EstimateNewBandwidth(feedback_receive_time, sent_bandwidth);
- }
- return;
- }
- EstimateDelayBandwidth(feedback_receive_time, sent_bandwidth);
-}
-
-bool InterArrivalSender::ProbingPhase(QuicTime feedback_receive_time) {
- QuicBandwidth available_channel_estimate = QuicBandwidth::Zero();
- if (!probe_->GetEstimate(&available_channel_estimate)) {
- // Continue probing phase.
- return true;
- }
- QuicBandwidth channel_estimate = QuicBandwidth::Zero();
- ChannelEstimateState channel_estimator_state =
- channel_estimator_->GetChannelEstimate(&channel_estimate);
-
- QuicBandwidth new_rate =
- available_channel_estimate.Scale(kUncertainSafetyMargin);
-
- switch (channel_estimator_state) {
- case kChannelEstimateUnknown:
- channel_estimate = available_channel_estimate;
- break;
- case kChannelEstimateUncertain:
- channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin);
- break;
- case kChannelEstimateGood:
- // Do nothing.
- break;
- }
- new_rate = std::max(new_rate,
- QuicBandwidth::FromKBitsPerSecond(kMinBitrateKbit));
-
- bitrate_ramp_up_->Reset(new_rate, available_channel_estimate,
- channel_estimate);
-
- current_bandwidth_ = new_rate;
- paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_rate);
- DVLOG(1) << "Probe result; new rate:"
- << new_rate.ToKBitsPerSecond() << " Kbits/s "
- << " available estimate:"
- << available_channel_estimate.ToKBitsPerSecond() << " Kbits/s "
- << " channel estimate:"
- << channel_estimate.ToKBitsPerSecond() << " Kbits/s ";
- return false;
-}
-
-void InterArrivalSender::OnPacketAcked(
- QuicPacketSequenceNumber /*acked_sequence_number*/,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) {
- // RTT can't be negative.
- DCHECK_LE(0, rtt.ToMicroseconds());
-
- if (probing_) {
- probe_->OnAcknowledgedPacket(acked_bytes);
- }
-
- if (rtt.IsInfinite()) {
- return;
- }
-
- if (smoothed_rtt_.IsZero()) {
- smoothed_rtt_ = rtt;
- } else {
- smoothed_rtt_ = QuicTime::Delta::FromMicroseconds(
- kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() +
- kAlpha * rtt.ToMicroseconds());
- }
- state_machine_->set_rtt(smoothed_rtt_);
-}
-
-void InterArrivalSender::OnPacketLost(
- QuicPacketSequenceNumber /*sequence_number*/,
- QuicTime ack_receive_time) {
- // Packet loss was reported.
- if (!probing_) {
- if (!state_machine_->PacketLossEvent()) {
- // Less than one RTT since last PacketLossEvent.
- return;
- }
- // Calculate new pace rate.
- EstimateBandwidthAfterLossEvent(ack_receive_time);
- }
-}
-
-bool InterArrivalSender::OnPacketSent(
- QuicTime sent_time,
- QuicPacketSequenceNumber sequence_number,
- QuicByteCount bytes,
- TransmissionType /*transmission_type*/,
- HasRetransmittableData /*has_retransmittable_data*/) {
- if (probing_) {
- probe_->OnPacketSent(bytes);
- }
- paced_sender_->OnPacketSent(sent_time, bytes);
- return true;
-}
-
-void InterArrivalSender::OnRetransmissionTimeout() {
- // TODO(ianswett): Decrease the available bandwidth.
-}
-
-void InterArrivalSender::OnPacketAbandoned(
- QuicPacketSequenceNumber /*sequence_number*/,
- QuicByteCount abandoned_bytes) {
- // TODO(pwestin): use for out outer_congestion_window_ logic.
- if (probing_) {
- probe_->OnAcknowledgedPacket(abandoned_bytes);
- }
-}
-
-QuicTime::Delta InterArrivalSender::TimeUntilSend(
- QuicTime now,
- TransmissionType /*transmission_type*/,
- HasRetransmittableData has_retransmittable_data,
- IsHandshake /*handshake*/) {
- // TODO(pwestin): implement outer_congestion_window_ logic.
- QuicTime::Delta outer_window = QuicTime::Delta::Zero();
-
- if (probing_) {
- if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA &&
- probe_->GetAvailableCongestionWindow() == 0) {
- outer_window = QuicTime::Delta::Infinite();
- }
- }
- return paced_sender_->TimeUntilSend(now, outer_window);
-}
-
-void InterArrivalSender::EstimateDelayBandwidth(QuicTime feedback_receive_time,
- QuicBandwidth sent_bandwidth) {
- QuicTime::Delta estimated_congestion_delay = QuicTime::Delta::Zero();
- BandwidthUsage new_bandwidth_usage_state =
- overuse_detector_->GetState(&estimated_congestion_delay);
-
- switch (new_bandwidth_usage_state) {
- case kBandwidthDraining:
- case kBandwidthUnderUsing:
- // Hold our current bitrate.
- break;
- case kBandwidthOverUsing:
- if (!state_machine_->IncreasingDelayEvent()) {
- // Less than one RTT since last IncreasingDelayEvent.
- return;
- }
- EstimateBandwidthAfterDelayEvent(feedback_receive_time,
- estimated_congestion_delay);
- break;
- case kBandwidthSteady:
- // Calculate new pace rate.
- if (bandwidth_usage_state_ == kBandwidthDraining ||
- bandwidth_usage_state_ == kBandwidthOverUsing) {
- EstimateNewBandwidthAfterDraining(feedback_receive_time,
- estimated_congestion_delay);
- } else {
- EstimateNewBandwidth(feedback_receive_time, sent_bandwidth);
- }
- break;
- }
- bandwidth_usage_state_ = new_bandwidth_usage_state;
-}
-
-QuicBandwidth InterArrivalSender::BandwidthEstimate() const {
- return current_bandwidth_;
-}
-
-QuicTime::Delta InterArrivalSender::SmoothedRtt() const {
- if (smoothed_rtt_.IsZero()) {
- return QuicTime::Delta::FromMilliseconds(kInitialRttMs);
- }
- return smoothed_rtt_;
-}
-
-QuicTime::Delta InterArrivalSender::RetransmissionDelay() const {
- // TODO(pwestin): Calculate and return retransmission delay.
- // Use 2 * the smoothed RTT for now.
- return smoothed_rtt_.Add(smoothed_rtt_);
-}
-
-QuicByteCount InterArrivalSender::GetCongestionWindow() const {
- return 0;
-}
-
-void InterArrivalSender::EstimateNewBandwidth(QuicTime feedback_receive_time,
- QuicBandwidth sent_bandwidth) {
- QuicBandwidth new_bandwidth = bitrate_ramp_up_->GetNewBitrate(sent_bandwidth);
- if (current_bandwidth_ == new_bandwidth) {
- return;
- }
- current_bandwidth_ = new_bandwidth;
- state_machine_->IncreaseBitrateDecision();
-
- QuicBandwidth channel_estimate = QuicBandwidth::Zero();
- ChannelEstimateState channel_estimator_state =
- channel_estimator_->GetChannelEstimate(&channel_estimate);
-
- if (channel_estimator_state == kChannelEstimateGood) {
- bitrate_ramp_up_->UpdateChannelEstimate(channel_estimate);
- }
- paced_sender_->UpdateBandwidthEstimate(feedback_receive_time,
- current_bandwidth_);
- DVLOG(1) << "New bandwidth estimate in steady state:"
- << current_bandwidth_.ToKBitsPerSecond()
- << " Kbits/s";
-}
-
-// Did we drain the network buffers in our expected pace?
-void InterArrivalSender::EstimateNewBandwidthAfterDraining(
- QuicTime feedback_receive_time,
- QuicTime::Delta estimated_congestion_delay) {
- if (current_bandwidth_ > back_down_bandwidth_) {
- // Do nothing, our current bandwidth is higher than our bandwidth at the
- // previous back down.
- DVLOG(1) << "Current bandwidth estimate is higher than before draining";
- return;
- }
- if (estimated_congestion_delay >= back_down_congestion_delay_) {
- // Do nothing, our estimated delay have increased.
- DVLOG(1) << "Current delay estimate is higher than before draining";
- return;
- }
- DCHECK(back_down_time_.IsInitialized());
- QuicTime::Delta buffer_reduction =
- back_down_congestion_delay_.Subtract(estimated_congestion_delay);
- QuicTime::Delta elapsed_time =
- feedback_receive_time.Subtract(back_down_time_).Subtract(SmoothedRtt());
-
- QuicBandwidth new_estimate = QuicBandwidth::Zero();
- if (buffer_reduction >= elapsed_time) {
- // We have drained more than the elapsed time... go back to our old rate.
- new_estimate = back_down_bandwidth_;
- } else {
- float fraction_of_rate =
- static_cast<float>(buffer_reduction.ToMicroseconds()) /
- elapsed_time.ToMicroseconds(); // < 1.0
-
- QuicBandwidth draining_rate = back_down_bandwidth_.Scale(fraction_of_rate);
- QuicBandwidth max_estimated_draining_rate =
- back_down_bandwidth_.Subtract(current_bandwidth_);
- if (draining_rate > max_estimated_draining_rate) {
- // We drained faster than our old send rate, go back to our old rate.
- new_estimate = back_down_bandwidth_;
- } else {
- // Use our drain rate and our kMinBitrateReduction to go to our
- // new estimate.
- new_estimate = std::max(current_bandwidth_,
- current_bandwidth_.Add(draining_rate).Scale(
- 1.0f - kMinBitrateReduction));
- DVLOG(1) << "Draining calculation; current rate:"
- << current_bandwidth_.ToKBitsPerSecond() << " Kbits/s "
- << "draining rate:"
- << draining_rate.ToKBitsPerSecond() << " Kbits/s "
- << "new estimate:"
- << new_estimate.ToKBitsPerSecond() << " Kbits/s "
- << " buffer reduction:"
- << buffer_reduction.ToMicroseconds() << " us "
- << " elapsed time:"
- << elapsed_time.ToMicroseconds() << " us ";
- }
- }
- if (new_estimate == current_bandwidth_) {
- return;
- }
-
- QuicBandwidth channel_estimate = QuicBandwidth::Zero();
- ChannelEstimateState channel_estimator_state =
- channel_estimator_->GetChannelEstimate(&channel_estimate);
-
- // TODO(pwestin): we need to analyze channel_estimate too.
- switch (channel_estimator_state) {
- case kChannelEstimateUnknown:
- channel_estimate = current_bandwidth_;
- break;
- case kChannelEstimateUncertain:
- channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin);
- break;
- case kChannelEstimateGood:
- // Do nothing, estimate is accurate.
- break;
- }
- bitrate_ramp_up_->Reset(new_estimate, back_down_bandwidth_, channel_estimate);
- state_machine_->IncreaseBitrateDecision();
- paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_estimate);
- current_bandwidth_ = new_estimate;
- DVLOG(1) << "New bandwidth estimate after draining:"
- << new_estimate.ToKBitsPerSecond() << " Kbits/s";
-}
-
-void InterArrivalSender::EstimateBandwidthAfterDelayEvent(
- QuicTime feedback_receive_time,
- QuicTime::Delta estimated_congestion_delay) {
- QuicByteCount estimated_byte_buildup =
- current_bandwidth_.ToBytesPerPeriod(estimated_congestion_delay);
-
- // To drain all build up buffer within one RTT we need to reduce the
- // bitrate with the following.
- // TODO(pwestin): this is a crude first implementation.
- int64 draining_rate_per_rtt = (estimated_byte_buildup *
- kNumMicrosPerSecond) / SmoothedRtt().ToMicroseconds();
-
- float decrease_factor =
- draining_rate_per_rtt / current_bandwidth_.ToBytesPerSecond();
-
- decrease_factor = std::max(decrease_factor, kMinBitrateReduction);
- decrease_factor = std::min(decrease_factor, kMaxBitrateReduction);
- back_down_congestion_delay_ = estimated_congestion_delay;
- QuicBandwidth new_target_bitrate =
- current_bandwidth_.Scale(1.0f - decrease_factor);
-
- // While in delay sensing mode send at least one packet per RTT.
- QuicBandwidth min_delay_bitrate =
- QuicBandwidth::FromBytesAndTimeDelta(max_segment_size_, SmoothedRtt());
- new_target_bitrate = std::max(new_target_bitrate, min_delay_bitrate);
-
- ResetCurrentBandwidth(feedback_receive_time, new_target_bitrate);
-
- DVLOG(1) << "New bandwidth estimate after delay event:"
- << current_bandwidth_.ToKBitsPerSecond()
- << " Kbits/s min delay bitrate:"
- << min_delay_bitrate.ToKBitsPerSecond()
- << " Kbits/s RTT:"
- << SmoothedRtt().ToMicroseconds()
- << " us";
-}
-
-void InterArrivalSender::EstimateBandwidthAfterLossEvent(
- QuicTime feedback_receive_time) {
- ResetCurrentBandwidth(feedback_receive_time,
- current_bandwidth_.Scale(kPacketLossBitrateReduction));
- DVLOG(1) << "New bandwidth estimate after loss event:"
- << current_bandwidth_.ToKBitsPerSecond()
- << " Kbits/s";
-}
-
-void InterArrivalSender::ResetCurrentBandwidth(QuicTime feedback_receive_time,
- QuicBandwidth new_rate) {
- new_rate = std::max(new_rate,
- QuicBandwidth::FromKBitsPerSecond(kMinBitrateKbit));
- QuicBandwidth channel_estimate = QuicBandwidth::Zero();
- ChannelEstimateState channel_estimator_state =
- channel_estimator_->GetChannelEstimate(&channel_estimate);
-
- switch (channel_estimator_state) {
- case kChannelEstimateUnknown:
- channel_estimate = current_bandwidth_;
- break;
- case kChannelEstimateUncertain:
- channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin);
- break;
- case kChannelEstimateGood:
- // Do nothing.
- break;
- }
- back_down_time_ = feedback_receive_time;
- back_down_bandwidth_ = current_bandwidth_;
- bitrate_ramp_up_->Reset(new_rate, current_bandwidth_, channel_estimate);
- if (new_rate != current_bandwidth_) {
- current_bandwidth_ = new_rate;
- paced_sender_->UpdateBandwidthEstimate(feedback_receive_time,
- current_bandwidth_);
- state_machine_->DecreaseBitrateDecision();
- }
-}
-
-} // namespace net