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()
     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