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
10namespace {
11const int kProbeSizePackets = 10;
12const net::QuicByteCount kMinPacketSize = 500;
13const int64 kDefaultBytesPerSecond = 40000;
14const float kUncertainScaleFactor = 0.5;  // TODO(pwestin): revisit this factor.
15}
16
17namespace net {
18
19InterArrivalProbe::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
26InterArrivalProbe::~InterArrivalProbe() {
27}
28
29void InterArrivalProbe::set_max_segment_size(QuicByteCount max_segment_size) {
30  max_segment_size_ = max_segment_size;
31}
32
33bool 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
41void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) {
42  if (!estimate_available_) {
43    unacked_data_ += bytes;
44  }
45}
46
47void InterArrivalProbe::OnAcknowledgedPacket(QuicByteCount bytes) {
48  if (!estimate_available_) {
49    DCHECK_LE(bytes, unacked_data_);
50    unacked_data_ -= bytes;
51  }
52}
53
54QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() {
55  if (estimate_available_) {
56    return 0;
57  }
58  return (kProbeSizePackets * max_segment_size_) - unacked_data_;
59}
60
61void 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