Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(389)

Side by Side Diff: net/quic/core/quic_flow_controller.cc

Issue 2611613003: Add quic_logging (Closed)
Patch Set: fix failed test? Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/core/quic_data_writer.h ('k') | net/quic/core/quic_framer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/core/quic_flow_controller.h" 5 #include "net/quic/core/quic_flow_controller.h"
6 6
7 #include <cstdint> 7 #include <cstdint>
8 8
9 #include "net/quic/core/quic_connection.h" 9 #include "net/quic/core/quic_connection.h"
10 #include "net/quic/core/quic_packets.h" 10 #include "net/quic/core/quic_packets.h"
11 #include "net/quic/platform/api/quic_bug_tracker.h" 11 #include "net/quic/platform/api/quic_bug_tracker.h"
12 #include "net/quic/platform/api/quic_logging.h"
12 #include "net/quic/platform/api/quic_str_cat.h" 13 #include "net/quic/platform/api/quic_str_cat.h"
13 14
14 namespace net { 15 namespace net {
15 16
16 #define ENDPOINT \ 17 #define ENDPOINT \
17 (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") 18 (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
18 19
19 QuicFlowController::QuicFlowController(QuicConnection* connection, 20 QuicFlowController::QuicFlowController(QuicConnection* connection,
20 QuicStreamId id, 21 QuicStreamId id,
21 Perspective perspective, 22 Perspective perspective,
(...skipping 10 matching lines...) Expand all
32 receive_window_offset_(receive_window_offset), 33 receive_window_offset_(receive_window_offset),
33 receive_window_size_(receive_window_offset), 34 receive_window_size_(receive_window_offset),
34 auto_tune_receive_window_(should_auto_tune_receive_window), 35 auto_tune_receive_window_(should_auto_tune_receive_window),
35 last_blocked_send_window_offset_(0), 36 last_blocked_send_window_offset_(0),
36 prev_window_update_time_(QuicTime::Zero()) { 37 prev_window_update_time_(QuicTime::Zero()) {
37 receive_window_size_limit_ = (id_ == kConnectionLevelId) 38 receive_window_size_limit_ = (id_ == kConnectionLevelId)
38 ? kSessionReceiveWindowLimit 39 ? kSessionReceiveWindowLimit
39 : kStreamReceiveWindowLimit; 40 : kStreamReceiveWindowLimit;
40 DCHECK_LE(receive_window_size_, receive_window_size_limit_); 41 DCHECK_LE(receive_window_size_, receive_window_size_limit_);
41 42
42 DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_ 43 QUIC_DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
43 << ", setting initial receive window offset to: " 44 << ", setting initial receive window offset to: "
44 << receive_window_offset_ 45 << receive_window_offset_
45 << ", max receive window to: " << receive_window_size_ 46 << ", max receive window to: " << receive_window_size_
46 << ", max receive window limit to: " << receive_window_size_limit_ 47 << ", max receive window limit to: "
47 << ", setting send window offset to: " << send_window_offset_; 48 << receive_window_size_limit_
49 << ", setting send window offset to: " << send_window_offset_;
48 } 50 }
49 51
50 void QuicFlowController::AddBytesConsumed(QuicByteCount bytes_consumed) { 52 void QuicFlowController::AddBytesConsumed(QuicByteCount bytes_consumed) {
51 bytes_consumed_ += bytes_consumed; 53 bytes_consumed_ += bytes_consumed;
52 DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_; 54 QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_
55 << " consumed: " << bytes_consumed_;
53 56
54 MaybeSendWindowUpdate(); 57 MaybeSendWindowUpdate();
55 } 58 }
56 59
57 bool QuicFlowController::UpdateHighestReceivedOffset( 60 bool QuicFlowController::UpdateHighestReceivedOffset(
58 QuicStreamOffset new_offset) { 61 QuicStreamOffset new_offset) {
59 // Only update if offset has increased. 62 // Only update if offset has increased.
60 if (new_offset <= highest_received_byte_offset_) { 63 if (new_offset <= highest_received_byte_offset_) {
61 return false; 64 return false;
62 } 65 }
63 66
64 DVLOG(1) << ENDPOINT << "Stream " << id_ 67 QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_
65 << " highest byte offset increased from: " 68 << " highest byte offset increased from: "
66 << highest_received_byte_offset_ << " to " << new_offset; 69 << highest_received_byte_offset_ << " to " << new_offset;
67 highest_received_byte_offset_ = new_offset; 70 highest_received_byte_offset_ = new_offset;
68 return true; 71 return true;
69 } 72 }
70 73
71 void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) { 74 void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) {
72 if (bytes_sent_ + bytes_sent > send_window_offset_) { 75 if (bytes_sent_ + bytes_sent > send_window_offset_) {
73 QUIC_BUG << ENDPOINT << "Stream " << id_ << " Trying to send an extra " 76 QUIC_BUG << ENDPOINT << "Stream " << id_ << " Trying to send an extra "
74 << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_ 77 << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
75 << ", and send_window_offset_ = " << send_window_offset_; 78 << ", and send_window_offset_ = " << send_window_offset_;
76 bytes_sent_ = send_window_offset_; 79 bytes_sent_ = send_window_offset_;
77 80
78 // This is an error on our side, close the connection as soon as possible. 81 // This is an error on our side, close the connection as soon as possible.
79 connection_->CloseConnection( 82 connection_->CloseConnection(
80 QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, 83 QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA,
81 QuicStrCat(send_window_offset_ - (bytes_sent_ + bytes_sent), 84 QuicStrCat(send_window_offset_ - (bytes_sent_ + bytes_sent),
82 "bytes over send window offset"), 85 "bytes over send window offset"),
83 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); 86 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
84 return; 87 return;
85 } 88 }
86 89
87 bytes_sent_ += bytes_sent; 90 bytes_sent_ += bytes_sent;
88 DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_; 91 QUIC_DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_;
89 } 92 }
90 93
91 bool QuicFlowController::FlowControlViolation() { 94 bool QuicFlowController::FlowControlViolation() {
92 if (highest_received_byte_offset_ > receive_window_offset_) { 95 if (highest_received_byte_offset_ > receive_window_offset_) {
93 DVLOG(1) << ENDPOINT << "Flow control violation on stream " << id_ 96 QUIC_DLOG(INFO) << ENDPOINT << "Flow control violation on stream " << id_
94 << ", receive window offset: " << receive_window_offset_ 97 << ", receive window offset: " << receive_window_offset_
95 << ", highest received byte offset: " 98 << ", highest received byte offset: "
96 << highest_received_byte_offset_; 99 << highest_received_byte_offset_;
97 return true; 100 return true;
98 } 101 }
99 return false; 102 return false;
100 } 103 }
101 104
102 void QuicFlowController::MaybeIncreaseMaxWindowSize() { 105 void QuicFlowController::MaybeIncreaseMaxWindowSize() {
103 // Core of receive window auto tuning. This method should be called before a 106 // Core of receive window auto tuning. This method should be called before a
104 // WINDOW_UPDATE frame is sent. Ideally, window updates should occur close to 107 // WINDOW_UPDATE frame is sent. Ideally, window updates should occur close to
105 // once per RTT. If a window update happens much faster than RTT, it implies 108 // once per RTT. If a window update happens much faster than RTT, it implies
106 // that the flow control window is imposing a bottleneck. To prevent this, 109 // that the flow control window is imposing a bottleneck. To prevent this,
107 // this method will increase the receive window size (subject to a reasonable 110 // this method will increase the receive window size (subject to a reasonable
108 // upper bound). For simplicity this algorithm is deliberately asymmetric, in 111 // upper bound). For simplicity this algorithm is deliberately asymmetric, in
109 // that it may increase window size but never decreases. 112 // that it may increase window size but never decreases.
110 113
111 // Keep track of timing between successive window updates. 114 // Keep track of timing between successive window updates.
112 QuicTime now = connection_->clock()->ApproximateNow(); 115 QuicTime now = connection_->clock()->ApproximateNow();
113 QuicTime prev = prev_window_update_time_; 116 QuicTime prev = prev_window_update_time_;
114 prev_window_update_time_ = now; 117 prev_window_update_time_ = now;
115 if (!prev.IsInitialized()) { 118 if (!prev.IsInitialized()) {
116 DVLOG(1) << ENDPOINT << "first window update for stream " << id_; 119 QUIC_DVLOG(1) << ENDPOINT << "first window update for stream " << id_;
117 return; 120 return;
118 } 121 }
119 122
120 if (!auto_tune_receive_window_) { 123 if (!auto_tune_receive_window_) {
121 return; 124 return;
122 } 125 }
123 126
124 // Get outbound RTT. 127 // Get outbound RTT.
125 QuicTime::Delta rtt = 128 QuicTime::Delta rtt =
126 connection_->sent_packet_manager().GetRttStats()->smoothed_rtt(); 129 connection_->sent_packet_manager().GetRttStats()->smoothed_rtt();
127 if (rtt.IsZero()) { 130 if (rtt.IsZero()) {
128 DVLOG(1) << ENDPOINT << "rtt zero for stream " << id_; 131 QUIC_DVLOG(1) << ENDPOINT << "rtt zero for stream " << id_;
129 return; 132 return;
130 } 133 }
131 134
132 // Now we can compare timing of window updates with RTT. 135 // Now we can compare timing of window updates with RTT.
133 QuicTime::Delta since_last = now - prev; 136 QuicTime::Delta since_last = now - prev;
134 QuicTime::Delta two_rtt = 2 * rtt; 137 QuicTime::Delta two_rtt = 2 * rtt;
135 138
136 if (since_last >= two_rtt) { 139 if (since_last >= two_rtt) {
137 // If interval between window updates is sufficiently large, there 140 // If interval between window updates is sufficiently large, there
138 // is no need to increase receive_window_size_. 141 // is no need to increase receive_window_size_.
139 return; 142 return;
140 } 143 }
141 144
142 QuicByteCount old_window = receive_window_size_; 145 QuicByteCount old_window = receive_window_size_;
143 receive_window_size_ *= 2; 146 receive_window_size_ *= 2;
144 receive_window_size_ = 147 receive_window_size_ =
145 std::min(receive_window_size_, receive_window_size_limit_); 148 std::min(receive_window_size_, receive_window_size_limit_);
146 149
147 if (receive_window_size_ > old_window) { 150 if (receive_window_size_ > old_window) {
148 DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_ 151 QUIC_DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_
149 << " after " << since_last.ToMicroseconds() << " us, and RTT is " 152 << " after " << since_last.ToMicroseconds()
150 << rtt.ToMicroseconds() 153 << " us, and RTT is " << rtt.ToMicroseconds()
151 << "us. max wndw: " << receive_window_size_; 154 << "us. max wndw: " << receive_window_size_;
152 } else { 155 } else {
153 // TODO(ckrasic) - add a varz to track this (?). 156 // TODO(ckrasic) - add a varz to track this (?).
154 DVLOG(1) << ENDPOINT << "Max window at limit for stream " << id_ 157 QUIC_LOG_FIRST_N(INFO, 1) << ENDPOINT << "Max window at limit for stream "
155 << " after " << since_last.ToMicroseconds() << " us, and RTT is " 158 << id_ << " after " << since_last.ToMicroseconds()
156 << rtt.ToMicroseconds() 159 << " us, and RTT is " << rtt.ToMicroseconds()
157 << "us. Limit size: " << receive_window_size_; 160 << "us. Limit size: " << receive_window_size_;
158 } 161 }
159 } 162 }
160 163
161 QuicByteCount QuicFlowController::WindowUpdateThreshold() { 164 QuicByteCount QuicFlowController::WindowUpdateThreshold() {
162 return receive_window_size_ / 2; 165 return receive_window_size_ / 2;
163 } 166 }
164 167
165 void QuicFlowController::MaybeSendWindowUpdate() { 168 void QuicFlowController::MaybeSendWindowUpdate() {
166 // Send WindowUpdate to increase receive window if 169 // Send WindowUpdate to increase receive window if
167 // (receive window offset - consumed bytes) < (max window / 2). 170 // (receive window offset - consumed bytes) < (max window / 2).
168 // This is behaviour copied from SPDY. 171 // This is behaviour copied from SPDY.
169 DCHECK_LE(bytes_consumed_, receive_window_offset_); 172 DCHECK_LE(bytes_consumed_, receive_window_offset_);
170 QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_; 173 QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_;
171 QuicByteCount threshold = WindowUpdateThreshold(); 174 QuicByteCount threshold = WindowUpdateThreshold();
172 175
173 if (available_window >= threshold) { 176 if (available_window >= threshold) {
174 DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_ 177 QUIC_DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_
175 << ", available window: " << available_window 178 << ", available window: " << available_window
176 << " >= threshold: " << threshold; 179 << " >= threshold: " << threshold;
177 return; 180 return;
178 } 181 }
179 182
180 MaybeIncreaseMaxWindowSize(); 183 MaybeIncreaseMaxWindowSize();
181 184
182 // Update our receive window. 185 // Update our receive window.
183 receive_window_offset_ += (receive_window_size_ - available_window); 186 receive_window_offset_ += (receive_window_size_ - available_window);
184 187
185 DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_ 188 QUIC_DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
186 << ", consumed bytes: " << bytes_consumed_ 189 << ", consumed bytes: " << bytes_consumed_
187 << ", available window: " << available_window 190 << ", available window: " << available_window
188 << ", and threshold: " << threshold 191 << ", and threshold: " << threshold
189 << ", and receive window size: " << receive_window_size_ 192 << ", and receive window size: " << receive_window_size_
190 << ". New receive window offset is: " << receive_window_offset_; 193 << ". New receive window offset is: " << receive_window_offset_;
191 194
192 // Inform the peer of our new receive window. 195 // Inform the peer of our new receive window.
193 connection_->SendWindowUpdate(id_, receive_window_offset_); 196 connection_->SendWindowUpdate(id_, receive_window_offset_);
194 } 197 }
195 198
196 void QuicFlowController::MaybeSendBlocked() { 199 void QuicFlowController::MaybeSendBlocked() {
197 if (SendWindowSize() == 0 && 200 if (SendWindowSize() == 0 &&
198 last_blocked_send_window_offset_ < send_window_offset_) { 201 last_blocked_send_window_offset_ < send_window_offset_) {
199 DVLOG(1) << ENDPOINT << "Stream " << id_ << " is flow control blocked. " 202 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id_
200 << "Send window: " << SendWindowSize() 203 << " is flow control blocked. "
201 << ", bytes sent: " << bytes_sent_ 204 << "Send window: " << SendWindowSize()
202 << ", send limit: " << send_window_offset_; 205 << ", bytes sent: " << bytes_sent_
206 << ", send limit: " << send_window_offset_;
203 // The entire send_window has been consumed, we are now flow control 207 // The entire send_window has been consumed, we are now flow control
204 // blocked. 208 // blocked.
205 connection_->SendBlocked(id_); 209 connection_->SendBlocked(id_);
206 210
207 // Keep track of when we last sent a BLOCKED frame so that we only send one 211 // Keep track of when we last sent a BLOCKED frame so that we only send one
208 // at a given send offset. 212 // at a given send offset.
209 last_blocked_send_window_offset_ = send_window_offset_; 213 last_blocked_send_window_offset_ = send_window_offset_;
210 } 214 }
211 } 215 }
212 216
213 bool QuicFlowController::UpdateSendWindowOffset( 217 bool QuicFlowController::UpdateSendWindowOffset(
214 QuicStreamOffset new_send_window_offset) { 218 QuicStreamOffset new_send_window_offset) {
215 // Only update if send window has increased. 219 // Only update if send window has increased.
216 if (new_send_window_offset <= send_window_offset_) { 220 if (new_send_window_offset <= send_window_offset_) {
217 return false; 221 return false;
218 } 222 }
219 223
220 DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_ 224 QUIC_DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_
221 << " with new offset " << new_send_window_offset 225 << " with new offset " << new_send_window_offset
222 << " current offset: " << send_window_offset_ 226 << " current offset: " << send_window_offset_
223 << " bytes_sent: " << bytes_sent_; 227 << " bytes_sent: " << bytes_sent_;
224 228
225 const bool blocked = IsBlocked(); 229 const bool blocked = IsBlocked();
226 send_window_offset_ = new_send_window_offset; 230 send_window_offset_ = new_send_window_offset;
227 return blocked; 231 return blocked;
228 } 232 }
229 233
230 bool QuicFlowController::IsBlocked() const { 234 bool QuicFlowController::IsBlocked() const {
231 return SendWindowSize() == 0; 235 return SendWindowSize() == 0;
232 } 236 }
233 237
234 uint64_t QuicFlowController::SendWindowSize() const { 238 uint64_t QuicFlowController::SendWindowSize() const {
235 if (bytes_sent_ > send_window_offset_) { 239 if (bytes_sent_ > send_window_offset_) {
236 return 0; 240 return 0;
237 } 241 }
238 return send_window_offset_ - bytes_sent_; 242 return send_window_offset_ - bytes_sent_;
239 } 243 }
240 244
241 void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) { 245 void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) {
242 DCHECK_LE(size, receive_window_size_limit_); 246 DCHECK_LE(size, receive_window_size_limit_);
243 DVLOG(1) << ENDPOINT << "UpdateReceiveWindowSize for stream " << id_ << ": " 247 QUIC_DVLOG(1) << ENDPOINT << "UpdateReceiveWindowSize for stream " << id_
244 << size; 248 << ": " << size;
245 if (receive_window_size_ != receive_window_offset_) { 249 if (receive_window_size_ != receive_window_offset_) {
246 QUIC_BUG << "receive_window_size_:" << receive_window_size_ 250 QUIC_BUG << "receive_window_size_:" << receive_window_size_
247 << " != receive_window_offset:" << receive_window_offset_; 251 << " != receive_window_offset:" << receive_window_offset_;
248 return; 252 return;
249 } 253 }
250 receive_window_size_ = size; 254 receive_window_size_ = size;
251 receive_window_offset_ = size; 255 receive_window_offset_ = size;
252 } 256 }
253 257
254 } // namespace net 258 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_data_writer.h ('k') | net/quic/core/quic_framer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698