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

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

Issue 2228783004: Fix memory corruption from SetMaxPacingRate by inlining PacingSender. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@129351671
Patch Set: git pull from upper stream Created 4 years, 4 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_sent_packet_manager.h ('k') | net/quic/core/quic_session_test.cc » ('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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_sent_packet_manager.h" 5 #include "net/quic/core/quic_sent_packet_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 24 matching lines...) Expand all
35 const size_t kMinTimeoutsBeforePathDegrading = 2; 35 const size_t kMinTimeoutsBeforePathDegrading = 2;
36 36
37 // Ensure the handshake timer isnt't faster than 10ms. 37 // Ensure the handshake timer isnt't faster than 10ms.
38 // This limits the tenth retransmitted packet to 10s after the initial CHLO. 38 // This limits the tenth retransmitted packet to 10s after the initial CHLO.
39 static const int64_t kMinHandshakeTimeoutMs = 10; 39 static const int64_t kMinHandshakeTimeoutMs = 10;
40 40
41 // Sends up to two tail loss probes before firing an RTO, 41 // Sends up to two tail loss probes before firing an RTO,
42 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. 42 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe.
43 static const size_t kDefaultMaxTailLossProbes = 2; 43 static const size_t kDefaultMaxTailLossProbes = 2;
44 44
45 // Number of unpaced packets to send after quiescence.
46 static const size_t kInitialUnpacedBurst = 10;
47
48 bool HasCryptoHandshake(const TransmissionInfo& transmission_info) { 45 bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
49 DCHECK(!transmission_info.has_crypto_handshake || 46 DCHECK(!transmission_info.has_crypto_handshake ||
50 !transmission_info.retransmittable_frames.empty()); 47 !transmission_info.retransmittable_frames.empty());
51 return transmission_info.has_crypto_handshake; 48 return transmission_info.has_crypto_handshake;
52 } 49 }
53 50
54 } // namespace 51 } // namespace
55 52
56 #define ENDPOINT \ 53 #define ENDPOINT \
57 (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") 54 (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
58 55
59 QuicSentPacketManager::QuicSentPacketManager( 56 QuicSentPacketManager::QuicSentPacketManager(
60 Perspective perspective, 57 Perspective perspective,
61 QuicPathId path_id, 58 QuicPathId path_id,
62 const QuicClock* clock, 59 const QuicClock* clock,
63 QuicConnectionStats* stats, 60 QuicConnectionStats* stats,
64 CongestionControlType congestion_control_type, 61 CongestionControlType congestion_control_type,
65 LossDetectionType loss_type, 62 LossDetectionType loss_type,
66 MultipathDelegateInterface* delegate) 63 MultipathDelegateInterface* delegate)
67 : unacked_packets_(), 64 : unacked_packets_(),
68 perspective_(perspective), 65 perspective_(perspective),
69 path_id_(path_id), 66 path_id_(path_id),
70 clock_(clock), 67 clock_(clock),
71 stats_(stats), 68 stats_(stats),
72 delegate_(delegate), 69 delegate_(delegate),
73 debug_delegate_(nullptr), 70 debug_delegate_(nullptr),
74 network_change_visitor_(nullptr), 71 network_change_visitor_(nullptr),
75 initial_congestion_window_(kInitialCongestionWindow), 72 initial_congestion_window_(kInitialCongestionWindow),
76 send_algorithm_(
77 SendAlgorithmInterface::Create(clock,
78 &rtt_stats_,
79 congestion_control_type,
80 stats,
81 initial_congestion_window_)),
82 loss_algorithm_(&general_loss_algorithm_), 73 loss_algorithm_(&general_loss_algorithm_),
83 general_loss_algorithm_(loss_type), 74 general_loss_algorithm_(loss_type),
84 n_connection_simulation_(false), 75 n_connection_simulation_(false),
85 receive_buffer_bytes_(kDefaultSocketReceiveBuffer), 76 receive_buffer_bytes_(kDefaultSocketReceiveBuffer),
86 least_packet_awaited_by_peer_(1), 77 least_packet_awaited_by_peer_(1),
87 first_rto_transmission_(0), 78 first_rto_transmission_(0),
88 consecutive_rto_count_(0), 79 consecutive_rto_count_(0),
89 consecutive_tlp_count_(0), 80 consecutive_tlp_count_(0),
90 consecutive_crypto_retransmission_count_(0), 81 consecutive_crypto_retransmission_count_(0),
91 pending_timer_transmission_count_(0), 82 pending_timer_transmission_count_(0),
92 max_tail_loss_probes_(kDefaultMaxTailLossProbes), 83 max_tail_loss_probes_(kDefaultMaxTailLossProbes),
93 enable_half_rtt_tail_loss_probe_(false), 84 enable_half_rtt_tail_loss_probe_(false),
94 using_pacing_(false), 85 using_pacing_(false),
95 use_new_rto_(false), 86 use_new_rto_(false),
96 undo_pending_retransmits_(false), 87 undo_pending_retransmits_(false),
97 largest_newly_acked_(0), 88 largest_newly_acked_(0),
98 largest_mtu_acked_(0), 89 largest_mtu_acked_(0),
99 handshake_confirmed_(false) {} 90 handshake_confirmed_(false) {
91 SetSendAlgorithm(congestion_control_type);
92 }
100 93
101 QuicSentPacketManager::~QuicSentPacketManager() {} 94 QuicSentPacketManager::~QuicSentPacketManager() {}
102 95
103 void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { 96 void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
104 if (config.HasReceivedInitialRoundTripTimeUs() && 97 if (config.HasReceivedInitialRoundTripTimeUs() &&
105 config.ReceivedInitialRoundTripTimeUs() > 0) { 98 config.ReceivedInitialRoundTripTimeUs() > 0) {
106 rtt_stats_.set_initial_rtt_us( 99 rtt_stats_.set_initial_rtt_us(
107 max(kMinInitialRoundTripTimeUs, 100 max(kMinInitialRoundTripTimeUs,
108 min(kMaxInitialRoundTripTimeUs, 101 min(kMaxInitialRoundTripTimeUs,
109 config.ReceivedInitialRoundTripTimeUs()))); 102 config.ReceivedInitialRoundTripTimeUs())));
110 } else if (config.HasInitialRoundTripTimeUsToSend() && 103 } else if (config.HasInitialRoundTripTimeUsToSend() &&
111 config.GetInitialRoundTripTimeUsToSend() > 0) { 104 config.GetInitialRoundTripTimeUsToSend() > 0) {
112 rtt_stats_.set_initial_rtt_us( 105 rtt_stats_.set_initial_rtt_us(
113 max(kMinInitialRoundTripTimeUs, 106 max(kMinInitialRoundTripTimeUs,
114 min(kMaxInitialRoundTripTimeUs, 107 min(kMaxInitialRoundTripTimeUs,
115 config.GetInitialRoundTripTimeUsToSend()))); 108 config.GetInitialRoundTripTimeUsToSend())));
116 } 109 }
117 // TODO(ianswett): BBR is currently a server only feature. 110 // TODO(ianswett): BBR is currently a server only feature.
118 if (FLAGS_quic_allow_bbr && config.HasReceivedConnectionOptions() && 111 if (FLAGS_quic_allow_bbr && config.HasReceivedConnectionOptions() &&
119 ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) { 112 ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
120 send_algorithm_.reset(SendAlgorithmInterface::Create( 113 SetSendAlgorithm(kBBR);
121 clock_, &rtt_stats_, kBBR, stats_, initial_congestion_window_));
122 } 114 }
123 if (config.HasReceivedConnectionOptions() && 115 if (config.HasReceivedConnectionOptions() &&
124 ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) { 116 ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
125 if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) { 117 if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
126 send_algorithm_.reset(SendAlgorithmInterface::Create( 118 SetSendAlgorithm(kRenoBytes);
127 clock_, &rtt_stats_, kRenoBytes, stats_, initial_congestion_window_));
128 } else { 119 } else {
129 send_algorithm_.reset(SendAlgorithmInterface::Create( 120 SetSendAlgorithm(kReno);
130 clock_, &rtt_stats_, kReno, stats_, initial_congestion_window_));
131 } 121 }
132 } else if (config.HasReceivedConnectionOptions() && 122 } else if (config.HasReceivedConnectionOptions() &&
133 ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) { 123 ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
134 send_algorithm_.reset(SendAlgorithmInterface::Create( 124 SetSendAlgorithm(kCubicBytes);
135 clock_, &rtt_stats_, kCubicBytes, stats_, initial_congestion_window_));
136 } 125 }
137 if (!FLAGS_quic_disable_pacing_for_perf_tests) { 126 using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests;
138 EnablePacing();
139 }
140 127
141 if (config.HasClientSentConnectionOption(k1CON, perspective_)) { 128 if (config.HasClientSentConnectionOption(k1CON, perspective_)) {
142 send_algorithm_->SetNumEmulatedConnections(1); 129 send_algorithm_->SetNumEmulatedConnections(1);
143 } 130 }
144 if (config.HasClientSentConnectionOption(kNCON, perspective_)) { 131 if (config.HasClientSentConnectionOption(kNCON, perspective_)) {
145 n_connection_simulation_ = true; 132 n_connection_simulation_ = true;
146 } 133 }
147 if (config.HasClientSentConnectionOption(kNTLP, perspective_)) { 134 if (config.HasClientSentConnectionOption(kNTLP, perspective_)) {
148 max_tail_loss_probes_ = 0; 135 max_tail_loss_probes_ = 0;
149 } 136 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 175
189 void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) { 176 void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) {
190 if (n_connection_simulation_) { 177 if (n_connection_simulation_) {
191 // Ensure the number of connections is between 1 and 5. 178 // Ensure the number of connections is between 1 and 5.
192 send_algorithm_->SetNumEmulatedConnections( 179 send_algorithm_->SetNumEmulatedConnections(
193 min<size_t>(5, max<size_t>(1, num_streams))); 180 min<size_t>(5, max<size_t>(1, num_streams)));
194 } 181 }
195 } 182 }
196 183
197 void QuicSentPacketManager::SetMaxPacingRate(QuicBandwidth max_pacing_rate) { 184 void QuicSentPacketManager::SetMaxPacingRate(QuicBandwidth max_pacing_rate) {
198 if (using_pacing_) { 185 pacing_sender_.set_max_pacing_rate(max_pacing_rate);
199 static_cast<PacingSender*>(send_algorithm_.get())
200 ->SetMaxPacingRate(max_pacing_rate);
201 }
202 } 186 }
203 187
204 void QuicSentPacketManager::SetHandshakeConfirmed() { 188 void QuicSentPacketManager::SetHandshakeConfirmed() {
205 handshake_confirmed_ = true; 189 handshake_confirmed_ = true;
206 } 190 }
207 191
208 void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame, 192 void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
209 QuicTime ack_receive_time) { 193 QuicTime ack_receive_time) {
210 DCHECK_LE(ack_frame.largest_observed, unacked_packets_.largest_sent_packet()); 194 DCHECK_LE(ack_frame.largest_observed, unacked_packets_.largest_sent_packet());
211 QuicByteCount bytes_in_flight = unacked_packets_.bytes_in_flight(); 195 QuicByteCount bytes_in_flight = unacked_packets_.bytes_in_flight();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 least_packet_awaited_by_peer_ = ack_frame.packets.Min(); 260 least_packet_awaited_by_peer_ = ack_frame.packets.Min();
277 } 261 }
278 } 262 }
279 263
280 void QuicSentPacketManager::MaybeInvokeCongestionEvent( 264 void QuicSentPacketManager::MaybeInvokeCongestionEvent(
281 bool rtt_updated, 265 bool rtt_updated,
282 QuicByteCount bytes_in_flight) { 266 QuicByteCount bytes_in_flight) {
283 if (!rtt_updated && packets_acked_.empty() && packets_lost_.empty()) { 267 if (!rtt_updated && packets_acked_.empty() && packets_lost_.empty()) {
284 return; 268 return;
285 } 269 }
286 send_algorithm_->OnCongestionEvent(rtt_updated, bytes_in_flight, 270 if (using_pacing_) {
271 pacing_sender_.OnCongestionEvent(rtt_updated, bytes_in_flight,
287 packets_acked_, packets_lost_); 272 packets_acked_, packets_lost_);
273 } else {
274 send_algorithm_->OnCongestionEvent(rtt_updated, bytes_in_flight,
275 packets_acked_, packets_lost_);
276 }
288 packets_acked_.clear(); 277 packets_acked_.clear();
289 packets_lost_.clear(); 278 packets_lost_.clear();
290 if (network_change_visitor_ != nullptr) { 279 if (network_change_visitor_ != nullptr) {
291 network_change_visitor_->OnCongestionChange(); 280 network_change_visitor_->OnCongestionChange();
292 } 281 }
293 } 282 }
294 283
295 void QuicSentPacketManager::HandleAckForSentPackets( 284 void QuicSentPacketManager::HandleAckForSentPackets(
296 const QuicAckFrame& ack_frame) { 285 const QuicAckFrame& ack_frame) {
297 // Go through the packets we have not received an ack for and see if this 286 // Go through the packets we have not received an ack for and see if this
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 << "Cannot send empty packets."; 542 << "Cannot send empty packets.";
554 543
555 if (delegate_ == nullptr && original_packet_number != 0) { 544 if (delegate_ == nullptr && original_packet_number != 0) {
556 pending_retransmissions_.erase(original_packet_number); 545 pending_retransmissions_.erase(original_packet_number);
557 } 546 }
558 547
559 if (pending_timer_transmission_count_ > 0) { 548 if (pending_timer_transmission_count_ > 0) {
560 --pending_timer_transmission_count_; 549 --pending_timer_transmission_count_;
561 } 550 }
562 551
563 // TODO(ianswett): Remove sent_time, because it's unused. 552 bool in_flight;
564 const bool in_flight = send_algorithm_->OnPacketSent( 553 if (using_pacing_) {
565 sent_time, unacked_packets_.bytes_in_flight(), packet_number, 554 in_flight = pacing_sender_.OnPacketSent(
566 serialized_packet->encrypted_length, has_retransmittable_data); 555 sent_time, unacked_packets_.bytes_in_flight(), packet_number,
556 serialized_packet->encrypted_length, has_retransmittable_data);
557 } else {
558 in_flight = send_algorithm_->OnPacketSent(
559 sent_time, unacked_packets_.bytes_in_flight(), packet_number,
560 serialized_packet->encrypted_length, has_retransmittable_data);
561 }
567 562
568 unacked_packets_.AddSentPacket(serialized_packet, original_packet_number, 563 unacked_packets_.AddSentPacket(serialized_packet, original_packet_number,
569 transmission_type, sent_time, in_flight); 564 transmission_type, sent_time, in_flight);
570 // Reset the retransmission timer anytime a pending packet is sent. 565 // Reset the retransmission timer anytime a pending packet is sent.
571 return in_flight; 566 return in_flight;
572 } 567 }
573 568
574 void QuicSentPacketManager::OnRetransmissionTimeout() { 569 void QuicSentPacketManager::OnRetransmissionTimeout() {
575 DCHECK(unacked_packets_.HasInFlightPackets()); 570 DCHECK(unacked_packets_.HasInFlightPackets());
576 DCHECK_EQ(0u, pending_timer_transmission_count_); 571 DCHECK_EQ(0u, pending_timer_transmission_count_);
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 return true; 762 return true;
768 } 763 }
769 764
770 QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now, 765 QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now,
771 QuicPathId* path_id) { 766 QuicPathId* path_id) {
772 QuicTime::Delta delay = QuicTime::Delta::Infinite(); 767 QuicTime::Delta delay = QuicTime::Delta::Infinite();
773 // The TLP logic is entirely contained within QuicSentPacketManager, so the 768 // The TLP logic is entirely contained within QuicSentPacketManager, so the
774 // send algorithm does not need to be consulted. 769 // send algorithm does not need to be consulted.
775 if (pending_timer_transmission_count_ > 0) { 770 if (pending_timer_transmission_count_ > 0) {
776 delay = QuicTime::Delta::Zero(); 771 delay = QuicTime::Delta::Zero();
772 } else if (using_pacing_) {
773 delay =
774 pacing_sender_.TimeUntilSend(now, unacked_packets_.bytes_in_flight());
777 } else { 775 } else {
778 delay = 776 delay =
779 send_algorithm_->TimeUntilSend(now, unacked_packets_.bytes_in_flight()); 777 send_algorithm_->TimeUntilSend(now, unacked_packets_.bytes_in_flight());
780 } 778 }
781 if (!delay.IsInfinite()) { 779 if (!delay.IsInfinite()) {
782 *path_id = path_id_; 780 *path_id = path_id_;
783 } 781 }
784 return delay; 782 return delay;
785 } 783 }
786 784
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 PendingRetransmissionMap::iterator it = pending_retransmissions_.begin(); 917 PendingRetransmissionMap::iterator it = pending_retransmissions_.begin();
920 while (it != pending_retransmissions_.end()) { 918 while (it != pending_retransmissions_.end()) {
921 if (unacked_packets_.HasRetransmittableFrames(it->first)) { 919 if (unacked_packets_.HasRetransmittableFrames(it->first)) {
922 ++it; 920 ++it;
923 continue; 921 continue;
924 } 922 }
925 it = pending_retransmissions_.erase(it); 923 it = pending_retransmissions_.erase(it);
926 } 924 }
927 } 925 }
928 926
929 void QuicSentPacketManager::EnablePacing() { 927 void QuicSentPacketManager::SetSendAlgorithm(
930 // TODO(ianswett): Replace with a method which wraps the send algorithm in a 928 CongestionControlType congestion_control_type) {
931 // pacer every time a new algorithm is set. 929 SetSendAlgorithm(SendAlgorithmInterface::Create(
932 if (using_pacing_) { 930 clock_, &rtt_stats_, congestion_control_type, stats_,
933 return; 931 initial_congestion_window_));
934 } 932 }
935 933
936 // Set up a pacing sender with a 1 millisecond alarm granularity, the same as 934 void QuicSentPacketManager::SetSendAlgorithm(
937 // the default granularity of the Linux kernel's FQ qdisc. 935 SendAlgorithmInterface* send_algorithm) {
938 using_pacing_ = true; 936 send_algorithm_.reset(send_algorithm);
939 send_algorithm_.reset(new PacingSender(send_algorithm_.release(), 937 pacing_sender_.set_sender(send_algorithm);
940 QuicTime::Delta::FromMilliseconds(1),
941 kInitialUnpacedBurst));
942 } 938 }
943 939
944 void QuicSentPacketManager::OnConnectionMigration(QuicPathId, 940 void QuicSentPacketManager::OnConnectionMigration(QuicPathId,
945 PeerAddressChangeType type) { 941 PeerAddressChangeType type) {
946 if (type == PORT_CHANGE || type == IPV4_SUBNET_CHANGE) { 942 if (type == PORT_CHANGE || type == IPV4_SUBNET_CHANGE) {
947 // Rtt and cwnd do not need to be reset when the peer address change is 943 // Rtt and cwnd do not need to be reset when the peer address change is
948 // considered to be caused by NATs. 944 // considered to be caused by NATs.
949 return; 945 return;
950 } 946 }
951 consecutive_rto_count_ = 0; 947 consecutive_rto_count_ = 0;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 998
1003 void QuicSentPacketManager::RemoveObsoletePackets() { 999 void QuicSentPacketManager::RemoveObsoletePackets() {
1004 unacked_packets_.RemoveObsoletePackets(); 1000 unacked_packets_.RemoveObsoletePackets();
1005 } 1001 }
1006 1002
1007 void QuicSentPacketManager::OnApplicationLimited() { 1003 void QuicSentPacketManager::OnApplicationLimited() {
1008 send_algorithm_->OnApplicationLimited(unacked_packets_.bytes_in_flight()); 1004 send_algorithm_->OnApplicationLimited(unacked_packets_.bytes_in_flight());
1009 } 1005 }
1010 1006
1011 } // namespace net 1007 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_sent_packet_manager.h ('k') | net/quic/core/quic_session_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698