// 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/pacing_sender.h" namespace net { PacingSender::PacingSender(SendAlgorithmInterface* sender, QuicTime::Delta alarm_granularity, uint32 initial_packet_burst) : sender_(sender), alarm_granularity_(alarm_granularity), initial_packet_burst_(initial_packet_burst), burst_tokens_(initial_packet_burst), last_delayed_packet_sent_time_(QuicTime::Zero()), ideal_next_packet_send_time_(QuicTime::Zero()), was_last_send_delayed_(false) { } PacingSender::~PacingSender() {} void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server, bool using_pacing) { DCHECK(using_pacing); sender_->SetFromConfig(config, is_server, using_pacing); } bool PacingSender::ResumeConnectionState( const CachedNetworkParameters& cached_network_params) { return sender_->ResumeConnectionState(cached_network_params); } void PacingSender::SetNumEmulatedConnections(int num_connections) { sender_->SetNumEmulatedConnections(num_connections); } void PacingSender::OnCongestionEvent(bool rtt_updated, QuicByteCount bytes_in_flight, const CongestionVector& acked_packets, const CongestionVector& lost_packets) { sender_->OnCongestionEvent( rtt_updated, bytes_in_flight, acked_packets, lost_packets); } bool PacingSender::OnPacketSent( QuicTime sent_time, QuicByteCount bytes_in_flight, QuicPacketSequenceNumber sequence_number, QuicByteCount bytes, HasRetransmittableData has_retransmittable_data) { const bool in_flight = sender_->OnPacketSent(sent_time, bytes_in_flight, sequence_number, bytes, has_retransmittable_data); if (has_retransmittable_data != HAS_RETRANSMITTABLE_DATA) { return in_flight; } if (bytes_in_flight == 0) { // Add more burst tokens anytime the connection is leaving quiescence. burst_tokens_ = initial_packet_burst_; } if (burst_tokens_ > 0) { --burst_tokens_; was_last_send_delayed_ = false; last_delayed_packet_sent_time_ = QuicTime::Zero(); ideal_next_packet_send_time_ = QuicTime::Zero(); return in_flight; } // The next packet should be sent as soon as the current packets has been // transferred. QuicTime::Delta delay = PacingRate().TransferTime(bytes); // If the last send was delayed, and the alarm took a long time to get // invoked, allow the connection to make up for lost time. if (was_last_send_delayed_) { ideal_next_packet_send_time_ = ideal_next_packet_send_time_.Add(delay); // The send was application limited if it takes longer than the // pacing delay between sent packets. const bool application_limited = last_delayed_packet_sent_time_.IsInitialized() && sent_time > last_delayed_packet_sent_time_.Add(delay); const bool making_up_for_lost_time = ideal_next_packet_send_time_ <= sent_time; // As long as we're making up time and not application limited, // continue to consider the packets delayed, allowing the packets to be // sent immediately. if (making_up_for_lost_time && !application_limited) { last_delayed_packet_sent_time_ = sent_time; } else { was_last_send_delayed_ = false; last_delayed_packet_sent_time_ = QuicTime::Zero(); } } else { ideal_next_packet_send_time_ = QuicTime::Max( ideal_next_packet_send_time_.Add(delay), sent_time.Add(delay)); } return in_flight; } void PacingSender::OnRetransmissionTimeout(bool packets_retransmitted) { sender_->OnRetransmissionTimeout(packets_retransmitted); } void PacingSender::RevertRetransmissionTimeout() { sender_->RevertRetransmissionTimeout(); } QuicTime::Delta PacingSender::TimeUntilSend( QuicTime now, QuicByteCount bytes_in_flight, HasRetransmittableData has_retransmittable_data) const { QuicTime::Delta time_until_send = sender_->TimeUntilSend(now, bytes_in_flight, has_retransmittable_data); if (burst_tokens_ > 0 || bytes_in_flight == 0) { // Don't pace if we have burst tokens available or leaving quiescence. return time_until_send; } if (!time_until_send.IsZero()) { DCHECK(time_until_send.IsInfinite()); // The underlying sender prevents sending. return time_until_send; } if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { // Don't pace ACK packets, since they do not count against CWND and do not // cause CWND to grow. return QuicTime::Delta::Zero(); } // If the next send time is within the alarm granularity, send immediately. if (ideal_next_packet_send_time_ > now.Add(alarm_granularity_)) { DVLOG(1) << "Delaying packet: " << ideal_next_packet_send_time_.Subtract(now).ToMicroseconds(); was_last_send_delayed_ = true; return ideal_next_packet_send_time_.Subtract(now); } DVLOG(1) << "Sending packet now"; return QuicTime::Delta::Zero(); } QuicBandwidth PacingSender::PacingRate() const { return sender_->PacingRate(); } QuicBandwidth PacingSender::BandwidthEstimate() const { return sender_->BandwidthEstimate(); } bool PacingSender::HasReliableBandwidthEstimate() const { return sender_->HasReliableBandwidthEstimate(); } QuicTime::Delta PacingSender::RetransmissionDelay() const { return sender_->RetransmissionDelay(); } QuicByteCount PacingSender::GetCongestionWindow() const { return sender_->GetCongestionWindow(); } bool PacingSender::InSlowStart() const { return sender_->InSlowStart(); } bool PacingSender::InRecovery() const { return sender_->InRecovery(); } QuicByteCount PacingSender::GetSlowStartThreshold() const { return sender_->GetSlowStartThreshold(); } CongestionControlType PacingSender::GetCongestionControlType() const { return sender_->GetCongestionControlType(); } } // namespace net