tcp_cubic_sender.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/congestion_control/tcp_cubic_sender.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Constants based on TCP defaults.
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kHybridStartLowWindow = 16;
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const QuicByteCount kMaxSegmentSize = kMaxPacketSize;
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const QuicByteCount kDefaultReceiveWindow = 64000;
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kInitialCongestionWindow = 10;
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxBurstLength = 3;
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kInitialRttMs = 60;  // At a typical RTT 60 ms.
17558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst float kAlpha = 0.125f;
18558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst float kOneMinusAlpha = (1 - kAlpha);
19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst float kBeta = 0.25f;
20558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst float kOneMinusBeta = (1 - kBeta);
21558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch};  // namespace
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTcpCubicSender::TcpCubicSender(
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const QuicClock* clock,
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bool reno,
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    QuicTcpCongestionWindow max_tcp_congestion_window)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : hybrid_slow_start_(clock),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cubic_(clock),
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reno_(reno),
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      congestion_window_count_(0),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      receiver_congestion_window_(kDefaultReceiveWindow),
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_received_accumulated_number_of_lost_packets_(0),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_in_flight_(0),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update_end_sequence_number_(true),
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      end_sequence_number_(0),
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      congestion_window_(kInitialCongestionWindow),
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      slowstart_threshold_(max_tcp_congestion_window),
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      max_tcp_congestion_window_(max_tcp_congestion_window),
39558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      delay_min_(QuicTime::Delta::Zero()),
40558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      smoothed_rtt_(QuicTime::Delta::Zero()),
41558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      mean_deviation_(QuicTime::Delta::Zero()) {
42558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
43558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
44558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTcpCubicSender::~TcpCubicSender() {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame(
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const QuicCongestionFeedbackFrame& feedback,
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicTime feedback_receive_time,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SentPacketsMap& /*sent_packets*/) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (last_received_accumulated_number_of_lost_packets_ !=
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      feedback.tcp.accumulated_number_of_lost_packets) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int recovered_lost_packets =
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_received_accumulated_number_of_lost_packets_ -
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        feedback.tcp.accumulated_number_of_lost_packets;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_received_accumulated_number_of_lost_packets_ =
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        feedback.tcp.accumulated_number_of_lost_packets;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (recovered_lost_packets > 0) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnIncomingLoss(feedback_receive_time);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  receiver_congestion_window_ = feedback.tcp.receive_window;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::OnIncomingAck(
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicPacketSequenceNumber acked_sequence_number, QuicByteCount acked_bytes,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicTime::Delta rtt) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bytes_in_flight_ -= acked_bytes;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CongestionAvoidance(acked_sequence_number);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckAccounting(rtt);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (end_sequence_number_ == acked_sequence_number) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(INFO) << "Start update end sequence number @" << acked_sequence_number;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_end_sequence_number_ = true;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In a normal TCP we would need to know the lowest missing packet to detect
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if we receive 3 missing packets. Here we get a missing packet for which we
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // enter TCP Fast Retransmit immediately.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (reno_) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    congestion_window_ = congestion_window_ >> 1;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    slowstart_threshold_ = congestion_window_;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    congestion_window_ =
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    slowstart_threshold_ = congestion_window_;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity, make sure that we don't end up with an empty window.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (congestion_window_ == 0) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    congestion_window_ = 1;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DLOG(INFO) << "Incoming loss; congestion window:" << congestion_window_;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::SentPacket(QuicTime /*sent_time*/,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                QuicPacketSequenceNumber sequence_number,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                QuicByteCount bytes,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                Retransmission is_retransmission) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bytes_in_flight_ += bytes;
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (is_retransmission == NOT_RETRANSMISSION && update_end_sequence_number_) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    end_sequence_number_ = sequence_number;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (AvailableCongestionWindow() == 0) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update_end_sequence_number_ = false;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(INFO) << "Stop update end sequence number @" << sequence_number;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::AbandoningPacket(QuicPacketSequenceNumber sequence_number,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      QuicByteCount abandoned_bytes) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bytes_in_flight_ -= abandoned_bytes;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicTime::Delta TcpCubicSender::TimeUntilSend(
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicTime now,
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Retransmission is_retransmission,
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    HasRetransmittableData has_retransmittable_data,
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    IsHandshake handshake) {
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (is_retransmission == IS_RETRANSMISSION ||
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      has_retransmittable_data == NO_RETRANSMITTABLE_DATA ||
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      handshake == IS_HANDSHAKE) {
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // For TCP we can always send a retransmission,  or an ACK immediately.
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // We also immediately send any handshake packet (CHLO, etc.).  We provide
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // this  special dispensation for handshake messages in QUIC, although the
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // concept is not present in TCP.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicTime::Delta::Zero();
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (AvailableCongestionWindow() == 0) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicTime::Delta::Infinite();
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return QuicTime::Delta::Zero();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicByteCount TcpCubicSender::AvailableCongestionWindow() {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bytes_in_flight_ > CongestionWindow()) {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CongestionWindow() - bytes_in_flight_;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicByteCount TcpCubicSender::CongestionWindow() {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // What's the current congestion window in bytes.
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::min(receiver_congestion_window_,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  congestion_window_ * kMaxSegmentSize);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicBandwidth TcpCubicSender::BandwidthEstimate() {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(pwestin): make a long term estimate, based on RTT and loss rate? or
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // instantaneous estimate?
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Throughput ~= (1/RTT)*sqrt(3/2p)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return QuicBandwidth::Zero();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicTime::Delta TcpCubicSender::SmoothedRtt() {
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (smoothed_rtt_.IsZero()) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicTime::Delta::FromMilliseconds(kInitialRttMs);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return smoothed_rtt_;
160558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
161558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
162558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochQuicTime::Delta TcpCubicSender::RetransmissionDelay() {
163558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return QuicTime::Delta::FromMicroseconds(
164558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds());
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::Reset() {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delay_min_ = QuicTime::Delta::Zero();
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hybrid_slow_start_.Restart();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TcpCubicSender::IsCwndLimited() const {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const QuicByteCount congestion_window_bytes = congestion_window_ *
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kMaxSegmentSize;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bytes_in_flight_ >= congestion_window_bytes) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const QuicByteCount tcp_max_burst = kMaxBurstLength * kMaxSegmentSize;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const QuicByteCount left = congestion_window_bytes - bytes_in_flight_;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return left <= tcp_max_burst;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called when we receive and ack. Normal TCP tracks how many packets one ack
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// represents, but quic has a separate ack for each packet.
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsCwndLimited()) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We don't update the congestion window unless we are close to using the
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // window we have available.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (congestion_window_ < slowstart_threshold_) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Slow start.
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (hybrid_slow_start_.EndOfRound(ack)) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hybrid_slow_start_.Reset(end_sequence_number_);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // congestion_window_cnt is the number of acks since last change of snd_cwnd
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (congestion_window_ < max_tcp_congestion_window_) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // TCP slow start, exponentail growth, increase by one for each ACK.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      congestion_window_++;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(INFO) << "Slow start; congestion window:" << congestion_window_;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (congestion_window_ < max_tcp_congestion_window_) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (reno_) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Classic Reno congestion avoidance provided for testing.
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (congestion_window_count_ >= congestion_window_) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          congestion_window_++;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          congestion_window_count_ = 0;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          congestion_window_count_++;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(INFO) << "Reno; congestion window:" << congestion_window_;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        congestion_window_ = cubic_.CongestionWindowAfterAck(congestion_window_,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                             delay_min_);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(INFO) << "Cubic; congestion window:" << congestion_window_;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(pwestin): what is the timout value?
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::OnTimeOut() {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cubic_.Reset();
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  congestion_window_ = 1;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TcpCubicSender::AckAccounting(QuicTime::Delta rtt) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rtt.IsInfinite() || rtt.IsZero()) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // RTT can't be negative.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LT(0, rtt.ToMicroseconds());
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(pwestin): Discard delay samples right after fast recovery,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // during 1 second?.
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First time call or link delay decreases.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delay_min_.IsZero() || delay_min_ > rtt) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delay_min_ = rtt;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // First time call.
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (smoothed_rtt_.IsZero()) {
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    smoothed_rtt_ = rtt;
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    mean_deviation_ = QuicTime::Delta::FromMicroseconds(
246558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        rtt.ToMicroseconds() / 2);
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  } else {
248558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    mean_deviation_ = QuicTime::Delta::FromMicroseconds(
249558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        kOneMinusBeta * mean_deviation_.ToMicroseconds() +
250558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        kBeta * abs(smoothed_rtt_.ToMicroseconds() - rtt.ToMicroseconds()));
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    smoothed_rtt_ = QuicTime::Delta::FromMicroseconds(
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() +
253558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        kAlpha * rtt.ToMicroseconds());
254558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DLOG(INFO) << "Cubic; mean_deviation_:" << mean_deviation_.ToMicroseconds();
255558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
256558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Hybrid start triggers when cwnd is larger than some threshold.
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (congestion_window_ <= slowstart_threshold_ &&
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      congestion_window_ >= kHybridStartLowWindow) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!hybrid_slow_start_.started()) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Time to start the hybrid slow start.
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hybrid_slow_start_.Reset(end_sequence_number_);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hybrid_slow_start_.Update(rtt, delay_min_);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (hybrid_slow_start_.Exit()) {
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      slowstart_threshold_ = congestion_window_;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
272