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