| 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 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 bytes, | 460 bytes, |
| 461 has_retransmittable_data); | 461 has_retransmittable_data); |
| 462 unacked_packets_.SetSent(sequence_number, sent_time, bytes, in_flight); | 462 unacked_packets_.SetSent(sequence_number, sent_time, bytes, in_flight); |
| 463 | 463 |
| 464 // Reset the retransmission timer anytime a pending packet is sent. | 464 // Reset the retransmission timer anytime a pending packet is sent. |
| 465 return in_flight; | 465 return in_flight; |
| 466 } | 466 } |
| 467 | 467 |
| 468 void QuicSentPacketManager::OnRetransmissionTimeout() { | 468 void QuicSentPacketManager::OnRetransmissionTimeout() { |
| 469 DCHECK(unacked_packets_.HasInFlightPackets()); | 469 DCHECK(unacked_packets_.HasInFlightPackets()); |
| 470 DCHECK(!pending_tlp_transmission_); |
| 470 // Handshake retransmission, timer based loss detection, TLP, and RTO are | 471 // Handshake retransmission, timer based loss detection, TLP, and RTO are |
| 471 // implemented with a single alarm. The handshake alarm is set when the | 472 // implemented with a single alarm. The handshake alarm is set when the |
| 472 // handshake has not completed, the loss alarm is set when the loss detection | 473 // handshake has not completed, the loss alarm is set when the loss detection |
| 473 // algorithm says to, and the TLP and RTO alarms are set after that. | 474 // algorithm says to, and the TLP and RTO alarms are set after that. |
| 474 // The TLP alarm is always set to run for under an RTO. | 475 // The TLP alarm is always set to run for under an RTO. |
| 475 switch (GetRetransmissionMode()) { | 476 switch (GetRetransmissionMode()) { |
| 476 case HANDSHAKE_MODE: | 477 case HANDSHAKE_MODE: |
| 477 ++stats_->crypto_retransmit_count; | 478 ++stats_->crypto_retransmit_count; |
| 478 RetransmitCryptoPackets(); | 479 RetransmitCryptoPackets(); |
| 479 return; | 480 return; |
| 480 case LOSS_MODE: { | 481 case LOSS_MODE: { |
| 481 ++stats_->loss_timeout_count; | 482 ++stats_->loss_timeout_count; |
| 482 QuicByteCount bytes_in_flight = unacked_packets_.bytes_in_flight(); | 483 QuicByteCount bytes_in_flight = unacked_packets_.bytes_in_flight(); |
| 483 InvokeLossDetection(clock_->Now()); | 484 InvokeLossDetection(clock_->Now()); |
| 484 MaybeInvokeCongestionEvent(false, bytes_in_flight); | 485 MaybeInvokeCongestionEvent(false, bytes_in_flight); |
| 485 return; | 486 return; |
| 486 } | 487 } |
| 487 case TLP_MODE: | 488 case TLP_MODE: |
| 488 // If no tail loss probe can be sent, because there are no retransmittable | 489 // If no tail loss probe can be sent, because there are no retransmittable |
| 489 // packets, execute a conventional RTO to abandon old packets. | 490 // packets, execute a conventional RTO to abandon old packets. |
| 490 ++stats_->tlp_count; | 491 ++stats_->tlp_count; |
| 492 ++consecutive_tlp_count_; |
| 491 pending_tlp_transmission_ = true; | 493 pending_tlp_transmission_ = true; |
| 492 RetransmitOldestPacket(); | 494 // TLPs prefer sending new data instead of retransmitting data, so |
| 495 // give the connection a chance to write before completing the TLP. |
| 493 return; | 496 return; |
| 494 case RTO_MODE: | 497 case RTO_MODE: |
| 495 ++stats_->rto_count; | 498 ++stats_->rto_count; |
| 496 RetransmitAllPackets(); | 499 RetransmitAllPackets(); |
| 497 return; | 500 return; |
| 498 } | 501 } |
| 499 } | 502 } |
| 500 | 503 |
| 501 void QuicSentPacketManager::RetransmitCryptoPackets() { | 504 void QuicSentPacketManager::RetransmitCryptoPackets() { |
| 502 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); | 505 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 513 if (!it->second.in_flight || frames == NULL || | 516 if (!it->second.in_flight || frames == NULL || |
| 514 frames->HasCryptoHandshake() != IS_HANDSHAKE) { | 517 frames->HasCryptoHandshake() != IS_HANDSHAKE) { |
| 515 continue; | 518 continue; |
| 516 } | 519 } |
| 517 packet_retransmitted = true; | 520 packet_retransmitted = true; |
| 518 MarkForRetransmission(sequence_number, HANDSHAKE_RETRANSMISSION); | 521 MarkForRetransmission(sequence_number, HANDSHAKE_RETRANSMISSION); |
| 519 } | 522 } |
| 520 DCHECK(packet_retransmitted) << "No crypto packets found to retransmit."; | 523 DCHECK(packet_retransmitted) << "No crypto packets found to retransmit."; |
| 521 } | 524 } |
| 522 | 525 |
| 523 void QuicSentPacketManager::RetransmitOldestPacket() { | 526 bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() { |
| 524 DCHECK_EQ(TLP_MODE, GetRetransmissionMode()); | 527 if (!pending_tlp_transmission_) { |
| 525 ++consecutive_tlp_count_; | 528 return false; |
| 529 } |
| 526 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 530 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 527 it != unacked_packets_.end(); ++it) { | 531 it != unacked_packets_.end(); ++it) { |
| 528 QuicPacketSequenceNumber sequence_number = it->first; | 532 QuicPacketSequenceNumber sequence_number = it->first; |
| 529 const RetransmittableFrames* frames = it->second.retransmittable_frames; | 533 const RetransmittableFrames* frames = it->second.retransmittable_frames; |
| 530 // Only retransmit frames which are in flight, and therefore have been sent. | 534 // Only retransmit frames which are in flight, and therefore have been sent. |
| 531 if (!it->second.in_flight || frames == NULL) { | 535 if (!it->second.in_flight || frames == NULL) { |
| 532 continue; | 536 continue; |
| 533 } | 537 } |
| 534 DCHECK_NE(IS_HANDSHAKE, frames->HasCryptoHandshake()); | 538 DCHECK_NE(IS_HANDSHAKE, frames->HasCryptoHandshake()); |
| 535 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); | 539 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); |
| 536 return; | 540 return true; |
| 537 } | 541 } |
| 538 DLOG(FATAL) | 542 DLOG(FATAL) |
| 539 << "No retransmittable packets, so RetransmitOldestPacket failed."; | 543 << "No retransmittable packets, so RetransmitOldestPacket failed."; |
| 544 return false; |
| 540 } | 545 } |
| 541 | 546 |
| 542 void QuicSentPacketManager::RetransmitAllPackets() { | 547 void QuicSentPacketManager::RetransmitAllPackets() { |
| 543 DVLOG(1) << "RetransmitAllPackets() called with " | 548 DVLOG(1) << "RetransmitAllPackets() called with " |
| 544 << unacked_packets_.GetNumUnackedPackets() << " unacked packets."; | 549 << unacked_packets_.GetNumUnackedPackets() << " unacked packets."; |
| 545 // Request retransmission of all retransmittable packets when the RTO | 550 // Request retransmission of all retransmittable packets when the RTO |
| 546 // fires, and let the congestion manager decide how many to send | 551 // fires, and let the congestion manager decide how many to send |
| 547 // immediately and the remaining packets will be queued. | 552 // immediately and the remaining packets will be queued. |
| 548 // Abandon any non-retransmittable packets that are sufficiently old. | 553 // Abandon any non-retransmittable packets that are sufficiently old. |
| 549 bool packets_retransmitted = false; | 554 bool packets_retransmitted = false; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 // There may be a value in making this delay adaptive with the help of | 669 // There may be a value in making this delay adaptive with the help of |
| 665 // the sender and a signaling mechanism -- if the sender uses a | 670 // the sender and a signaling mechanism -- if the sender uses a |
| 666 // different MinRTO, we may get spurious retransmissions. May not have | 671 // different MinRTO, we may get spurious retransmissions. May not have |
| 667 // any benefits, but if the delayed ack becomes a significant source | 672 // any benefits, but if the delayed ack becomes a significant source |
| 668 // of (likely, tail) latency, then consider such a mechanism. | 673 // of (likely, tail) latency, then consider such a mechanism. |
| 669 const QuicTime::Delta QuicSentPacketManager::DelayedAckTime() const { | 674 const QuicTime::Delta QuicSentPacketManager::DelayedAckTime() const { |
| 670 return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2); | 675 return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2); |
| 671 } | 676 } |
| 672 | 677 |
| 673 const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { | 678 const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { |
| 674 // Don't set the timer if there are no packets in flight. | 679 // Don't set the timer if there are no packets in flight or we've already |
| 675 if (!unacked_packets_.HasInFlightPackets()) { | 680 // queued a tlp transmission and it hasn't been sent yet. |
| 681 if (!unacked_packets_.HasInFlightPackets() || pending_tlp_transmission_) { |
| 676 return QuicTime::Zero(); | 682 return QuicTime::Zero(); |
| 677 } | 683 } |
| 678 switch (GetRetransmissionMode()) { | 684 switch (GetRetransmissionMode()) { |
| 679 case HANDSHAKE_MODE: | 685 case HANDSHAKE_MODE: |
| 680 return clock_->ApproximateNow().Add(GetCryptoRetransmissionDelay()); | 686 return clock_->ApproximateNow().Add(GetCryptoRetransmissionDelay()); |
| 681 case LOSS_MODE: | 687 case LOSS_MODE: |
| 682 return loss_algorithm_->GetLossTimeout(); | 688 return loss_algorithm_->GetLossTimeout(); |
| 683 case TLP_MODE: { | 689 case TLP_MODE: { |
| 684 // TODO(ianswett): When CWND is available, it would be preferable to | 690 // TODO(ianswett): When CWND is available, it would be preferable to |
| 685 // set the timer based on the earliest retransmittable packet. | 691 // set the timer based on the earliest retransmittable packet. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 } | 776 } |
| 771 | 777 |
| 772 // Set up a pacing sender with a 5 millisecond alarm granularity. | 778 // Set up a pacing sender with a 5 millisecond alarm granularity. |
| 773 using_pacing_ = true; | 779 using_pacing_ = true; |
| 774 send_algorithm_.reset( | 780 send_algorithm_.reset( |
| 775 new PacingSender(send_algorithm_.release(), | 781 new PacingSender(send_algorithm_.release(), |
| 776 QuicTime::Delta::FromMilliseconds(5))); | 782 QuicTime::Delta::FromMilliseconds(5))); |
| 777 } | 783 } |
| 778 | 784 |
| 779 } // namespace net | 785 } // namespace net |
| OLD | NEW |