root/net/quic/congestion_control/inter_arrival_probe.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unacked_data_
  2. GetEstimate
  3. OnPacketSent
  4. OnAcknowledgedPacket
  5. OnRetransmissionTimeout
  6. GetAvailableCongestionWindow
  7. OnIncomingFeedback

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/congestion_control/inter_arrival_probe.h"

#include <algorithm>

#include "base/basictypes.h"
#include "base/logging.h"

using std::max;

namespace net {

namespace {
const int kProbeSizePackets = 10;
const QuicByteCount kMinPacketSize = 500;
const int64 kDefaultBytesPerSecond = 40000;
const float kUncertainScaleFactor = 0.5;  // TODO(pwestin): revisit this factor.
}

InterArrivalProbe::InterArrivalProbe(QuicByteCount max_segment_size)
    : max_segment_size_(max_segment_size),
      estimate_available_(false),
      available_channel_estimate_(QuicBandwidth::Zero()),
      unacked_data_(0) {
}

InterArrivalProbe::~InterArrivalProbe() {
}

bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) {
  if (!estimate_available_) {
    return false;
  }
  *available_channel_estimate = available_channel_estimate_;
  return true;
}

void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) {
  if (!estimate_available_) {
    unacked_data_ += bytes;
  }
}

void InterArrivalProbe::OnAcknowledgedPacket(QuicByteCount bytes) {
  if (!estimate_available_) {
    DCHECK_LE(bytes, unacked_data_);
    unacked_data_ -= bytes;
  }
}

void InterArrivalProbe::OnRetransmissionTimeout() {
  if (!estimate_available_) {
    unacked_data_ = 0;
  }
}

QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() {
  if (estimate_available_) {
    return 0;
  }
  return (kProbeSizePackets * max_segment_size_) - unacked_data_;
}

void InterArrivalProbe::OnIncomingFeedback(
    QuicPacketSequenceNumber sequence_number,
    QuicByteCount bytes_sent,
    QuicTime time_sent,
    QuicTime time_received) {
  if (estimate_available_) {
    return;
  }

  if (available_channel_estimator_.get() == NULL) {
    if (bytes_sent < kMinPacketSize) {
      // Packet too small to start the probe phase.
      return;
    }
    first_sequence_number_ = sequence_number;
    available_channel_estimator_.reset(new AvailableChannelEstimator(
        sequence_number, time_sent, time_received));
    return;
  }

  available_channel_estimator_->OnIncomingFeedback(sequence_number,
                                                   bytes_sent,
                                                   time_sent,
                                                   time_received);
  if (sequence_number < kProbeSizePackets - 1  + first_sequence_number_) {
    // We need more feedback before we have a probe estimate.
    return;
  }
  // Get the current estimated available channel capacity.
  // available_channel_estimate is invalid if kAvailableChannelEstimateUnknown
  // is returned.
  QuicBandwidth available_channel_estimate = QuicBandwidth::Zero();
  AvailableChannelEstimateState available_channel_estimate_state =
      available_channel_estimator_->GetAvailableChannelEstimate(
          &available_channel_estimate);
  switch (available_channel_estimate_state) {
    case kAvailableChannelEstimateUnknown:
      // Backup when we miss our probe.
      available_channel_estimate_ =
          QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond);
      break;
    case kAvailableChannelEstimateUncertain:
      available_channel_estimate_ =
          available_channel_estimate.Scale(kUncertainScaleFactor);
      break;
    case kAvailableChannelEstimateGood:
      available_channel_estimate_ = available_channel_estimate;
      break;
    case kAvailableChannelEstimateSenderLimited:
      available_channel_estimate_ =
          max(available_channel_estimate,
              QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond));
      break;
  }
  estimate_available_ = true;
  available_channel_estimator_.reset(NULL);
  DVLOG(1) << "Probe estimate:"
           << available_channel_estimate_.ToKBitsPerSecond()
           << " Kbits/s";
}

}  // namespace net

/* [<][>][^][v][top][bottom][index][help] */