Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / net / quic / congestion_control / inter_arrival_state_machine.cc
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_state_machine.h"
6
7 #include "base/logging.h"
8
9 namespace  {
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;
18 }
19
20 namespace net {
21
22 InterArrivalStateMachine::InterArrivalStateMachine(const QuicClock* clock)
23     : clock_(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()),
30       loss_event_count_(0),
31       last_loss_event_(QuicTime::Zero()),
32       delay_event_count_(0),
33       last_delay_event_(QuicTime::Zero()) {
34 }
35
36 InterArrivalState InterArrivalStateMachine::GetInterArrivalState() {
37   return current_state_;
38 }
39
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.
46     return;
47   }
48   last_increase_event_ = current_time;
49   increase_event_count_++;
50   decrease_event_count_ = 0;  // Reset previous decrease events.
51
52   if (increase_event_count_ < kIncreaseEventsBeforeDowngradingState) {
53     // Not enough increase events to change state.
54     return;
55   }
56   increase_event_count_ = 0;  // Reset increase events.
57
58   switch (current_state_) {
59     case kInterArrivalStateStable:
60       // Keep this state.
61       break;
62     case kInterArrivalStatePacketLoss:
63       current_state_ = kInterArrivalStateStable;
64       break;
65     case kInterArrivalStateDelay:
66       current_state_ = kInterArrivalStateStable;
67       break;
68     case kInterArrivalStateCompetingFlow:
69       current_state_ = kInterArrivalStateDelay;
70       break;
71     case kInterArrivalStateCompetingTcpFLow:
72       current_state_ = kInterArrivalStateDelay;
73       break;
74   }
75 }
76
77 void InterArrivalStateMachine::DecreaseBitrateDecision() {
78   DCHECK(kDecreaseEventsBeforeUpgradingState >=
79          kLossEventsBeforeUpgradingState);
80
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.
84     return;
85   }
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.
91     return;
92   }
93   decrease_event_count_ = 0;  // Reset decrease events.
94
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;
100       } else {
101         current_state_ = kInterArrivalStateDelay;
102       }
103       break;
104     case kInterArrivalStatePacketLoss:
105       // Keep this state.
106       break;
107     case kInterArrivalStateDelay:
108       if (loss_event_count_ >= kLossEventsBeforeUpgradingState) {
109         // We have packet loss events. Assume fighting with TCP.
110         current_state_ = kInterArrivalStateCompetingTcpFLow;
111       } else {
112         current_state_ = kInterArrivalStateCompetingFlow;
113       }
114       break;
115     case kInterArrivalStateCompetingFlow:
116       if (loss_event_count_ >= kLossEventsBeforeUpgradingState) {
117         // We have packet loss events. Assume fighting with TCP.
118         current_state_ = kInterArrivalStateCompetingTcpFLow;
119       }
120       break;
121     case kInterArrivalStateCompetingTcpFLow:
122       // Keep this state.
123       break;
124   }
125 }
126
127 void InterArrivalStateMachine::set_rtt(QuicTime::Delta rtt) {
128   smoothed_rtt_ = rtt;
129 }
130
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.
135     return false;
136   }
137   last_loss_event_ = current_time;
138   loss_event_count_++;
139   if (current_time.Subtract(last_delay_event_) >
140       QuicTime::Delta::FromMilliseconds(kEventTimeoutMs)) {
141     // Delay event have timed out.
142     delay_event_count_ = 0;
143   }
144   return true;
145 }
146
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.
151     return false;
152   }
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;
159   }
160   return true;
161 }
162
163 }  // namespace net