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.
5 #include "net/quic/congestion_control/inter_arrival_state_machine.h"
7 #include "base/logging.h"
10 const int kIncreaseEventsBeforeDowngradingState = 5;
11 const int kDecreaseEventsBeforeUpgradingState = 2;
12 // Note: Can not be higher than kDecreaseEventsBeforeUpgradingState;
13 const int kLossEventsBeforeUpgradingState = 2;
14 // Timeout old loss and delay events after this time.
15 const int kEventTimeoutMs = 10000;
16 // A reasonable arbitrary chosen value for initial round trip time.
17 const int kInitialRttMs = 80;
22 InterArrivalStateMachine::InterArrivalStateMachine(const QuicClock* clock)
24 current_state_(kInterArrivalStateStable),
25 smoothed_rtt_(QuicTime::Delta::FromMilliseconds(kInitialRttMs)),
26 decrease_event_count_(0),
27 last_decrease_event_(QuicTime::Zero()),
28 increase_event_count_(0),
29 last_increase_event_(QuicTime::Zero()),
31 last_loss_event_(QuicTime::Zero()),
32 delay_event_count_(0),
33 last_delay_event_(QuicTime::Zero()) {
36 InterArrivalState InterArrivalStateMachine::GetInterArrivalState() {
37 return current_state_;
40 void InterArrivalStateMachine::IncreaseBitrateDecision() {
41 // Multiple increase event without packet loss or delay events will drive
42 // state back to stable.
43 QuicTime current_time = clock_->ApproximateNow();
44 if (current_time.Subtract(last_increase_event_) < smoothed_rtt_) {
45 // Less than one RTT have passed; ignore this event.
48 last_increase_event_ = current_time;
49 increase_event_count_++;
50 decrease_event_count_ = 0; // Reset previous decrease events.
52 if (increase_event_count_ < kIncreaseEventsBeforeDowngradingState) {
53 // Not enough increase events to change state.
56 increase_event_count_ = 0; // Reset increase events.
58 switch (current_state_) {
59 case kInterArrivalStateStable:
62 case kInterArrivalStatePacketLoss:
63 current_state_ = kInterArrivalStateStable;
65 case kInterArrivalStateDelay:
66 current_state_ = kInterArrivalStateStable;
68 case kInterArrivalStateCompetingFlow:
69 current_state_ = kInterArrivalStateDelay;
71 case kInterArrivalStateCompetingTcpFLow:
72 current_state_ = kInterArrivalStateDelay;
77 void InterArrivalStateMachine::DecreaseBitrateDecision() {
78 DCHECK(kDecreaseEventsBeforeUpgradingState >=
79 kLossEventsBeforeUpgradingState);
81 QuicTime current_time = clock_->ApproximateNow();
82 if (current_time.Subtract(last_decrease_event_) < smoothed_rtt_) {
83 // Less than one RTT have passed; ignore this event.
86 last_decrease_event_ = current_time;
87 decrease_event_count_++;
88 increase_event_count_ = 0; // Reset previous increase events.
89 if (decrease_event_count_ < kDecreaseEventsBeforeUpgradingState) {
90 // Not enough decrease events to change state.
93 decrease_event_count_ = 0; // Reset decrease events.
95 switch (current_state_) {
96 case kInterArrivalStateStable:
97 if (delay_event_count_ == 0 && loss_event_count_ > 0) {
98 // No recent delay events; only packet loss events.
99 current_state_ = kInterArrivalStatePacketLoss;
101 current_state_ = kInterArrivalStateDelay;
104 case kInterArrivalStatePacketLoss:
107 case kInterArrivalStateDelay:
108 if (loss_event_count_ >= kLossEventsBeforeUpgradingState) {
109 // We have packet loss events. Assume fighting with TCP.
110 current_state_ = kInterArrivalStateCompetingTcpFLow;
112 current_state_ = kInterArrivalStateCompetingFlow;
115 case kInterArrivalStateCompetingFlow:
116 if (loss_event_count_ >= kLossEventsBeforeUpgradingState) {
117 // We have packet loss events. Assume fighting with TCP.
118 current_state_ = kInterArrivalStateCompetingTcpFLow;
121 case kInterArrivalStateCompetingTcpFLow:
127 void InterArrivalStateMachine::set_rtt(QuicTime::Delta rtt) {
131 bool InterArrivalStateMachine::PacketLossEvent() {
132 QuicTime current_time = clock_->ApproximateNow();
133 if (current_time.Subtract(last_loss_event_) < smoothed_rtt_) {
134 // Less than one RTT have passed; ignore this event.
137 last_loss_event_ = current_time;
139 if (current_time.Subtract(last_delay_event_) >
140 QuicTime::Delta::FromMilliseconds(kEventTimeoutMs)) {
141 // Delay event have timed out.
142 delay_event_count_ = 0;
147 bool InterArrivalStateMachine::IncreasingDelayEvent() {
148 QuicTime current_time = clock_->ApproximateNow();
149 if (current_time.Subtract(last_delay_event_) < smoothed_rtt_) {
150 // Less than one RTT have passed; ignore this event.
153 last_delay_event_ = current_time;
154 delay_event_count_++;
155 if (current_time.Subtract(last_loss_event_) >
156 QuicTime::Delta::FromMilliseconds(kEventTimeoutMs)) {
157 // Loss event have timed out.
158 loss_event_count_ = 0;