summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h
blob: 6c3c6b0ef17c258dc80e9692d017adb08625f46d (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
115
116
117
118
119
120
// 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.

#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_
#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_

#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"

namespace quic {
namespace simulator {

// A finitely sized queue which egresses packets onto a constrained link.  The
// capacity of the queue is measured in bytes as opposed to packets.
class Queue : public Actor, public UnconstrainedPortInterface {
 public:
  class ListenerInterface {
   public:
    virtual ~ListenerInterface();

    // Called whenever a packet is removed from the queue.
    virtual void OnPacketDequeued() = 0;
  };

  Queue(Simulator* simulator, std::string name, QuicByteCount capacity);
  Queue(const Queue&) = delete;
  Queue& operator=(const Queue&) = delete;
  ~Queue() override;

  void set_tx_port(ConstrainedPortInterface* port);

  void AcceptPacket(std::unique_ptr<Packet> packet) override;

  void Act() override;

  inline QuicByteCount capacity() const { return capacity_; }
  inline QuicByteCount bytes_queued() const { return bytes_queued_; }
  inline QuicPacketCount packets_queued() const { return queue_.size(); }

  inline void set_listener_interface(ListenerInterface* listener) {
    listener_ = listener;
  }

  // Enables packet aggregation on the queue.  Packet aggregation makes the
  // queue bundle packets up until they reach certain size.  When the
  // aggregation is enabled, the packets are not dequeued until the total size
  // of packets in the queue reaches |aggregation_threshold|.  The packets are
  // automatically flushed from the queue if the oldest packet has been in it
  // for |aggregation_timeout|.
  //
  // This method may only be called when the queue is empty.  Once enabled,
  // aggregation cannot be disabled.
  void EnableAggregation(QuicByteCount aggregation_threshold,
                         QuicTime::Delta aggregation_timeout);

 private:
  typedef uint64_t AggregationBundleNumber;

  // In order to implement packet aggregation, each packet is tagged with a
  // bundle number.  The queue keeps a bundle counter, and whenever a bundle is
  // ready, it increments the number of the current bundle.  Only the packets
  // outside of the current bundle are allowed to leave the queue.
  struct EnqueuedPacket {
    EnqueuedPacket(std::unique_ptr<Packet> packet,
                   AggregationBundleNumber bundle);
    EnqueuedPacket(EnqueuedPacket&& other);
    ~EnqueuedPacket();

    std::unique_ptr<Packet> packet;
    AggregationBundleNumber bundle;
  };

  // Alarm handler for aggregation timeout.
  class AggregationAlarmDelegate : public QuicAlarm::Delegate {
   public:
    explicit AggregationAlarmDelegate(Queue* queue);

    void OnAlarm() override;

   private:
    Queue* queue_;
  };

  inline bool IsAggregationEnabled() const {
    return aggregation_threshold_ > 0;
  }

  // Increment the bundle counter and reset the bundle state.  This causes all
  // packets currently in the bundle to be flushed onto the link.
  void NextBundle();

  void ScheduleNextPacketDequeue();

  const QuicByteCount capacity_;
  QuicByteCount bytes_queued_;

  QuicByteCount aggregation_threshold_;
  QuicTime::Delta aggregation_timeout_;
  // The number of the current aggregation bundle.  Monotonically increasing.
  // All packets in the previous bundles are allowed to leave the queue, and
  // none of the packets in the current one are.
  AggregationBundleNumber current_bundle_;
  // Size of the current bundle.  Whenever it exceeds |aggregation_threshold_|,
  // the next bundle is created.
  QuicByteCount current_bundle_bytes_;
  // Alarm responsible for flushing the current bundle upon timeout.  Set when
  // the first packet in the bundle is enqueued.
  std::unique_ptr<QuicAlarm> aggregation_timeout_alarm_;

  ConstrainedPortInterface* tx_port_;
  QuicQueue<EnqueuedPacket> queue_;

  ListenerInterface* listener_;
};

}  // namespace simulator
}  // namespace quic

#endif  // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_