blob: 6c3c6b0ef17c258dc80e9692d017adb08625f46d [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_
6#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_
7
8#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
9#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
10
11namespace quic {
12namespace simulator {
13
14// A finitely sized queue which egresses packets onto a constrained link. The
15// capacity of the queue is measured in bytes as opposed to packets.
16class Queue : public Actor, public UnconstrainedPortInterface {
17 public:
18 class ListenerInterface {
19 public:
20 virtual ~ListenerInterface();
21
22 // Called whenever a packet is removed from the queue.
23 virtual void OnPacketDequeued() = 0;
24 };
25
vasilvvc48c8712019-03-11 13:38:16 -070026 Queue(Simulator* simulator, std::string name, QuicByteCount capacity);
QUICHE teama6ef0a62019-03-07 20:34:33 -050027 Queue(const Queue&) = delete;
28 Queue& operator=(const Queue&) = delete;
29 ~Queue() override;
30
31 void set_tx_port(ConstrainedPortInterface* port);
32
33 void AcceptPacket(std::unique_ptr<Packet> packet) override;
34
35 void Act() override;
36
37 inline QuicByteCount capacity() const { return capacity_; }
38 inline QuicByteCount bytes_queued() const { return bytes_queued_; }
39 inline QuicPacketCount packets_queued() const { return queue_.size(); }
40
41 inline void set_listener_interface(ListenerInterface* listener) {
42 listener_ = listener;
43 }
44
45 // Enables packet aggregation on the queue. Packet aggregation makes the
46 // queue bundle packets up until they reach certain size. When the
47 // aggregation is enabled, the packets are not dequeued until the total size
48 // of packets in the queue reaches |aggregation_threshold|. The packets are
49 // automatically flushed from the queue if the oldest packet has been in it
50 // for |aggregation_timeout|.
51 //
52 // This method may only be called when the queue is empty. Once enabled,
53 // aggregation cannot be disabled.
54 void EnableAggregation(QuicByteCount aggregation_threshold,
55 QuicTime::Delta aggregation_timeout);
56
57 private:
58 typedef uint64_t AggregationBundleNumber;
59
60 // In order to implement packet aggregation, each packet is tagged with a
61 // bundle number. The queue keeps a bundle counter, and whenever a bundle is
62 // ready, it increments the number of the current bundle. Only the packets
63 // outside of the current bundle are allowed to leave the queue.
64 struct EnqueuedPacket {
65 EnqueuedPacket(std::unique_ptr<Packet> packet,
66 AggregationBundleNumber bundle);
67 EnqueuedPacket(EnqueuedPacket&& other);
68 ~EnqueuedPacket();
69
70 std::unique_ptr<Packet> packet;
71 AggregationBundleNumber bundle;
72 };
73
74 // Alarm handler for aggregation timeout.
75 class AggregationAlarmDelegate : public QuicAlarm::Delegate {
76 public:
77 explicit AggregationAlarmDelegate(Queue* queue);
78
79 void OnAlarm() override;
80
81 private:
82 Queue* queue_;
83 };
84
85 inline bool IsAggregationEnabled() const {
86 return aggregation_threshold_ > 0;
87 }
88
89 // Increment the bundle counter and reset the bundle state. This causes all
90 // packets currently in the bundle to be flushed onto the link.
91 void NextBundle();
92
93 void ScheduleNextPacketDequeue();
94
95 const QuicByteCount capacity_;
96 QuicByteCount bytes_queued_;
97
98 QuicByteCount aggregation_threshold_;
99 QuicTime::Delta aggregation_timeout_;
100 // The number of the current aggregation bundle. Monotonically increasing.
101 // All packets in the previous bundles are allowed to leave the queue, and
102 // none of the packets in the current one are.
103 AggregationBundleNumber current_bundle_;
104 // Size of the current bundle. Whenever it exceeds |aggregation_threshold_|,
105 // the next bundle is created.
106 QuicByteCount current_bundle_bytes_;
107 // Alarm responsible for flushing the current bundle upon timeout. Set when
108 // the first packet in the bundle is enqueued.
109 std::unique_ptr<QuicAlarm> aggregation_timeout_alarm_;
110
111 ConstrainedPortInterface* tx_port_;
112 QuicQueue<EnqueuedPacket> queue_;
113
114 ListenerInterface* listener_;
115};
116
117} // namespace simulator
118} // namespace quic
119
120#endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_