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;