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