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