blob: 5acb5a02a1923ef512199a5e8ae0ed941ba62c27 [file] [log] [blame]
// Copyright (c) 2012 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/paced_sender.h"
#include "base/time.h"
#include "net/quic/quic_protocol.h"
namespace net {
// To prevent too aggressive pacing we allow the following packet burst size.
const size_t kMinPacketBurstSize = 2;
// Max estimated time between calls to TimeUntilSend and
// AvailableCongestionWindow.
const int64 kMaxSchedulingDelayUs = 2000;
PacedSender::PacedSender(const QuicClock* clock, int bytes_per_s)
: leaky_bucket_(clock, bytes_per_s),
pace_in_bytes_per_s_(bytes_per_s) {
}
void PacedSender::UpdateBandwidthEstimate(int bytes_per_s) {
leaky_bucket_.SetDrainingRate(bytes_per_s);
pace_in_bytes_per_s_ = bytes_per_s;
}
void PacedSender::SentPacket(size_t bytes) {
leaky_bucket_.Add(bytes);
}
QuicTime::Delta PacedSender::TimeUntilSend(QuicTime::Delta time_until_send) {
if (time_until_send.ToMicroseconds() >= kMaxSchedulingDelayUs) {
return time_until_send;
}
// Pace the data.
size_t pacing_window = kMaxSchedulingDelayUs * pace_in_bytes_per_s_ /
base::Time::kMicrosecondsPerSecond;
size_t min_window_size = kMinPacketBurstSize * kMaxPacketSize;
pacing_window = std::max(pacing_window, min_window_size);
if (pacing_window > leaky_bucket_.BytesPending()) {
// We have not filled our pacing window yet.
return time_until_send;
}
return leaky_bucket_.TimeRemaining();
}
size_t PacedSender::AvailableWindow(size_t available_congestion_window) {
size_t accuracy_window = (kMaxSchedulingDelayUs * pace_in_bytes_per_s_) /
base::Time::kMicrosecondsPerSecond;
size_t min_burst_window = kMinPacketBurstSize * kMaxPacketSize;
DVLOG(1) << "Available congestion window:" << available_congestion_window
<< " accuracy window:" << accuracy_window
<< " min burst window:" << min_burst_window;
// Should we limit the window to pace the data?
if (available_congestion_window > min_burst_window &&
available_congestion_window > accuracy_window) {
// Max window depends on estimated bandwidth; higher bandwidth => larger
// burst we also consider our timing accuracy. An accuracy of 1 ms will
// allow us to send up to 19.2Mbit/s with 2 packets per burst.
available_congestion_window = std::max(min_burst_window, accuracy_window);
size_t bytes_pending = leaky_bucket_.BytesPending();
if (bytes_pending > available_congestion_window) {
return 0;
}
available_congestion_window -= bytes_pending;
}
return available_congestion_window;
}
} // namespace net