// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // The is the base class for QUIC send side congestion control. // It decides when we can send a QUIC packet to the wire. // This class handles the basic bookkeeping of sent bitrate and packet loss. // The actual send side algorithm is implemented via the // SendAlgorithmInterface. #ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_ #define NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_ #include #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "net/base/net_export.h" #include "net/quic/congestion_control/quic_receipt_metrics_collector.h" #include "net/quic/congestion_control/send_algorithm_interface.h" #include "net/quic/quic_clock.h" #include "net/quic/quic_time.h" namespace net { const uint32 kBitrateSmoothingBuckets = 300; // 10 ms in micro seconds, must be less than 1 second for current // implementation due to overflow resulting in a potential divide by zero. const uint32 kBitrateSmoothingPeriod = 10000; class NET_EXPORT_PRIVATE QuicSendScheduler { public: class PendingPacket { public: PendingPacket(size_t bytes, QuicTime timestamp) : bytes_sent_(bytes), send_timestamp_(timestamp) { } size_t BytesSent() { return bytes_sent_; } QuicTime& SendTimestamp() { return send_timestamp_; } private: size_t bytes_sent_; QuicTime send_timestamp_; }; typedef std::map PendingPacketsMap; // Enable pacing to prevent a large congestion window to be sent all at once, // when pacing is enabled a large congestion window will be sent in multiple // bursts of packet(s) instead of one big burst that might introduce packet // loss. QuicSendScheduler(const QuicClock* clock, CongestionFeedbackType congestion_type); virtual ~QuicSendScheduler(); // Called when we have received an ack frame from remote peer. virtual void OnIncomingAckFrame(const QuicAckFrame& ack_frame); // Called when we have received an congestion feedback frame from remote peer. virtual void OnIncomingQuicCongestionFeedbackFrame( const QuicCongestionFeedbackFrame& congestion_feedback_frame); // Inform that we sent x bytest to the wire, and if that was a retransmission. // Note: this function must be called for every packet sent to the wire. virtual void SentPacket(QuicPacketSequenceNumber sequence_number, size_t bytes, bool retransmit); // Calculate the time until we can send the next packet to the wire. // Note 1: When kUnknownWaitTime is returned, there is no need to poll // TimeUntilSend again until we receive an OnIncomingAckFrame event. // Note 2: Send algorithms may or may not use |retransmit| in their // calculations. virtual QuicTime::Delta TimeUntilSend(bool retransmit); // Returns the current available congestion window in bytes, the number of // bytes that can be sent now. // Note: due to pacing this function might return a smaller value than the // real available congestion window. This way we hold off the sender to avoid // queuing in the lower layers in the stack. size_t AvailableCongestionWindow(); int BandwidthEstimate(); // Current estimate, in bytes per second. int SentBandwidth(); // Current smooth acctually sent, in bytes per second. int PeakSustainedBandwidth(); // In bytes per second. private: // Have we sent any packets during this session? bool HasSentPacket(); int UpdatePacketHistory(); const QuicClock* clock_; int current_estimated_bandwidth_; int max_estimated_bandwidth_; QuicTime last_sent_packet_; // To keep track of the real sent bitrate we keep track of the last sent bytes // by keeping an array containing the number of bytes sent in a short timespan // kBitrateSmoothingPeriod; multiple of these buckets kBitrateSmoothingBuckets // create a time window in which we calculate the average bitrate. int current_packet_bucket_; // Last active bucket in window. int first_packet_bucket_; // First active bucket in window. uint32 packet_history_[kBitrateSmoothingBuckets]; // The window. scoped_ptr send_algorithm_; // TODO(pwestin): should we combine the packet_history_ bucket with this map? // For now I keep it separate for easy implementation. PendingPacketsMap pending_packets_; }; } // namespace net #endif // NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_