blob: bbc9940431c18019f2d50fa9621a28ca969ea0fa [file] [log] [blame]
Davide Pesaventobf1c0692017-01-15 19:15:09 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +00002/*
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
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +000025 * @author Chavoosh Ghasemi
Weiwei Liu245d7912016-07-28 00:04:25 -070026 */
27
28#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP
29#define NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_AIMD_HPP
30
31#include "options.hpp"
32#include "aimd-rtt-estimator.hpp"
33#include "pipeline-interests.hpp"
34
35#include <queue>
Davide Pesaventoc0702702017-08-24 22:04:00 -040036#include <unordered_map>
Weiwei Liu245d7912016-07-28 00:04:25 -070037
38namespace ndn {
39namespace chunks {
40namespace aimd {
41
Davide Pesavento92998fe2017-01-18 21:04:52 -050042class PipelineInterestsAimdOptions : public Options
Weiwei Liu245d7912016-07-28 00:04:25 -070043{
Davide Pesavento92998fe2017-01-18 21:04:52 -050044public:
45 explicit
46 PipelineInterestsAimdOptions(const Options& options = Options())
47 : Options(options)
48 {
49 }
50
51public:
Weiwei Liu245d7912016-07-28 00:04:25 -070052 double initCwnd = 1.0; ///< initial congestion window size
Davide Pesavento92998fe2017-01-18 21:04:52 -050053 double initSsthresh = std::numeric_limits<double>::max(); ///< initial slow start threshold
54 double aiStep = 1.0; ///< additive increase step (in segments)
Weiwei Liu245d7912016-07-28 00:04:25 -070055 double mdCoef = 0.5; ///< multiplicative decrease coefficient
Davide Pesavento92998fe2017-01-18 21:04:52 -050056 time::milliseconds rtoCheckInterval{10}; ///< interval for checking retransmission timer
Weiwei Liu245d7912016-07-28 00:04:25 -070057 bool disableCwa = false; ///< disable Conservative Window Adaptation
58 bool resetCwndToInit = false; ///< reduce cwnd to initCwnd when loss event occurs
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000059 bool ignoreCongMarks = false; ///< disable window decrease after congestion marks
Weiwei Liu245d7912016-07-28 00:04:25 -070060};
61
62/**
63 * @brief indicates the state of the segment
64 */
65enum class SegmentState {
66 FirstTimeSent, ///< segment has been sent for the first time
67 InRetxQueue, ///< segment is in retransmission queue
68 Retransmitted, ///< segment has been retransmitted
69 RetxReceived, ///< segment has been received after retransmission
70};
71
72std::ostream&
73operator<<(std::ostream& os, SegmentState state);
74
75/**
76 * @brief Wraps up information that's necessary for segment transmission
77 */
78struct SegmentInfo
79{
Davide Pesavento958896e2017-01-19 00:52:04 -050080 const PendingInterestId* interestId; ///< pending interest ID returned by ndn::Face::expressInterest
Weiwei Liu245d7912016-07-28 00:04:25 -070081 time::steady_clock::TimePoint timeSent;
Davide Pesavento958896e2017-01-19 00:52:04 -050082 Milliseconds rto;
83 SegmentState state;
Weiwei Liu245d7912016-07-28 00:04:25 -070084};
85
86/**
87 * @brief Service for retrieving Data via an Interest pipeline
88 *
89 * Retrieves all segmented Data under the specified prefix by maintaining a dynamic AIMD
90 * congestion window combined with a Conservative Loss Adaptation algorithm. For details,
91 * please refer to the description in section "Interest pipeline types in ndncatchunks" of
92 * tools/chunks/README.md
93 *
94 * Provides retrieved Data on arrival with no ordering guarantees. Data is delivered to the
95 * PipelineInterests' user via callback immediately upon arrival.
96 */
97class PipelineInterestsAimd : public PipelineInterests
98{
99public:
100 typedef PipelineInterestsAimdOptions Options;
101
102public:
103 /**
104 * @brief create a PipelineInterestsAimd service
105 *
106 * Configures the pipelining service without specifying the retrieval namespace. After this
107 * configuration the method run must be called to start the Pipeline.
108 */
109 PipelineInterestsAimd(Face& face, RttEstimator& rttEstimator,
110 const Options& options = Options());
111
112 ~PipelineInterestsAimd() final;
113
114 /**
115 * @brief Signals when cwnd changes
116 *
117 * The callback function should be: void(Milliseconds age, double cwnd) where age is the
118 * duration since pipeline starts, and cwnd is the new congestion window size (in segments).
119 */
120 signal::Signal<PipelineInterestsAimd, Milliseconds, double> afterCwndChange;
121
122private:
123 /**
124 * @brief fetch all the segments between 0 and lastSegment of the specified prefix
125 *
Davide Pesaventob587cfd2017-11-04 16:29:50 -0400126 * Starts the pipeline with an AIMD algorithm to control the window size. The pipeline will
127 * fetch every segment until the last segment is successfully received or an error occurs.
Weiwei Liu245d7912016-07-28 00:04:25 -0700128 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500129 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700130 doRun() final;
131
132 /**
133 * @brief stop all fetch operations
134 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500135 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700136 doCancel() final;
137
138 /**
139 * @brief check RTO for all sent-but-not-acked segments.
140 */
141 void
142 checkRto();
143
144 /**
145 * @param segNo the segment # of the to-be-sent Interest
146 * @param isRetransmission true if this is a retransmission
147 */
148 void
149 sendInterest(uint64_t segNo, bool isRetransmission);
150
151 void
152 schedulePackets();
153
154 void
155 handleData(const Interest& interest, const Data& data);
156
157 void
158 handleNack(const Interest& interest, const lp::Nack& nack);
159
160 void
161 handleLifetimeExpiration(const Interest& interest);
162
163 void
Davide Pesavento958896e2017-01-19 00:52:04 -0500164 recordTimeout();
165
166 void
167 enqueueForRetransmission(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700168
169 void
170 handleFail(uint64_t segNo, const std::string& reason);
171
172 /**
173 * @brief increase congestion window size based on AIMD scheme
174 */
175 void
176 increaseWindow();
177
178 /**
179 * @brief decrease congestion window size based on AIMD scheme
180 */
181 void
182 decreaseWindow();
183
Weiwei Liu245d7912016-07-28 00:04:25 -0700184 void
Davide Pesavento958896e2017-01-19 00:52:04 -0500185 cancelInFlightSegmentsGreaterThan(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700186
187 void
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +0000188 printSummary() const final;
Weiwei Liu245d7912016-07-28 00:04:25 -0700189
190PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000191 static constexpr double MIN_SSTHRESH = 2.0;
Weiwei Liu245d7912016-07-28 00:04:25 -0700192 const Options m_options;
193 RttEstimator& m_rttEstimator;
194 Scheduler m_scheduler;
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500195 scheduler::ScopedEventId m_checkRtoEvent;
196
Weiwei Liu245d7912016-07-28 00:04:25 -0700197 uint64_t m_highData; ///< the highest segment number of the Data packet the consumer has received so far
198 uint64_t m_highInterest; ///< the highest segment number of the Interests the consumer has sent so far
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500199 uint64_t m_recPoint; ///< the value of m_highInterest when a packet loss event occurred,
200 ///< it remains fixed until the next packet loss event happens
Weiwei Liu245d7912016-07-28 00:04:25 -0700201
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500202 int64_t m_nInFlight; ///< # of segments in flight
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500203 int64_t m_nLossEvents; ///< # of loss events occurred
204 int64_t m_nRetransmitted; ///< # of segments retransmitted
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000205 int64_t m_nCongMarks; ///< # of data packets with congestion mark
Weiwei Liu245d7912016-07-28 00:04:25 -0700206
207 double m_cwnd; ///< current congestion window size (in segments)
208 double m_ssthresh; ///< current slow start threshold
209
Davide Pesavento958896e2017-01-19 00:52:04 -0500210 std::unordered_map<uint64_t, SegmentInfo> m_segmentInfo; ///< keeps all the internal information
211 ///< on sent but not acked segments
212 std::unordered_map<uint64_t, int> m_retxCount; ///< maps segment number to its retransmission count;
Weiwei Liu245d7912016-07-28 00:04:25 -0700213 ///< if the count reaches to the maximum number of
214 ///< timeout/nack retries, the pipeline will be aborted
Davide Pesavento958896e2017-01-19 00:52:04 -0500215 std::queue<uint64_t> m_retxQueue;
216
Weiwei Liu245d7912016-07-28 00:04:25 -0700217 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