| OLD | NEW |
| 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/quic_sent_packet_manager.h" | 5 #include "net/quic/quic_sent_packet_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 static const int64 kDefaultRetransmissionTimeMs = 500; | 29 static const int64 kDefaultRetransmissionTimeMs = 500; |
| 30 // TCP RFC calls for 1 second RTO however Linux differs from this default and | 30 // TCP RFC calls for 1 second RTO however Linux differs from this default and |
| 31 // define the minimum RTO to 200ms, we will use the same until we have data to | 31 // define the minimum RTO to 200ms, we will use the same until we have data to |
| 32 // support a higher or lower value. | 32 // support a higher or lower value. |
| 33 static const int64 kMinRetransmissionTimeMs = 200; | 33 static const int64 kMinRetransmissionTimeMs = 200; |
| 34 static const int64 kMaxRetransmissionTimeMs = 60000; | 34 static const int64 kMaxRetransmissionTimeMs = 60000; |
| 35 static const size_t kMaxRetransmissions = 10; | 35 static const size_t kMaxRetransmissions = 10; |
| 36 | 36 |
| 37 // Only exponentially back off the handshake timer 5 times due to a timeout. | 37 // Ensure the handshake timer isnt't faster than 10ms. |
| 38 static const size_t kMaxHandshakeRetransmissionBackoffs = 5; | 38 // This limits the tenth retransmitted packet to 10s after the initial CHLO. |
| 39 static const int64 kMinHandshakeTimeoutMs = 10; | 39 static const int64 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 static const int64 kMinTailLossProbeTimeoutMs = 10; | 44 static const int64 kMinTailLossProbeTimeoutMs = 10; |
| 45 | 45 |
| 46 // Number of samples before we force a new recent min rtt to be captured. | 46 // Number of samples before we force a new recent min rtt to be captured. |
| 47 static const size_t kNumMinRttSamplesAfterQuiescence = 2; | 47 static const size_t kNumMinRttSamplesAfterQuiescence = 2; |
| 48 | 48 |
| 49 // Number of unpaced packets to send after quiescence. | 49 // Number of unpaced packets to send after quiescence. |
| 50 static const size_t kInitialUnpacedBurst = 10; | 50 static const size_t kInitialUnpacedBurst = 10; |
| 51 | 51 |
| 52 // Fraction of the receive buffer that can be used for encrypted bytes. |
| 53 // Allows a 5% overhead for IP and UDP framing, as well as ack only packets. |
| 54 static const float kUsableRecieveBufferFraction = 0.95f; |
| 55 |
| 52 bool HasCryptoHandshake(const TransmissionInfo& transmission_info) { | 56 bool HasCryptoHandshake(const TransmissionInfo& transmission_info) { |
| 53 if (transmission_info.retransmittable_frames == nullptr) { | 57 if (transmission_info.retransmittable_frames == nullptr) { |
| 54 return false; | 58 return false; |
| 55 } | 59 } |
| 56 return transmission_info.retransmittable_frames->HasCryptoHandshake() == | 60 return transmission_info.retransmittable_frames->HasCryptoHandshake() == |
| 57 IS_HANDSHAKE; | 61 IS_HANDSHAKE; |
| 58 } | 62 } |
| 59 | 63 |
| 60 } // namespace | 64 } // namespace |
| 61 | 65 |
| 62 #define ENDPOINT (is_server_ ? "Server: " : " Client: ") | 66 #define ENDPOINT (is_server_ ? "Server: " : " Client: ") |
| 63 | 67 |
| 64 QuicSentPacketManager::QuicSentPacketManager( | 68 QuicSentPacketManager::QuicSentPacketManager( |
| 65 bool is_server, | 69 bool is_server, |
| 66 const QuicClock* clock, | 70 const QuicClock* clock, |
| 67 QuicConnectionStats* stats, | 71 QuicConnectionStats* stats, |
| 68 CongestionControlType congestion_control_type, | 72 CongestionControlType congestion_control_type, |
| 69 LossDetectionType loss_type) | 73 LossDetectionType loss_type, |
| 74 bool is_secure) |
| 70 : unacked_packets_(), | 75 : unacked_packets_(), |
| 71 is_server_(is_server), | 76 is_server_(is_server), |
| 72 clock_(clock), | 77 clock_(clock), |
| 73 stats_(stats), | 78 stats_(stats), |
| 74 debug_delegate_(nullptr), | 79 debug_delegate_(nullptr), |
| 75 network_change_visitor_(nullptr), | 80 network_change_visitor_(nullptr), |
| 76 send_algorithm_(SendAlgorithmInterface::Create(clock, | 81 initial_congestion_window_(is_secure ? kInitialCongestionWindowSecure |
| 77 &rtt_stats_, | 82 : kInitialCongestionWindowInsecure), |
| 78 congestion_control_type, | 83 send_algorithm_( |
| 79 stats)), | 84 SendAlgorithmInterface::Create(clock, |
| 85 &rtt_stats_, |
| 86 congestion_control_type, |
| 87 stats, |
| 88 initial_congestion_window_)), |
| 80 loss_algorithm_(LossDetectionInterface::Create(loss_type)), | 89 loss_algorithm_(LossDetectionInterface::Create(loss_type)), |
| 81 n_connection_simulation_(false), | 90 n_connection_simulation_(false), |
| 82 receive_buffer_bytes_(kDefaultSocketReceiveBuffer), | 91 receive_buffer_bytes_(kDefaultSocketReceiveBuffer), |
| 83 least_packet_awaited_by_peer_(1), | 92 least_packet_awaited_by_peer_(1), |
| 84 first_rto_transmission_(0), | 93 first_rto_transmission_(0), |
| 85 consecutive_rto_count_(0), | 94 consecutive_rto_count_(0), |
| 86 consecutive_tlp_count_(0), | 95 consecutive_tlp_count_(0), |
| 87 consecutive_crypto_retransmission_count_(0), | 96 consecutive_crypto_retransmission_count_(0), |
| 88 pending_timer_transmission_count_(0), | 97 pending_timer_transmission_count_(0), |
| 89 max_tail_loss_probes_(kDefaultMaxTailLossProbes), | 98 max_tail_loss_probes_(kDefaultMaxTailLossProbes), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 109 config.GetInitialRoundTripTimeUsToSend()))); | 118 config.GetInitialRoundTripTimeUsToSend()))); |
| 110 } | 119 } |
| 111 // TODO(ianswett): BBR is currently a server only feature. | 120 // TODO(ianswett): BBR is currently a server only feature. |
| 112 if (FLAGS_quic_allow_bbr && | 121 if (FLAGS_quic_allow_bbr && |
| 113 config.HasReceivedConnectionOptions() && | 122 config.HasReceivedConnectionOptions() && |
| 114 ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) { | 123 ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) { |
| 115 if (FLAGS_quic_recent_min_rtt_window_s > 0) { | 124 if (FLAGS_quic_recent_min_rtt_window_s > 0) { |
| 116 rtt_stats_.set_recent_min_rtt_window( | 125 rtt_stats_.set_recent_min_rtt_window( |
| 117 QuicTime::Delta::FromSeconds(FLAGS_quic_recent_min_rtt_window_s)); | 126 QuicTime::Delta::FromSeconds(FLAGS_quic_recent_min_rtt_window_s)); |
| 118 } | 127 } |
| 119 send_algorithm_.reset( | 128 send_algorithm_.reset(SendAlgorithmInterface::Create( |
| 120 SendAlgorithmInterface::Create(clock_, &rtt_stats_, kBBR, stats_)); | 129 clock_, &rtt_stats_, kBBR, stats_, initial_congestion_window_)); |
| 121 } | 130 } |
| 122 if (config.HasReceivedConnectionOptions() && | 131 if (config.HasReceivedConnectionOptions() && |
| 123 ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) { | 132 ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) { |
| 124 send_algorithm_.reset( | 133 send_algorithm_.reset(SendAlgorithmInterface::Create( |
| 125 SendAlgorithmInterface::Create(clock_, &rtt_stats_, kReno, stats_)); | 134 clock_, &rtt_stats_, kReno, stats_, initial_congestion_window_)); |
| 126 } | 135 } |
| 127 if (HasClientSentConnectionOption(config, kPACE)) { | 136 if (HasClientSentConnectionOption(config, kPACE) || |
| 137 (FLAGS_quic_allow_bbr && |
| 138 HasClientSentConnectionOption(config, kTBBR))) { |
| 128 EnablePacing(); | 139 EnablePacing(); |
| 129 } | 140 } |
| 130 if (HasClientSentConnectionOption(config, k1CON)) { | 141 if (HasClientSentConnectionOption(config, k1CON)) { |
| 131 send_algorithm_->SetNumEmulatedConnections(1); | 142 send_algorithm_->SetNumEmulatedConnections(1); |
| 132 } | 143 } |
| 133 if (HasClientSentConnectionOption(config, kNCON)) { | 144 if (HasClientSentConnectionOption(config, kNCON)) { |
| 134 n_connection_simulation_ = true; | 145 n_connection_simulation_ = true; |
| 135 } | 146 } |
| 136 if (HasClientSentConnectionOption(config, kNTLP)) { | 147 if (HasClientSentConnectionOption(config, kNTLP)) { |
| 137 max_tail_loss_probes_ = 0; | 148 max_tail_loss_probes_ = 0; |
| 138 } | 149 } |
| 139 if (config.HasReceivedConnectionOptions() && | 150 if (config.HasReceivedConnectionOptions() && |
| 140 ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) { | 151 ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) { |
| 141 loss_algorithm_.reset(LossDetectionInterface::Create(kTime)); | 152 loss_algorithm_.reset(LossDetectionInterface::Create(kTime)); |
| 142 } | 153 } |
| 143 if (config.HasReceivedSocketReceiveBuffer()) { | 154 if (config.HasReceivedSocketReceiveBuffer()) { |
| 144 receive_buffer_bytes_ = | 155 receive_buffer_bytes_ = |
| 145 max(kMinSocketReceiveBuffer, | 156 max(kMinSocketReceiveBuffer, |
| 146 static_cast<QuicByteCount>(config.ReceivedSocketReceiveBuffer())); | 157 static_cast<QuicByteCount>(config.ReceivedSocketReceiveBuffer())); |
| 147 } | 158 } |
| 148 send_algorithm_->SetFromConfig(config, is_server_); | 159 send_algorithm_->SetFromConfig(config, is_server_, using_pacing_); |
| 149 | 160 |
| 150 if (network_change_visitor_ != nullptr) { | 161 if (network_change_visitor_ != nullptr) { |
| 151 network_change_visitor_->OnCongestionWindowChange(); | 162 network_change_visitor_->OnCongestionWindowChange(); |
| 152 } | 163 } |
| 153 } | 164 } |
| 154 | 165 |
| 155 void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) { | 166 void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) { |
| 156 if (n_connection_simulation_) { | 167 if (n_connection_simulation_) { |
| 157 // Ensure the number of connections is between 1 and 5. | 168 // Ensure the number of connections is between 1 and 5. |
| 158 send_algorithm_->SetNumEmulatedConnections( | 169 send_algorithm_->SetNumEmulatedConnections( |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 return; | 599 return; |
| 589 case RTO_MODE: | 600 case RTO_MODE: |
| 590 ++stats_->rto_count; | 601 ++stats_->rto_count; |
| 591 RetransmitAllPackets(); | 602 RetransmitAllPackets(); |
| 592 return; | 603 return; |
| 593 } | 604 } |
| 594 } | 605 } |
| 595 | 606 |
| 596 void QuicSentPacketManager::RetransmitCryptoPackets() { | 607 void QuicSentPacketManager::RetransmitCryptoPackets() { |
| 597 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); | 608 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); |
| 598 // TODO(ianswett): Typical TCP implementations only retransmit 5 times. | 609 ++consecutive_crypto_retransmission_count_; |
| 599 consecutive_crypto_retransmission_count_ = | |
| 600 min(kMaxHandshakeRetransmissionBackoffs, | |
| 601 consecutive_crypto_retransmission_count_ + 1); | |
| 602 bool packet_retransmitted = false; | 610 bool packet_retransmitted = false; |
| 603 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); | 611 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); |
| 604 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 612 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 605 it != unacked_packets_.end(); ++it, ++sequence_number) { | 613 it != unacked_packets_.end(); ++it, ++sequence_number) { |
| 606 // Only retransmit frames which are in flight, and therefore have been sent. | 614 // Only retransmit frames which are in flight, and therefore have been sent. |
| 607 if (!it->in_flight || it->retransmittable_frames == nullptr || | 615 if (!it->in_flight || it->retransmittable_frames == nullptr || |
| 608 it->retransmittable_frames->HasCryptoHandshake() != IS_HANDSHAKE) { | 616 it->retransmittable_frames->HasCryptoHandshake() != IS_HANDSHAKE) { |
| 609 continue; | 617 continue; |
| 610 } | 618 } |
| 611 packet_retransmitted = true; | 619 packet_retransmitted = true; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 } | 758 } |
| 751 | 759 |
| 752 QuicTime::Delta QuicSentPacketManager::TimeUntilSend( | 760 QuicTime::Delta QuicSentPacketManager::TimeUntilSend( |
| 753 QuicTime now, | 761 QuicTime now, |
| 754 HasRetransmittableData retransmittable) { | 762 HasRetransmittableData retransmittable) { |
| 755 // The TLP logic is entirely contained within QuicSentPacketManager, so the | 763 // The TLP logic is entirely contained within QuicSentPacketManager, so the |
| 756 // send algorithm does not need to be consulted. | 764 // send algorithm does not need to be consulted. |
| 757 if (pending_timer_transmission_count_ > 0) { | 765 if (pending_timer_transmission_count_ > 0) { |
| 758 return QuicTime::Delta::Zero(); | 766 return QuicTime::Delta::Zero(); |
| 759 } | 767 } |
| 760 if (unacked_packets_.bytes_in_flight() >= receive_buffer_bytes_) { | 768 if (unacked_packets_.bytes_in_flight() >= |
| 769 kUsableRecieveBufferFraction * receive_buffer_bytes_) { |
| 761 return QuicTime::Delta::Infinite(); | 770 return QuicTime::Delta::Infinite(); |
| 762 } | 771 } |
| 763 return send_algorithm_->TimeUntilSend( | 772 return send_algorithm_->TimeUntilSend( |
| 764 now, unacked_packets_.bytes_in_flight(), retransmittable); | 773 now, unacked_packets_.bytes_in_flight(), retransmittable); |
| 765 } | 774 } |
| 766 | 775 |
| 767 // Uses a 25ms delayed ack timer. Also helps with better signaling | 776 // Uses a 25ms delayed ack timer. Also helps with better signaling |
| 768 // in low-bandwidth (< ~384 kbps), where an ack is sent per packet. | 777 // in low-bandwidth (< ~384 kbps), where an ack is sent per packet. |
| 769 // Ensures that the Delayed Ack timer is always set to a value lesser | 778 // Ensures that the Delayed Ack timer is always set to a value lesser |
| 770 // than the retransmission timer's minimum value (MinRTO). We want the | 779 // than the retransmission timer's minimum value (MinRTO). We want the |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 // Set up a pacing sender with a 1 millisecond alarm granularity, the same as | 919 // Set up a pacing sender with a 1 millisecond alarm granularity, the same as |
| 911 // the default granularity of the Linux kernel's FQ qdisc. | 920 // the default granularity of the Linux kernel's FQ qdisc. |
| 912 using_pacing_ = true; | 921 using_pacing_ = true; |
| 913 send_algorithm_.reset( | 922 send_algorithm_.reset( |
| 914 new PacingSender(send_algorithm_.release(), | 923 new PacingSender(send_algorithm_.release(), |
| 915 QuicTime::Delta::FromMilliseconds(1), | 924 QuicTime::Delta::FromMilliseconds(1), |
| 916 kInitialUnpacedBurst)); | 925 kInitialUnpacedBurst)); |
| 917 } | 926 } |
| 918 | 927 |
| 919 } // namespace net | 928 } // namespace net |
| OLD | NEW |