summaryrefslogtreecommitdiff
path: root/chromium/net/quic/congestion_control/inter_arrival_probe.cc
blob: 6d4c07315d044a99e1d4ad62a827dd7d368c846f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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 "base/basictypes.h"
#include "base/logging.h"

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

namespace net {

InterArrivalProbe::InterArrivalProbe()
    : 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::OnSentPacket(QuicByteCount bytes) {
  if (!estimate_available_) {
    unacked_data_ += bytes;
  }
}

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

QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() {
  if (estimate_available_) {
    return 0;
  }
  return (kProbeSizePackets * kMaxPacketSize) - 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_ =
          std::max(available_channel_estimate,
                   QuicBandwidth::FromBytesPerSecond(kDefaultBytesPerSecond));
      break;
  }
  estimate_available_ = true;
  available_channel_estimator_.reset(NULL);
  DLOG(INFO) << "Probe estimate:"
             << available_channel_estimate_.ToKBitsPerSecond()
             << " Kbits/s";
}

}  // namespace net