blob: c67d5bc06f44e02e03436ec28d0bea18e90de962 [file] [log] [blame]
Weiwei Liu245d7912016-07-28 00:04:25 -07001/**
Davide Pesaventocd65c2c2017-01-15 16:10:38 -05002 * Copyright (c) 2016-2017, Regents of the University of California,
3 * Colorado State University,
4 * University Pierre & Marie Curie, Sorbonne University.
Weiwei Liu245d7912016-07-28 00:04:25 -07005 *
6 * This file is part of ndn-tools (Named Data Networking Essential Tools).
7 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
8 *
9 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
10 * of the GNU General Public License as published by the Free Software Foundation,
11 * either version 3 of the License, or (at your option) any later version.
12 *
13 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
21 *
22 * @author Shuo Yang
23 * @author Weiwei Liu
24 */
25
26#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP
27#define NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP
28
29#include "options.hpp"
30#include "aimd-rtt-estimator.hpp"
31#include "pipeline-interests.hpp"
32
33#include <queue>
34
35namespace ndn {
36namespace chunks {
37namespace aimd {
38
39struct PipelineInterestsAimdOptions : public Options
40{
41 bool isVerbose = false;
42 double initCwnd = 1.0; ///< initial congestion window size
43 double initSsthresh = std::numeric_limits<double>::max(); ///< initial slow start threshold
44 double mdCoef = 0.5; ///< multiplicative decrease coefficient
45 double aiStep = 1.0; ///< additive increase step (unit: segment)
46 time::milliseconds rtoCheckInterval = time::milliseconds(10); ///< time interval for checking retransmission timer
47 bool disableCwa = false; ///< disable Conservative Window Adaptation
48 bool resetCwndToInit = false; ///< reduce cwnd to initCwnd when loss event occurs
49};
50
51/**
52 * @brief indicates the state of the segment
53 */
54enum class SegmentState {
55 FirstTimeSent, ///< segment has been sent for the first time
56 InRetxQueue, ///< segment is in retransmission queue
57 Retransmitted, ///< segment has been retransmitted
58 RetxReceived, ///< segment has been received after retransmission
59};
60
61std::ostream&
62operator<<(std::ostream& os, SegmentState state);
63
64/**
65 * @brief Wraps up information that's necessary for segment transmission
66 */
67struct SegmentInfo
68{
69 const PendingInterestId* interestId; ///< The pending interest ID returned by
70 ///< ndn::Face::expressInterest. It can be used with
71 ///< removePendingInterest before retransmitting this Interest.
72 SegmentState state;
73 Milliseconds rto;
74 time::steady_clock::TimePoint timeSent;
75};
76
77/**
78 * @brief Service for retrieving Data via an Interest pipeline
79 *
80 * Retrieves all segmented Data under the specified prefix by maintaining a dynamic AIMD
81 * congestion window combined with a Conservative Loss Adaptation algorithm. For details,
82 * please refer to the description in section "Interest pipeline types in ndncatchunks" of
83 * tools/chunks/README.md
84 *
85 * Provides retrieved Data on arrival with no ordering guarantees. Data is delivered to the
86 * PipelineInterests' user via callback immediately upon arrival.
87 */
88class PipelineInterestsAimd : public PipelineInterests
89{
90public:
91 typedef PipelineInterestsAimdOptions Options;
92
93public:
94 /**
95 * @brief create a PipelineInterestsAimd service
96 *
97 * Configures the pipelining service without specifying the retrieval namespace. After this
98 * configuration the method run must be called to start the Pipeline.
99 */
100 PipelineInterestsAimd(Face& face, RttEstimator& rttEstimator,
101 const Options& options = Options());
102
103 ~PipelineInterestsAimd() final;
104
105 /**
106 * @brief Signals when cwnd changes
107 *
108 * The callback function should be: void(Milliseconds age, double cwnd) where age is the
109 * duration since pipeline starts, and cwnd is the new congestion window size (in segments).
110 */
111 signal::Signal<PipelineInterestsAimd, Milliseconds, double> afterCwndChange;
112
113private:
114 /**
115 * @brief fetch all the segments between 0 and lastSegment of the specified prefix
116 *
117 * Starts the pipeline with an AIMD algorithm to control the window size. The pipeline will fetch
118 * every segment until the last segment is successfully received or an error occurs.
119 * The segment with segment number equal to m_excludedSegmentNo will not be fetched.
120 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500121 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700122 doRun() final;
123
124 /**
125 * @brief stop all fetch operations
126 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500127 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700128 doCancel() final;
129
130 /**
131 * @brief check RTO for all sent-but-not-acked segments.
132 */
133 void
134 checkRto();
135
136 /**
137 * @param segNo the segment # of the to-be-sent Interest
138 * @param isRetransmission true if this is a retransmission
139 */
140 void
141 sendInterest(uint64_t segNo, bool isRetransmission);
142
143 void
144 schedulePackets();
145
146 void
147 handleData(const Interest& interest, const Data& data);
148
149 void
150 handleNack(const Interest& interest, const lp::Nack& nack);
151
152 void
153 handleLifetimeExpiration(const Interest& interest);
154
155 void
156 handleTimeout(int timeoutCount);
157
158 void
159 handleFail(uint64_t segNo, const std::string& reason);
160
161 /**
162 * @brief increase congestion window size based on AIMD scheme
163 */
164 void
165 increaseWindow();
166
167 /**
168 * @brief decrease congestion window size based on AIMD scheme
169 */
170 void
171 decreaseWindow();
172
173 /** \return next segment number to retrieve
174 * \post m_nextSegmentNo == return-value + 1
175 */
176 uint64_t
177 getNextSegmentNo();
178
179 void
180 cancelInFlightSegmentsGreaterThan(uint64_t segmentNo);
181
182 void
183 printSummary() const;
184
185PUBLIC_WITH_TESTS_ELSE_PRIVATE:
186 const Options m_options;
187 RttEstimator& m_rttEstimator;
188 Scheduler m_scheduler;
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500189 scheduler::ScopedEventId m_checkRtoEvent;
190
Weiwei Liu245d7912016-07-28 00:04:25 -0700191 uint64_t m_nextSegmentNo;
192 size_t m_receivedSize;
193
194 uint64_t m_highData; ///< the highest segment number of the Data packet the consumer has received so far
195 uint64_t m_highInterest; ///< the highest segment number of the Interests the consumer has sent so far
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500196 uint64_t m_recPoint; ///< the value of m_highInterest when a packet loss event occurred,
197 ///< it remains fixed until the next packet loss event happens
Weiwei Liu245d7912016-07-28 00:04:25 -0700198
199 uint64_t m_nInFlight; ///< # of segments in flight
200 uint64_t m_nReceived; ///< # of segments received
201 uint64_t m_nLossEvents; ///< # of loss events occurred
202 uint64_t m_nRetransmitted; ///< # of segments retransmitted
203
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500204 time::steady_clock::TimePoint m_startTime; ///< start time of pipelining
Weiwei Liu245d7912016-07-28 00:04:25 -0700205
206 double m_cwnd; ///< current congestion window size (in segments)
207 double m_ssthresh; ///< current slow start threshold
208
209 std::queue<uint64_t> m_retxQueue;
210
211 std::unordered_map<uint64_t, SegmentInfo> m_segmentInfo; ///< the map keeps all the internal information
212 ///< of the sent but not ackownledged segments
213
214 std::unordered_map<uint64_t, int> m_retxCount; ///< maps segment number to its retransmission count.
215 ///< if the count reaches to the maximum number of
216 ///< timeout/nack retries, the pipeline will be aborted
217 bool m_hasFailure;
218 uint64_t m_failedSegNo;
219 std::string m_failureReason;
220};
221
222std::ostream&
223operator<<(std::ostream& os, const PipelineInterestsAimdOptions& options);
224
225} // namespace aimd
226
227using aimd::PipelineInterestsAimd;
228
229} // namespace chunks
230} // namespace ndn
231
232#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP