• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/quic/congestion_control/pacing_sender.h"
6 
7 namespace net {
8 
PacingSender(SendAlgorithmInterface * sender,QuicTime::Delta alarm_granularity,uint32 initial_packet_burst)9 PacingSender::PacingSender(SendAlgorithmInterface* sender,
10                            QuicTime::Delta alarm_granularity,
11                            uint32 initial_packet_burst)
12     : sender_(sender),
13       alarm_granularity_(alarm_granularity),
14       initial_packet_burst_(initial_packet_burst),
15       burst_tokens_(initial_packet_burst),
16       last_delayed_packet_sent_time_(QuicTime::Zero()),
17       next_packet_send_time_(QuicTime::Zero()),
18       was_last_send_delayed_(false),
19       has_valid_rtt_(false) {
20 }
21 
~PacingSender()22 PacingSender::~PacingSender() {}
23 
SetFromConfig(const QuicConfig & config,bool is_server)24 void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server) {
25   // TODO(ianswett): Consider using the suggested RTT for pacing an initial
26   // response.
27   sender_->SetFromConfig(config, is_server);
28 }
29 
OnIncomingQuicCongestionFeedbackFrame(const QuicCongestionFeedbackFrame & feedback,QuicTime feedback_receive_time)30 void PacingSender::OnIncomingQuicCongestionFeedbackFrame(
31       const QuicCongestionFeedbackFrame& feedback,
32       QuicTime feedback_receive_time) {
33   sender_->OnIncomingQuicCongestionFeedbackFrame(
34       feedback, feedback_receive_time);
35 }
36 
OnCongestionEvent(bool rtt_updated,QuicByteCount bytes_in_flight,const CongestionVector & acked_packets,const CongestionVector & lost_packets)37 void PacingSender::OnCongestionEvent(bool rtt_updated,
38                                      QuicByteCount bytes_in_flight,
39                                      const CongestionVector& acked_packets,
40                                      const CongestionVector& lost_packets) {
41   if (rtt_updated) {
42     has_valid_rtt_ = true;
43   }
44   sender_->OnCongestionEvent(
45       rtt_updated, bytes_in_flight, acked_packets, lost_packets);
46 }
47 
OnPacketSent(QuicTime sent_time,QuicByteCount bytes_in_flight,QuicPacketSequenceNumber sequence_number,QuicByteCount bytes,HasRetransmittableData has_retransmittable_data)48 bool PacingSender::OnPacketSent(
49     QuicTime sent_time,
50     QuicByteCount bytes_in_flight,
51     QuicPacketSequenceNumber sequence_number,
52     QuicByteCount bytes,
53     HasRetransmittableData has_retransmittable_data) {
54   // Only pace data packets once we have an updated RTT.
55   const bool in_flight =
56       sender_->OnPacketSent(sent_time, bytes_in_flight, sequence_number,
57                             bytes, has_retransmittable_data);
58   if (has_retransmittable_data != HAS_RETRANSMITTABLE_DATA || !has_valid_rtt_) {
59     return in_flight;
60   }
61   if (burst_tokens_ > 0) {
62     --burst_tokens_;
63     was_last_send_delayed_ = false;
64     last_delayed_packet_sent_time_ = QuicTime::Zero();
65     next_packet_send_time_ = QuicTime::Zero();
66     return in_flight;
67   }
68   // The next packet should be sent as soon as the current packets has
69   // been transferred.  We pace at twice the rate of the underlying
70   // sender's bandwidth estimate during slow start and 1.25x during congestion
71   // avoidance to ensure pacing doesn't prevent us from filling the window.
72   const float kPacingAggression = sender_->InSlowStart() ? 2 : 1.25;
73   QuicTime::Delta delay =
74       BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
75   // If the last send was delayed, and the alarm took a long time to get
76   // invoked, allow the connection to make up for lost time.
77   if (was_last_send_delayed_) {
78     next_packet_send_time_ = next_packet_send_time_.Add(delay);
79     // The send was application limited if it takes longer than the
80     // pacing delay between sent packets.
81     const bool application_limited =
82         last_delayed_packet_sent_time_.IsInitialized() &&
83         sent_time > last_delayed_packet_sent_time_.Add(delay);
84     const bool making_up_for_lost_time = next_packet_send_time_ <= sent_time;
85     // As long as we're making up time and not application limited,
86     // continue to consider the packets delayed, allowing the packets to be
87     // sent immediately.
88     if (making_up_for_lost_time && !application_limited) {
89       last_delayed_packet_sent_time_ = sent_time;
90     } else {
91       was_last_send_delayed_ = false;
92       last_delayed_packet_sent_time_ = QuicTime::Zero();
93     }
94   } else {
95     next_packet_send_time_ =
96         QuicTime::Max(next_packet_send_time_.Add(delay),
97                       sent_time.Add(delay).Subtract(alarm_granularity_));
98   }
99   return in_flight;
100 }
101 
OnRetransmissionTimeout(bool packets_retransmitted)102 void PacingSender::OnRetransmissionTimeout(bool packets_retransmitted) {
103   sender_->OnRetransmissionTimeout(packets_retransmitted);
104 }
105 
RevertRetransmissionTimeout()106 void PacingSender::RevertRetransmissionTimeout() {
107   sender_->RevertRetransmissionTimeout();
108 }
109 
TimeUntilSend(QuicTime now,QuicByteCount bytes_in_flight,HasRetransmittableData has_retransmittable_data) const110 QuicTime::Delta PacingSender::TimeUntilSend(
111       QuicTime now,
112       QuicByteCount bytes_in_flight,
113       HasRetransmittableData has_retransmittable_data) const {
114   QuicTime::Delta time_until_send =
115       sender_->TimeUntilSend(now, bytes_in_flight, has_retransmittable_data);
116   if (!has_valid_rtt_) {
117     // Don't pace if we don't have an updated RTT estimate.
118     return time_until_send;
119   }
120   if (bytes_in_flight == 0) {
121     // Add more burst tokens anytime the connection is entering quiescence.
122     burst_tokens_ = initial_packet_burst_;
123   }
124   if (burst_tokens_ > 0) {
125     // Don't pace if we have burst tokens available.
126     return time_until_send;
127   }
128 
129   if (!time_until_send.IsZero()) {
130     DCHECK(time_until_send.IsInfinite());
131     // The underlying sender prevents sending.
132     return time_until_send;
133   }
134 
135   if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
136     // Don't pace ACK packets, since they do not count against CWND and do not
137     // cause CWND to grow.
138     return QuicTime::Delta::Zero();
139   }
140 
141   // If the next send time is within the alarm granularity, send immediately.
142   if (next_packet_send_time_ > now.Add(alarm_granularity_)) {
143     DVLOG(1) << "Delaying packet: "
144              << next_packet_send_time_.Subtract(now).ToMicroseconds();
145     was_last_send_delayed_ = true;
146     return next_packet_send_time_.Subtract(now);
147   }
148 
149   DVLOG(1) << "Sending packet now";
150   return QuicTime::Delta::Zero();
151 }
152 
BandwidthEstimate() const153 QuicBandwidth PacingSender::BandwidthEstimate() const {
154   return sender_->BandwidthEstimate();
155 }
156 
HasReliableBandwidthEstimate() const157 bool PacingSender::HasReliableBandwidthEstimate() const {
158   return sender_->HasReliableBandwidthEstimate();
159 }
160 
RetransmissionDelay() const161 QuicTime::Delta PacingSender::RetransmissionDelay() const {
162   return sender_->RetransmissionDelay();
163 }
164 
GetCongestionWindow() const165 QuicByteCount PacingSender::GetCongestionWindow() const {
166   return sender_->GetCongestionWindow();
167 }
168 
InSlowStart() const169 bool PacingSender::InSlowStart() const {
170   return sender_->InSlowStart();
171 }
172 
InRecovery() const173 bool PacingSender::InRecovery() const {
174   return sender_->InRecovery();
175 }
176 
GetSlowStartThreshold() const177 QuicByteCount PacingSender::GetSlowStartThreshold() const {
178   return sender_->GetSlowStartThreshold();
179 }
180 
GetCongestionControlType() const181 CongestionControlType PacingSender::GetCongestionControlType() const {
182   return sender_->GetCongestionControlType();
183 }
184 
185 }  // namespace net
186