1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/congestion_control/prr_sender.h"
6
7 #include "quiche/quic/core/quic_packets.h"
8
9 namespace quic {
10
PrrSender()11 PrrSender::PrrSender()
12 : bytes_sent_since_loss_(0),
13 bytes_delivered_since_loss_(0),
14 ack_count_since_loss_(0),
15 bytes_in_flight_before_loss_(0) {}
16
OnPacketSent(QuicByteCount sent_bytes)17 void PrrSender::OnPacketSent(QuicByteCount sent_bytes) {
18 bytes_sent_since_loss_ += sent_bytes;
19 }
20
OnPacketLost(QuicByteCount prior_in_flight)21 void PrrSender::OnPacketLost(QuicByteCount prior_in_flight) {
22 bytes_sent_since_loss_ = 0;
23 bytes_in_flight_before_loss_ = prior_in_flight;
24 bytes_delivered_since_loss_ = 0;
25 ack_count_since_loss_ = 0;
26 }
27
OnPacketAcked(QuicByteCount acked_bytes)28 void PrrSender::OnPacketAcked(QuicByteCount acked_bytes) {
29 bytes_delivered_since_loss_ += acked_bytes;
30 ++ack_count_since_loss_;
31 }
32
CanSend(QuicByteCount congestion_window,QuicByteCount bytes_in_flight,QuicByteCount slowstart_threshold) const33 bool PrrSender::CanSend(QuicByteCount congestion_window,
34 QuicByteCount bytes_in_flight,
35 QuicByteCount slowstart_threshold) const {
36 // Return QuicTime::Zero in order to ensure limited transmit always works.
37 if (bytes_sent_since_loss_ == 0 || bytes_in_flight < kMaxSegmentSize) {
38 return true;
39 }
40 if (congestion_window > bytes_in_flight) {
41 // During PRR-SSRB, limit outgoing packets to 1 extra MSS per ack, instead
42 // of sending the entire available window. This prevents burst retransmits
43 // when more packets are lost than the CWND reduction.
44 // limit = MAX(prr_delivered - prr_out, DeliveredData) + MSS
45 if (bytes_delivered_since_loss_ + ack_count_since_loss_ * kMaxSegmentSize <=
46 bytes_sent_since_loss_) {
47 return false;
48 }
49 return true;
50 }
51 // Implement Proportional Rate Reduction (RFC6937).
52 // Checks a simplified version of the PRR formula that doesn't use division:
53 // AvailableSendWindow =
54 // CEIL(prr_delivered * ssthresh / BytesInFlightAtLoss) - prr_sent
55 if (bytes_delivered_since_loss_ * slowstart_threshold >
56 bytes_sent_since_loss_ * bytes_in_flight_before_loss_) {
57 return true;
58 }
59 return false;
60 }
61
62 } // namespace quic
63