summaryrefslogtreecommitdiff
path: root/chromium/net/quic/congestion_control/pacing_sender.cc
blob: a20e7522750139adf8d458db246dcebdaa7dcdfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// 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)
    : sender_(sender),
      alarm_granularity_(alarm_granularity),
      next_packet_send_time_(QuicTime::Zero()),
      was_last_send_delayed_(false),
      max_segment_size_(kDefaultMaxPacketSize) {
}

PacingSender::~PacingSender() {}

void PacingSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
  max_segment_size_ = max_packet_size;
  sender_->SetMaxPacketSize(max_packet_size);
}

void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server) {
  sender_->SetFromConfig(config, is_server);
}

void PacingSender::OnIncomingQuicCongestionFeedbackFrame(
      const QuicCongestionFeedbackFrame& feedback,
      QuicTime feedback_receive_time,
      const SendAlgorithmInterface::SentPacketsMap& sent_packets) {
  sender_->OnIncomingQuicCongestionFeedbackFrame(
      feedback, feedback_receive_time, sent_packets);
}

void PacingSender::OnPacketAcked(
    QuicPacketSequenceNumber acked_sequence_number,
    QuicByteCount acked_bytes,
    QuicTime::Delta rtt) {
  sender_->OnPacketAcked(acked_sequence_number, acked_bytes, rtt);
}

void PacingSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
                                QuicTime ack_receive_time) {
  sender_->OnPacketLost(sequence_number, ack_receive_time);
}

bool PacingSender::OnPacketSent(
    QuicTime sent_time,
    QuicPacketSequenceNumber sequence_number,
    QuicByteCount bytes,
    TransmissionType transmission_type,
    HasRetransmittableData has_retransmittable_data) {
  // Only pace data packets.
  if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
    // The next packet should be sent as soon as the current packets has
    // been transferred.  We pace at twice the rate of the underlying
    // sender's bandwidth estimate to help ensure that pacing doesn't become
    // a bottleneck.
    const float kPacingAggression = 2;
    QuicTime::Delta delay =
        BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
    next_packet_send_time_ = next_packet_send_time_.Add(delay);
  }
  return sender_->OnPacketSent(sent_time, sequence_number, bytes,
                               transmission_type, has_retransmittable_data);
}

void PacingSender::OnRetransmissionTimeout() {
  sender_->OnRetransmissionTimeout();
}

void PacingSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
                                     QuicByteCount abandoned_bytes) {
  sender_->OnPacketAbandoned(sequence_number, abandoned_bytes);
}

QuicTime::Delta PacingSender::TimeUntilSend(
      QuicTime now,
      TransmissionType transmission_type,
      HasRetransmittableData has_retransmittable_data,
      IsHandshake handshake) {
  QuicTime::Delta time_until_send =
      sender_->TimeUntilSend(now, transmission_type,
                             has_retransmittable_data, handshake);
  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 (!was_last_send_delayed_ &&
      (!next_packet_send_time_.IsInitialized() ||
       now > next_packet_send_time_.Add(alarm_granularity_))) {
    // An alarm did not go off late, instead the application is "slow"
    // delivering data.  In this case, we restrict the amount of lost time
    // that we can make up for.
    next_packet_send_time_ = now.Subtract(alarm_granularity_);
  }

  // If the end of the epoch is far enough in the future, delay the send.
  if (next_packet_send_time_ > now.Add(alarm_granularity_)) {
    was_last_send_delayed_ = true;
    DVLOG(1) << "Delaying packet: "
             << next_packet_send_time_.Subtract(now).ToMicroseconds();
    return next_packet_send_time_.Subtract(now);
  }

  // Sent it immediately.  The epoch end will be adjusted in OnPacketSent.
  was_last_send_delayed_ = false;
  DVLOG(1) << "Sending packet now";
  return QuicTime::Delta::Zero();
}

QuicBandwidth PacingSender::BandwidthEstimate() const {
  return sender_->BandwidthEstimate();
}

QuicTime::Delta PacingSender::SmoothedRtt() const {
  return sender_->SmoothedRtt();
}

QuicTime::Delta PacingSender::RetransmissionDelay() const {
  return sender_->RetransmissionDelay();
}

QuicByteCount PacingSender::GetCongestionWindow() const {
  return sender_->GetCongestionWindow();
}

}  // namespace net