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.
5 #include "net/quic/congestion_control/inter_arrival_probe.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
17 const int kProbeSizePackets = 10;
18 const QuicByteCount kMinPacketSize = 500;
19 const int64 kDefaultBytesPerSecond = 40000;
20 const float kUncertainScaleFactor = 0.5; // TODO(pwestin): revisit this factor.
23 InterArrivalProbe::InterArrivalProbe(QuicByteCount max_segment_size)
24 : max_segment_size_(max_segment_size),
25 estimate_available_(false),
26 available_channel_estimate_(QuicBandwidth::Zero()),
30 InterArrivalProbe::~InterArrivalProbe() {
33 bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) {
34 if (!estimate_available_) {
37 *available_channel_estimate = available_channel_estimate_;
41 void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) {
42 if (!estimate_available_) {
43 unacked_data_ += bytes;
47 void InterArrivalProbe::OnAcknowledgedPacket(QuicByteCount bytes) {
48 if (!estimate_available_) {
49 DCHECK_LE(bytes, unacked_data_);
50 unacked_data_ -= bytes;
54 void InterArrivalProbe::OnRetransmissionTimeout() {
55 if (!estimate_available_) {
60 QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() {
61 if (estimate_available_) {
64 return (kProbeSizePackets * max_segment_size_) - unacked_data_;
67 void InterArrivalProbe::OnIncomingFeedback(
68 QuicPacketSequenceNumber sequence_number,
69 QuicByteCount bytes_sent,
71 QuicTime time_received) {
72 if (estimate_available_) {
76 if (available_channel_estimator_.get() == NULL) {
77 if (bytes_sent < kMinPacketSize) {
78 // Packet too small to start the probe phase.
81 first_sequence_number_ = sequence_number;
82 available_channel_estimator_.reset(new AvailableChannelEstimator(
83 sequence_number, time_sent, time_received));
87 available_channel_estimator_->OnIncomingFeedback(sequence_number,
91 if (sequence_number < kProbeSizePackets - 1 + first_sequence_number_) {
92 // We need more feedback before we have a probe estimate.
95 // Get the current estimated available channel capacity.
96 // available_channel_estimate is invalid if kAvailableChannelEstimateUnknown
98 QuicBandwidth available_channel_estimate = QuicBandwidth::Zero();
99 AvailableChannelEstimateState available_channel_estimate_state =
100 available_channel_estimator_->GetAvailableChannelEstimate(
101 &available_channel_estimate);
102 switch (available_channel_estimate_state) {
103 case kAvailableChannelEstimateUnknown:
104 // Backup when we miss our probe.
105 available_channel_estimate_ =
106 QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond);
108 case kAvailableChannelEstimateUncertain:
109 available_channel_estimate_ =
110 available_channel_estimate.Scale(kUncertainScaleFactor);
112 case kAvailableChannelEstimateGood:
113 available_channel_estimate_ = available_channel_estimate;
115 case kAvailableChannelEstimateSenderLimited:
116 available_channel_estimate_ =
117 max(available_channel_estimate,
118 QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond));
121 estimate_available_ = true;
122 available_channel_estimator_.reset(NULL);
123 DVLOG(1) << "Probe estimate:"
124 << available_channel_estimate_.ToKBitsPerSecond()