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(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 26 InterArrivalProbe::~InterArrivalProbe() { 27 } 28 29 void InterArrivalProbe::set_max_segment_size(QuicByteCount max_segment_size) { 30 max_segment_size_ = max_segment_size; 31 } 32 33 bool 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 41 void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) { 42 if (!estimate_available_) { 43 unacked_data_ += bytes; 44 } 45 } 46 47 void InterArrivalProbe::OnAcknowledgedPacket(QuicByteCount bytes) { 48 if (!estimate_available_) { 49 DCHECK_LE(bytes, unacked_data_); 50 unacked_data_ -= bytes; 51 } 52 } 53 54 QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() { 55 if (estimate_available_) { 56 return 0; 57 } 58 return (kProbeSizePackets * max_segment_size_) - unacked_data_; 59 } 60 61 void 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