summaryrefslogtreecommitdiffstats
path: root/net/quic/congestion_control/quic_send_scheduler.h
blob: 66324aeb4c44cb0fb9c5cb7e1933c78d792f9148 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 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 <map>

#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<QuicPacketSequenceNumber, PendingPacket*> 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<SendAlgorithmInterface> 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_