// Copyright (c) 2013 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. // This class is a helper class to the inter arrival congestion control. It // provide a signal to the inter arrival congestion control of the estimated // state of our transport channel. The estimate is based on the inter arrival // time of the received packets relative to the time those packets were sent; // we can estimate the build up of buffers on the network before packets are // lost. // // Note: this class is not thread-safe. #ifndef NET_QUIC_CONGESTION_CONTROL_INTER_ARRIVAL_OVERUSE_DETECTOR_H_ #define NET_QUIC_CONGESTION_CONTROL_INTER_ARRIVAL_OVERUSE_DETECTOR_H_ #include "base/basictypes.h" #include "net/base/net_export.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_time.h" namespace net { enum NET_EXPORT_PRIVATE RateControlRegion { kRateControlRegionUnknown = 0, kRateControlRegionUnderMax = 1, kRateControlRegionNearMax = 2 }; // Note: Order is important. enum NET_EXPORT_PRIVATE BandwidthUsage { kBandwidthSteady = 0, kBandwidthUnderUsing = 1, kBandwidthDraining = 2, kBandwidthOverUsing = 3, }; // Normal state transition diagram // // kBandwidthUnderUsing // | // | // kBandwidthSteady // | ^ // | | // kBandwidthOverUsing | // | | // | | // kBandwidthDraining // // The above transitions is in normal operation, with extreme values we don't // enforce the state transitions, hence you could in extreme scenarios go // between any states. // // kBandwidthSteady When the packets arrive in the same pace as we sent // them. In this state we can increase our send pace. // // kBandwidthOverUsing When the packets arrive slower than the pace we sent // them. In this state we should decrease our send pace. // When we enter into this state we will also get an // estimate on how much delay we have built up. The // reduction in send pace should be chosen to drain the // built up delay within reasonable time. // // kBandwidthUnderUsing When the packets arrive faster than the pace we sent // them. In this state another stream disappeared from // a shared link leaving us more available bandwidth. // In this state we should hold our pace to make sure we // fully drain the buffers before we start increasing // our send rate. We do this to avoid operating with // semi-full buffers. // // kBandwidthDraining We can only be in this state after we have been in a // overuse state. In this state we should hold our pace // to make sure we fully drain the buffers before we // start increasing our send rate. We do this to avoid // operating with semi-full buffers. class NET_EXPORT_PRIVATE InterArrivalOveruseDetector { public: InterArrivalOveruseDetector(); // Update the statistics with the received delta times, call for every // received delta time. This function assumes that there is no re-orderings. // If multiple packets are sent at the same time (identical send_time) // last_of_send_time should be set to false for all but the last calls to // this function. If there is only one packet sent at a given time // last_of_send_time must be true. // received_delta is the time difference between receiving this packet and the // previously received packet. void OnAcknowledgedPacket(QuicPacketSequenceNumber sequence_number, QuicTime send_time, bool last_of_send_time, QuicTime receive_time); // Get the current estimated state and update the estimated congestion delay. // |estimated_congestion_delay| will be updated with the estimated built up // buffer delay; it must not be NULL as it will be updated with the estimate. // Note 1: estimated_buffer_delay will only be valid when kBandwidthOverUsing // is returned. // Note 2: it's assumed that the pacer lower its send pace to drain the // built up buffer within reasonable time. The pacer should use the // estimated_buffer_delay as a guidance on how much to back off. // Note 3: The absolute value of estimated_congestion_delay is less reliable // than the state itself. It is also biased to low since we can't know // how full the buffers are when the flow starts. BandwidthUsage GetState(QuicTime::Delta* estimated_congestion_delay); private: struct PacketGroup { PacketGroup() : send_time(QuicTime::Zero()), last_receive_time(QuicTime::Zero()) { } QuicTime send_time; QuicTime last_receive_time; }; // Update the statistics with the absolute receive time relative to the // absolute send time. void UpdateSendReceiveTimeOffset(QuicTime::Delta offset); // Update the filter with this new data point. void UpdateFilter(QuicTime::Delta received_delta, QuicTime::Delta sent_delta); // Update the estimate with this residual. void UpdateDeltaEstimate(QuicTime::Delta residual); // Estimate the state based on the slope of the changes. void DetectSlope(int64 sigma_delta); // Estimate the state based on the accumulated drift of the changes. void DetectDrift(int64 sigma_delta); // Current grouping of packets that were sent at the same time. PacketGroup current_packet_group_; // Grouping of packets that were sent at the same time, just before the // current_packet_group_ above. PacketGroup previous_packet_group_; // Sequence number of the last acknowledged packet. QuicPacketSequenceNumber last_sequence_number_; // Number of received delta times with unique send time. int num_of_deltas_; // Estimated accumulation of received delta times. // Note: Can be negative and can drift over time which is why we bias it // towards 0 and reset it given some triggers. QuicTime::Delta accumulated_deltas_; // Current running mean of our received delta times. int delta_mean_; // Current running variance of our received delta times. int64 delta_variance_; // Number of overuse signals currently triggered in this state. // Note: negative represent underuse. int delta_overuse_counter_; // State estimated by the delta times. BandwidthUsage delta_estimate_; // Number of overuse signals currently triggered in this state. // Note: negative represent underuse. int slope_overuse_counter_; // State estimated by the slope of the delta times. BandwidthUsage slope_estimate_; // Lowest offset between send and receive time ever received in this session. QuicTime::Delta send_receive_offset_; // Last received time difference between our normalized send and receive time. QuicTime::Delta estimated_congestion_delay_; DISALLOW_COPY_AND_ASSIGN(InterArrivalOveruseDetector); }; } // namespace net #endif // NET_QUIC_CONGESTION_CONTROL_INTER_ARRIVAL_OVERUSE_DETECTOR_H_