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/inter_arrival_probe.h" 6 7#include "base/basictypes.h" 8#include "base/logging.h" 9 10namespace { 11const int kProbeSizePackets = 10; 12const net::QuicByteCount kMinPacketSize = 500; 13const int64 kDefaultBytesPerSecond = 40000; 14const float kUncertainScaleFactor = 0.5; // TODO(pwestin): revisit this factor. 15} 16 17namespace net { 18 19InterArrivalProbe::InterArrivalProbe(QuicByteCount max_segment_size) 20 : max_segment_size_(max_segment_size), 21 estimate_available_(false), 22 available_channel_estimate_(QuicBandwidth::Zero()), 23 unacked_data_(0) { 24} 25 26InterArrivalProbe::~InterArrivalProbe() { 27} 28 29void InterArrivalProbe::set_max_segment_size(QuicByteCount max_segment_size) { 30 max_segment_size_ = max_segment_size; 31} 32 33bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) { 34 if (!estimate_available_) { 35 return false; 36 } 37 *available_channel_estimate = available_channel_estimate_; 38 return true; 39} 40 41void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) { 42 if (!estimate_available_) { 43 unacked_data_ += bytes; 44 } 45} 46 47void InterArrivalProbe::OnAcknowledgedPacket(QuicByteCount bytes) { 48 if (!estimate_available_) { 49 DCHECK_LE(bytes, unacked_data_); 50 unacked_data_ -= bytes; 51 } 52} 53 54QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() { 55 if (estimate_available_) { 56 return 0; 57 } 58 return (kProbeSizePackets * max_segment_size_) - unacked_data_; 59} 60 61void InterArrivalProbe::OnIncomingFeedback( 62 QuicPacketSequenceNumber sequence_number, 63 QuicByteCount bytes_sent, 64 QuicTime time_sent, 65 QuicTime time_received) { 66 if (estimate_available_) { 67 return; 68 } 69 70 if (available_channel_estimator_.get() == NULL) { 71 if (bytes_sent < kMinPacketSize) { 72 // Packet too small to start the probe phase. 73 return; 74 } 75 first_sequence_number_ = sequence_number; 76 available_channel_estimator_.reset(new AvailableChannelEstimator( 77 sequence_number, time_sent, time_received)); 78 return; 79 } 80 81 available_channel_estimator_->OnIncomingFeedback(sequence_number, 82 bytes_sent, 83 time_sent, 84 time_received); 85 if (sequence_number < kProbeSizePackets - 1 + first_sequence_number_) { 86 // We need more feedback before we have a probe estimate. 87 return; 88 } 89 // Get the current estimated available channel capacity. 90 // available_channel_estimate is invalid if kAvailableChannelEstimateUnknown 91 // is returned. 92 QuicBandwidth available_channel_estimate = QuicBandwidth::Zero(); 93 AvailableChannelEstimateState available_channel_estimate_state = 94 available_channel_estimator_->GetAvailableChannelEstimate( 95 &available_channel_estimate); 96 switch (available_channel_estimate_state) { 97 case kAvailableChannelEstimateUnknown: 98 // Backup when we miss our probe. 99 available_channel_estimate_ = 100 QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond); 101 break; 102 case kAvailableChannelEstimateUncertain: 103 available_channel_estimate_ = 104 available_channel_estimate.Scale(kUncertainScaleFactor); 105 break; 106 case kAvailableChannelEstimateGood: 107 available_channel_estimate_ = available_channel_estimate; 108 break; 109 case kAvailableChannelEstimateSenderLimited: 110 available_channel_estimate_ = 111 std::max(available_channel_estimate, 112 QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond)); 113 break; 114 } 115 estimate_available_ = true; 116 available_channel_estimator_.reset(NULL); 117 DVLOG(1) << "Probe estimate:" 118 << available_channel_estimate_.ToKBitsPerSecond() 119 << " Kbits/s"; 120} 121 122} // namespace net 123