Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_sent_packet_manager.cc
index 806297e..292afa6 100644 (file)
@@ -20,6 +20,11 @@ using std::max;
 using std::min;
 
 namespace net {
+
+// The length of the recent min rtt window in seconds. Windowing is disabled for
+// values less than or equal to 0.
+int32 FLAGS_quic_recent_min_rtt_window_s = 60;
+
 namespace {
 static const int kDefaultRetransmissionTimeMs = 500;
 // TCP RFC calls for 1 second RTO however Linux differs from this default and
@@ -41,6 +46,9 @@ static const int64 kMinTailLossProbeTimeoutMs = 10;
 // Number of samples before we force a new recent min rtt to be captured.
 static const size_t kNumMinRttSamplesAfterQuiescence = 2;
 
+// Number of unpaced packets to send after quiescence.
+static const size_t kInitialUnpacedBurst = 10;
+
 bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
   if (transmission_info.retransmittable_frames == NULL) {
     return false;
@@ -53,26 +61,32 @@ bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
 
 #define ENDPOINT (is_server_ ? "Server: " : " Client: ")
 
-QuicSentPacketManager::QuicSentPacketManager(bool is_server,
-                                             const QuicClock* clock,
-                                             QuicConnectionStats* stats,
-                                             CongestionFeedbackType type,
-                                             LossDetectionType loss_type)
+QuicSentPacketManager::QuicSentPacketManager(
+    bool is_server,
+    const QuicClock* clock,
+    QuicConnectionStats* stats,
+    CongestionControlType congestion_control_type,
+    LossDetectionType loss_type)
     : unacked_packets_(),
       is_server_(is_server),
       clock_(clock),
       stats_(stats),
       debug_delegate_(NULL),
-      send_algorithm_(
-          SendAlgorithmInterface::Create(clock, &rtt_stats_, type, stats)),
+      network_change_visitor_(NULL),
+      send_algorithm_(SendAlgorithmInterface::Create(clock,
+                                                     &rtt_stats_,
+                                                     congestion_control_type,
+                                                     stats)),
       loss_algorithm_(LossDetectionInterface::Create(loss_type)),
       largest_observed_(0),
+      first_rto_transmission_(0),
       consecutive_rto_count_(0),
       consecutive_tlp_count_(0),
       consecutive_crypto_retransmission_count_(0),
       pending_tlp_transmission_(false),
       max_tail_loss_probes_(kDefaultMaxTailLossProbes),
-      using_pacing_(false) {
+      using_pacing_(false),
+      handshake_confirmed_(false) {
 }
 
 QuicSentPacketManager::~QuicSentPacketManager() {
@@ -85,19 +99,37 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
                                       config.ReceivedInitialRoundTripTimeUs()));
   }
   // TODO(ianswett): BBR is currently a server only feature.
-  if (config.HasReceivedCongestionOptions() &&
-      ContainsQuicTag(config.ReceivedCongestionOptions(), kTBBR)) {
+  if (config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
+    if (FLAGS_quic_recent_min_rtt_window_s > 0) {
+      rtt_stats_.set_recent_min_rtt_window(
+          QuicTime::Delta::FromSeconds(FLAGS_quic_recent_min_rtt_window_s));
+    }
     send_algorithm_.reset(
-        SendAlgorithmInterface::Create(clock_, &rtt_stats_, kTCPBBR, stats_));
+        SendAlgorithmInterface::Create(clock_, &rtt_stats_, kBBR, stats_));
   }
-  if (config.congestion_feedback() == kPACE) {
+  if (config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
+    send_algorithm_.reset(
+        SendAlgorithmInterface::Create(clock_, &rtt_stats_, kReno, stats_));
+  }
+  if (config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kPACE)) {
     MaybeEnablePacing();
   }
-  if (config.HasReceivedLossDetection() &&
-      config.ReceivedLossDetection() == kTIME) {
+  // TODO(ianswett): Remove the "HasReceivedLossDetection" branch once
+  // the ConnectionOptions code is live everywhere.
+  if ((config.HasReceivedLossDetection() &&
+       config.ReceivedLossDetection() == kTIME) ||
+      (config.HasReceivedConnectionOptions() &&
+       ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME))) {
     loss_algorithm_.reset(LossDetectionInterface::Create(kTime));
   }
   send_algorithm_->SetFromConfig(config, is_server_);
+
+  if (network_change_visitor_ != NULL) {
+    network_change_visitor_->OnCongestionWindowChange(GetCongestionWindow());
+  }
 }
 
 // TODO(ianswett): Combine this method with OnPacketSent once packets are always
@@ -134,29 +166,35 @@ void QuicSentPacketManager::OnRetransmittedPacket(
   unacked_packets_.OnRetransmittedPacket(old_sequence_number,
                                          new_sequence_number,
                                          transmission_type);
+
+  if (debug_delegate_ != NULL) {
+    debug_delegate_->OnRetransmittedPacket(old_sequence_number,
+        new_sequence_number,
+        transmission_type,
+        clock_->ApproximateNow());
+  }
 }
 
-void QuicSentPacketManager::OnIncomingAck(
-    const ReceivedPacketInfo& received_info,
-    QuicTime ack_receive_time) {
+void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
+                                          QuicTime ack_receive_time) {
   QuicByteCount bytes_in_flight = unacked_packets_.bytes_in_flight();
 
   // We rely on delta_time_largest_observed to compute an RTT estimate, so
   // we only update rtt when the largest observed gets acked.
-  bool largest_observed_acked = MaybeUpdateRTT(received_info, ack_receive_time);
-  if (largest_observed_ < received_info.largest_observed) {
-    largest_observed_ = received_info.largest_observed;
+  bool largest_observed_acked = MaybeUpdateRTT(ack_frame, ack_receive_time);
+  if (largest_observed_ < ack_frame.largest_observed) {
+    largest_observed_ = ack_frame.largest_observed;
     unacked_packets_.IncreaseLargestObserved(largest_observed_);
   }
-  HandleAckForSentPackets(received_info);
+  HandleAckForSentPackets(ack_frame);
   InvokeLossDetection(ack_receive_time);
   MaybeInvokeCongestionEvent(largest_observed_acked, bytes_in_flight);
 
   // If we have received a truncated ack, then we need to clear out some
   // previous transmissions to allow the peer to actually ACK new packets.
-  if (received_info.is_truncated) {
+  if (ack_frame.is_truncated) {
     unacked_packets_.ClearPreviousRetransmissions(
-        received_info.missing_packets.size() / 2);
+        ack_frame.missing_packets.size() / 2);
   }
 
   // Anytime we are making forward progress and have a new RTT estimate, reset
@@ -167,40 +205,51 @@ void QuicSentPacketManager::OnIncomingAck(
     consecutive_tlp_count_ = 0;
     consecutive_crypto_retransmission_count_ = 0;
   }
+
+  if (debug_delegate_ != NULL) {
+    debug_delegate_->OnIncomingAck(ack_frame,
+                                   ack_receive_time,
+                                   largest_observed_,
+                                   largest_observed_acked,
+                                   GetLeastUnackedSentPacket());
+  }
 }
 
 void QuicSentPacketManager::MaybeInvokeCongestionEvent(
     bool rtt_updated, QuicByteCount bytes_in_flight) {
-  if (rtt_updated || !packets_acked_.empty() ||
-      !packets_lost_.empty()) {
-    send_algorithm_->OnCongestionEvent(
-        rtt_updated, bytes_in_flight, packets_acked_, packets_lost_);
-    packets_acked_.clear();
-    packets_lost_.clear();
+  if (!rtt_updated && packets_acked_.empty() && packets_lost_.empty()) {
+    return;
+  }
+  send_algorithm_->OnCongestionEvent(rtt_updated, bytes_in_flight,
+                                     packets_acked_, packets_lost_);
+  packets_acked_.clear();
+  packets_lost_.clear();
+  if (network_change_visitor_ != NULL) {
+    network_change_visitor_->OnCongestionWindowChange(GetCongestionWindow());
   }
 }
 
 void QuicSentPacketManager::HandleAckForSentPackets(
-    const ReceivedPacketInfo& received_info) {
+    const QuicAckFrame& ack_frame) {
   // Go through the packets we have not received an ack for and see if this
   // incoming_ack shows they've been seen by the peer.
   QuicTime::Delta delta_largest_observed =
-      received_info.delta_time_largest_observed;
+      ack_frame.delta_time_largest_observed;
   QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
   while (it != unacked_packets_.end()) {
     QuicPacketSequenceNumber sequence_number = it->first;
-    if (sequence_number > received_info.largest_observed) {
+    if (sequence_number > ack_frame.largest_observed) {
       // These packets are still in flight.
       break;
     }
 
-    if (IsAwaitingPacket(received_info, sequence_number)) {
+    if (IsAwaitingPacket(ack_frame, sequence_number)) {
       // Consider it multiple nacks when there is a gap between the missing
       // packet and the largest observed, since the purpose of a nack
       // threshold is to tolerate re-ordering.  This handles both StretchAcks
       // and Forward Acks.
       // The nack count only increases when the largest observed increases.
-      size_t min_nacks = received_info.largest_observed - sequence_number;
+      size_t min_nacks = ack_frame.largest_observed - sequence_number;
       // Truncated acks can nack the largest observed, so use a min of 1.
       if (min_nacks == 0) {
         min_nacks = 1;
@@ -221,8 +270,8 @@ void QuicSentPacketManager::HandleAckForSentPackets(
 
   // Discard any retransmittable frames associated with revived packets.
   for (SequenceNumberSet::const_iterator revived_it =
-           received_info.revived_packets.begin();
-       revived_it != received_info.revived_packets.end(); ++revived_it) {
+           ack_frame.revived_packets.begin();
+       revived_it != ack_frame.revived_packets.end(); ++revived_it) {
     MarkPacketRevived(*revived_it, delta_largest_observed);
   }
 }
@@ -289,6 +338,22 @@ void QuicSentPacketManager::MarkForRetransmission(
 void QuicSentPacketManager::RecordSpuriousRetransmissions(
     const SequenceNumberSet& all_transmissions,
     QuicPacketSequenceNumber acked_sequence_number) {
+  if (acked_sequence_number < first_rto_transmission_) {
+    // Cancel all pending RTO transmissions and restore their in flight status.
+    // Replace SRTT with latest_rtt and increase the variance to prevent
+    // a spurious RTO from happening again.
+    rtt_stats_.ExpireSmoothedMetrics();
+    for (PendingRetransmissionMap::const_iterator it =
+             pending_retransmissions_.begin();
+         it != pending_retransmissions_.end(); ++it) {
+      DCHECK_EQ(it->second, RTO_RETRANSMISSION);
+      unacked_packets_.RestoreInFlight(it->first);
+    }
+    pending_retransmissions_.clear();
+    send_algorithm_->RevertRetransmissionTimeout();
+    first_rto_transmission_ = 0;
+    ++stats_->spurious_rto_count;
+  }
   for (SequenceNumberSet::const_iterator
            it = all_transmissions.upper_bound(acked_sequence_number),
            end = all_transmissions.end();
@@ -461,6 +526,10 @@ bool QuicSentPacketManager::OnPacketSent(
                                     has_retransmittable_data);
   unacked_packets_.SetSent(sequence_number, sent_time, bytes, in_flight);
 
+  if (debug_delegate_ != NULL) {
+    debug_delegate_->OnSentPacket(sequence_number, sent_time, bytes);
+  }
+
   // Reset the retransmission timer anytime a pending packet is sent.
   return in_flight;
 }
@@ -535,7 +604,9 @@ bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
     if (!it->second.in_flight || frames == NULL) {
       continue;
     }
-    DCHECK_NE(IS_HANDSHAKE, frames->HasCryptoHandshake());
+    if (!handshake_confirmed_) {
+      DCHECK_NE(IS_HANDSHAKE, frames->HasCryptoHandshake());
+    }
     MarkForRetransmission(sequence_number, TLP_RETRANSMISSION);
     return true;
   }
@@ -567,14 +638,21 @@ void QuicSentPacketManager::RetransmitAllPackets() {
 
   send_algorithm_->OnRetransmissionTimeout(packets_retransmitted);
   if (packets_retransmitted) {
+    if (consecutive_rto_count_ == 0) {
+      first_rto_transmission_ = unacked_packets_.largest_sent_packet() + 1;
+    }
     ++consecutive_rto_count_;
   }
+
+  if (network_change_visitor_ != NULL) {
+    network_change_visitor_->OnCongestionWindowChange(GetCongestionWindow());
+  }
 }
 
 QuicSentPacketManager::RetransmissionTimeoutMode
     QuicSentPacketManager::GetRetransmissionMode() const {
   DCHECK(unacked_packets_.HasInFlightPackets());
-  if (unacked_packets_.HasPendingCryptoPackets()) {
+  if (!handshake_confirmed_ && unacked_packets_.HasPendingCryptoPackets()) {
     return HANDSHAKE_MODE;
   }
   if (loss_algorithm_->GetLossTimeout() != QuicTime::Zero()) {
@@ -626,15 +704,15 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) {
 }
 
 bool QuicSentPacketManager::MaybeUpdateRTT(
-    const ReceivedPacketInfo& received_info,
+    const QuicAckFrame& ack_frame,
     const QuicTime& ack_receive_time) {
-  if (!unacked_packets_.IsUnacked(received_info.largest_observed)) {
+  if (!unacked_packets_.IsUnacked(ack_frame.largest_observed)) {
     return false;
   }
   // We calculate the RTT based on the highest ACKed sequence number, the lower
   // sequence numbers will include the ACK aggregation delay.
   const TransmissionInfo& transmission_info =
-      unacked_packets_.GetTransmissionInfo(received_info.largest_observed);
+      unacked_packets_.GetTransmissionInfo(ack_frame.largest_observed);
   // Don't update the RTT if it hasn't been sent.
   if (transmission_info.sent_time == QuicTime::Zero()) {
     return false;
@@ -643,7 +721,7 @@ bool QuicSentPacketManager::MaybeUpdateRTT(
   QuicTime::Delta send_delta =
       ack_receive_time.Subtract(transmission_info.sent_time);
   rtt_stats_.UpdateRtt(
-      send_delta, received_info.delta_time_largest_observed, ack_receive_time);
+      send_delta, ack_frame.delta_time_largest_observed, ack_receive_time);
   return true;
 }
 
@@ -659,6 +737,8 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
       now, unacked_packets_.bytes_in_flight(), retransmittable);
 }
 
+// Uses a 25ms delayed ack timer. Also helps with better signaling
+// in low-bandwidth (< ~384 kbps), where an ack is sent per packet.
 // Ensures that the Delayed Ack timer is always set to a value lesser
 // than the retransmission timer's minimum value (MinRTO). We want the
 // delayed ack to get back to the QUIC peer before the sender's
@@ -672,7 +752,8 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
 // any benefits, but if the delayed ack becomes a significant source
 // of (likely, tail) latency, then consider such a mechanism.
 const QuicTime::Delta QuicSentPacketManager::DelayedAckTime() const {
-  return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
+  return QuicTime::Delta::FromMilliseconds(min(kMaxDelayedAckTime,
+                                               kMinRetransmissionTimeMs/2));
 }
 
 const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
@@ -699,12 +780,11 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
       // The RTO is based on the first outstanding packet.
       const QuicTime sent_time =
           unacked_packets_.GetFirstInFlightPacketSentTime();
-      QuicTime rto_timeout = sent_time.Add(GetRetransmissionDelay());
-      // Always wait at least 1.5 * RTT from now.
-      QuicTime min_timeout = clock_->ApproximateNow().Add(
-          rtt_stats_.SmoothedRtt().Multiply(1.5));
-
-      return QuicTime::Max(min_timeout, rto_timeout);
+      QuicTime rto_time = sent_time.Add(GetRetransmissionDelay());
+      // Wait for TLP packets to be acked before an RTO fires.
+      QuicTime tlp_time =
+          unacked_packets_.GetLastPacketSentTime().Add(GetTailLossProbeDelay());
+      return QuicTime::Max(tlp_time, rto_time);
     }
   }
   DCHECK(false);
@@ -725,7 +805,8 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
   QuicTime::Delta srtt = rtt_stats_.SmoothedRtt();
   if (!unacked_packets_.HasMultipleInFlightPackets()) {
     return QuicTime::Delta::Max(
-        srtt.Multiply(1.5).Add(DelayedAckTime()), srtt.Multiply(2));
+        srtt.Multiply(2), srtt.Multiply(1.5)
+          .Add(QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2)));
   }
   return QuicTime::Delta::FromMilliseconds(
       max(kMinTailLossProbeTimeoutMs,
@@ -762,10 +843,18 @@ QuicBandwidth QuicSentPacketManager::BandwidthEstimate() const {
   return send_algorithm_->BandwidthEstimate();
 }
 
+bool QuicSentPacketManager::HasReliableBandwidthEstimate() const {
+  return send_algorithm_->HasReliableBandwidthEstimate();
+}
+
 QuicByteCount QuicSentPacketManager::GetCongestionWindow() const {
   return send_algorithm_->GetCongestionWindow();
 }
 
+QuicByteCount QuicSentPacketManager::GetSlowStartThreshold() const {
+  return send_algorithm_->GetSlowStartThreshold();
+}
+
 void QuicSentPacketManager::MaybeEnablePacing() {
   if (!FLAGS_enable_quic_pacing) {
     return;
@@ -779,7 +868,8 @@ void QuicSentPacketManager::MaybeEnablePacing() {
   using_pacing_ = true;
   send_algorithm_.reset(
       new PacingSender(send_algorithm_.release(),
-                       QuicTime::Delta::FromMilliseconds(5)));
+                       QuicTime::Delta::FromMilliseconds(5),
+                       kInitialUnpacedBurst));
 }
 
 }  // namespace net