blob: 1670fdadc7bbcdbae6619511ec24f388d35b150f [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
40struct PipelineInterestsAimdOptions : public Options
41{
42 bool isVerbose = false;
43 double initCwnd = 1.0; ///< initial congestion window size
44 double initSsthresh = std::numeric_limits<double>::max(); ///< initial slow start threshold
45 double mdCoef = 0.5; ///< multiplicative decrease coefficient
46 double aiStep = 1.0; ///< additive increase step (unit: segment)
47 time::milliseconds rtoCheckInterval = time::milliseconds(10); ///< time interval for checking retransmission timer
48 bool disableCwa = false; ///< disable Conservative Window Adaptation
49 bool resetCwndToInit = false; ///< reduce cwnd to initCwnd when loss event occurs
50};
51
52/**
53 * @brief indicates the state of the segment
54 */
55enum class SegmentState {
56 FirstTimeSent, ///< segment has been sent for the first time
57 InRetxQueue, ///< segment is in retransmission queue
58 Retransmitted, ///< segment has been retransmitted
59 RetxReceived, ///< segment has been received after retransmission
60};
61
62std::ostream&
63operator<<(std::ostream& os, SegmentState state);
64
65/**
66 * @brief Wraps up information that's necessary for segment transmission
67 */
68struct SegmentInfo
69{
70 const PendingInterestId* interestId; ///< The pending interest ID returned by
71 ///< ndn::Face::expressInterest. It can be used with
72 ///< removePendingInterest before retransmitting this Interest.
73 SegmentState state;
74 Milliseconds rto;
75 time::steady_clock::TimePoint timeSent;
76};
77
78/**
79 * @brief Service for retrieving Data via an Interest pipeline
80 *
81 * Retrieves all segmented Data under the specified prefix by maintaining a dynamic AIMD
82 * congestion window combined with a Conservative Loss Adaptation algorithm. For details,
83 * please refer to the description in section "Interest pipeline types in ndncatchunks" of
84 * tools/chunks/README.md
85 *
86 * Provides retrieved Data on arrival with no ordering guarantees. Data is delivered to the
87 * PipelineInterests' user via callback immediately upon arrival.
88 */
89class PipelineInterestsAimd : public PipelineInterests
90{
91public:
92 typedef PipelineInterestsAimdOptions Options;
93
94public:
95 /**
96 * @brief create a PipelineInterestsAimd service
97 *
98 * Configures the pipelining service without specifying the retrieval namespace. After this
99 * configuration the method run must be called to start the Pipeline.
100 */
101 PipelineInterestsAimd(Face& face, RttEstimator& rttEstimator,
102 const Options& options = Options());
103
104 ~PipelineInterestsAimd() final;
105
106 /**
107 * @brief Signals when cwnd changes
108 *
109 * The callback function should be: void(Milliseconds age, double cwnd) where age is the
110 * duration since pipeline starts, and cwnd is the new congestion window size (in segments).
111 */
112 signal::Signal<PipelineInterestsAimd, Milliseconds, double> afterCwndChange;
113
114private:
115 /**
116 * @brief fetch all the segments between 0 and lastSegment of the specified prefix
117 *
118 * Starts the pipeline with an AIMD algorithm to control the window size. The pipeline will fetch
119 * every segment until the last segment is successfully received or an error occurs.
120 * The segment with segment number equal to m_excludedSegmentNo will not be fetched.
121 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500122 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700123 doRun() final;
124
125 /**
126 * @brief stop all fetch operations
127 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500128 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700129 doCancel() final;
130
131 /**
132 * @brief check RTO for all sent-but-not-acked segments.
133 */
134 void
135 checkRto();
136
137 /**
138 * @param segNo the segment # of the to-be-sent Interest
139 * @param isRetransmission true if this is a retransmission
140 */
141 void
142 sendInterest(uint64_t segNo, bool isRetransmission);
143
144 void
145 schedulePackets();
146
147 void
148 handleData(const Interest& interest, const Data& data);
149
150 void
151 handleNack(const Interest& interest, const lp::Nack& nack);
152
153 void
154 handleLifetimeExpiration(const Interest& interest);
155
156 void
157 handleTimeout(int timeoutCount);
158
159 void
160 handleFail(uint64_t segNo, const std::string& reason);
161
162 /**
163 * @brief increase congestion window size based on AIMD scheme
164 */
165 void
166 increaseWindow();
167
168 /**
169 * @brief decrease congestion window size based on AIMD scheme
170 */
171 void
172 decreaseWindow();
173
174 /** \return next segment number to retrieve
175 * \post m_nextSegmentNo == return-value + 1
176 */
177 uint64_t
178 getNextSegmentNo();
179
180 void
181 cancelInFlightSegmentsGreaterThan(uint64_t segmentNo);
182
183 void
184 printSummary() const;
185
186PUBLIC_WITH_TESTS_ELSE_PRIVATE:
187 const Options m_options;
188 RttEstimator& m_rttEstimator;
189 Scheduler m_scheduler;
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500190 scheduler::ScopedEventId m_checkRtoEvent;
191
Weiwei Liu245d7912016-07-28 00:04:25 -0700192 uint64_t m_nextSegmentNo;
193 size_t m_receivedSize;
194
195 uint64_t m_highData; ///< the highest segment number of the Data packet the consumer has received so far
196 uint64_t m_highInterest; ///< the highest segment number of the Interests the consumer has sent so far
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500197 uint64_t m_recPoint; ///< the value of m_highInterest when a packet loss event occurred,
198 ///< it remains fixed until the next packet loss event happens
Weiwei Liu245d7912016-07-28 00:04:25 -0700199
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500200 int64_t m_nInFlight; ///< # of segments in flight
201 int64_t m_nReceived; ///< # of segments received
202 int64_t m_nLossEvents; ///< # of loss events occurred
203 int64_t m_nRetransmitted; ///< # of segments retransmitted
Weiwei Liu245d7912016-07-28 00:04:25 -0700204
205 double m_cwnd; ///< current congestion window size (in segments)
206 double m_ssthresh; ///< current slow start threshold
207
208 std::queue<uint64_t> m_retxQueue;
209
210 std::unordered_map<uint64_t, SegmentInfo> m_segmentInfo; ///< the map keeps all the internal information
211 ///< of the sent but not ackownledged segments
212
213 std::unordered_map<uint64_t, int> m_retxCount; ///< maps segment number to its retransmission count.
214 ///< if the count reaches to the maximum number of
215 ///< timeout/nack retries, the pipeline will be aborted
216 bool m_hasFailure;
217 uint64_t m_failedSegNo;
218 std::string m_failureReason;
219};
220
221std::ostream&
222operator<<(std::ostream& os, const PipelineInterestsAimdOptions& options);
223
224} // namespace aimd
225
226using aimd::PipelineInterestsAimd;
227
228} // namespace chunks
229} // namespace ndn
230
231#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP