Home | History | Annotate | Download | only in congestion_control
      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