blob: 143b53ba3d8f0d0a4de518b1d78f0d89918d10dd [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/*
Junxiao Shi06d008c2019-02-04 08:26:59 +00003 * Copyright (c) 2016-2019, Regents of the University of California,
Davide Pesaventocd65c2c2017-01-15 16:10:38 -05004 * 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
schneiderklausd8197df2019-03-16 11:31:40 -070026 * @author Klaus Schneider
Weiwei Liu245d7912016-07-28 00:04:25 -070027 */
28
schneiderklausd8197df2019-03-16 11:31:40 -070029#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_ADAPTIVE_HPP
30#define NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_ADAPTIVE_HPP
Weiwei Liu245d7912016-07-28 00:04:25 -070031
32#include "options.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070033#include "pipeline-interests.hpp"
34
Davide Pesavento70576402019-06-07 16:42:21 -040035#include <ndn-cxx/util/rtt-estimator.hpp>
36
Weiwei Liu245d7912016-07-28 00:04:25 -070037#include <queue>
Davide Pesaventoc0702702017-08-24 22:04:00 -040038#include <unordered_map>
Weiwei Liu245d7912016-07-28 00:04:25 -070039
40namespace ndn {
41namespace chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070042
Davide Pesavento5e3773d2019-08-22 15:35:08 -040043using util::RttEstimatorWithStats;
Davide Pesavento70576402019-06-07 16:42:21 -040044
schneiderklausd8197df2019-03-16 11:31:40 -070045class PipelineInterestsAdaptiveOptions : public Options
Weiwei Liu245d7912016-07-28 00:04:25 -070046{
Davide Pesavento92998fe2017-01-18 21:04:52 -050047public:
48 explicit
schneiderklausd8197df2019-03-16 11:31:40 -070049 PipelineInterestsAdaptiveOptions(const Options& options = Options())
Davide Pesavento92998fe2017-01-18 21:04:52 -050050 : Options(options)
51 {
52 }
53
54public:
Weiwei Liu245d7912016-07-28 00:04:25 -070055 double initCwnd = 1.0; ///< initial congestion window size
Davide Pesavento92998fe2017-01-18 21:04:52 -050056 double initSsthresh = std::numeric_limits<double>::max(); ///< initial slow start threshold
57 double aiStep = 1.0; ///< additive increase step (in segments)
Weiwei Liu245d7912016-07-28 00:04:25 -070058 double mdCoef = 0.5; ///< multiplicative decrease coefficient
Davide Pesavento92998fe2017-01-18 21:04:52 -050059 time::milliseconds rtoCheckInterval{10}; ///< interval for checking retransmission timer
Weiwei Liu245d7912016-07-28 00:04:25 -070060 bool disableCwa = false; ///< disable Conservative Window Adaptation
61 bool resetCwndToInit = false; ///< reduce cwnd to initCwnd when loss event occurs
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000062 bool ignoreCongMarks = false; ///< disable window decrease after congestion marks
Weiwei Liu245d7912016-07-28 00:04:25 -070063};
64
Klaus Schneider9e5122b2019-03-19 17:03:25 -070065std::ostream&
66operator<<(std::ostream& os, const PipelineInterestsAdaptiveOptions& options);
67
Weiwei Liu245d7912016-07-28 00:04:25 -070068/**
69 * @brief indicates the state of the segment
70 */
71enum class SegmentState {
72 FirstTimeSent, ///< segment has been sent for the first time
73 InRetxQueue, ///< segment is in retransmission queue
74 Retransmitted, ///< segment has been retransmitted
Weiwei Liu245d7912016-07-28 00:04:25 -070075};
76
77std::ostream&
78operator<<(std::ostream& os, SegmentState state);
79
80/**
81 * @brief Wraps up information that's necessary for segment transmission
82 */
83struct SegmentInfo
84{
Junxiao Shi06d008c2019-02-04 08:26:59 +000085 ScopedPendingInterestHandle interestHdl;
Weiwei Liu245d7912016-07-28 00:04:25 -070086 time::steady_clock::TimePoint timeSent;
Davide Pesaventoba560662019-06-26 22:45:44 -040087 time::nanoseconds rto;
Davide Pesavento958896e2017-01-19 00:52:04 -050088 SegmentState state;
Weiwei Liu245d7912016-07-28 00:04:25 -070089};
90
91/**
92 * @brief Service for retrieving Data via an Interest pipeline
93 *
schneiderklausd8197df2019-03-16 11:31:40 -070094 * Retrieves all segmented Data under the specified prefix by maintaining a dynamic
Weiwei Liu245d7912016-07-28 00:04:25 -070095 * congestion window combined with a Conservative Loss Adaptation algorithm. For details,
96 * please refer to the description in section "Interest pipeline types in ndncatchunks" of
97 * tools/chunks/README.md
98 *
99 * Provides retrieved Data on arrival with no ordering guarantees. Data is delivered to the
100 * PipelineInterests' user via callback immediately upon arrival.
101 */
schneiderklausd8197df2019-03-16 11:31:40 -0700102class PipelineInterestsAdaptive : public PipelineInterests
Weiwei Liu245d7912016-07-28 00:04:25 -0700103{
104public:
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700105 using Options = PipelineInterestsAdaptiveOptions;
Weiwei Liu245d7912016-07-28 00:04:25 -0700106
107public:
108 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700109 * @brief Constructor.
Weiwei Liu245d7912016-07-28 00:04:25 -0700110 *
111 * Configures the pipelining service without specifying the retrieval namespace. After this
112 * configuration the method run must be called to start the Pipeline.
113 */
Davide Pesavento5e3773d2019-08-22 15:35:08 -0400114 PipelineInterestsAdaptive(Face& face, RttEstimatorWithStats& rttEstimator,
schneiderklausd8197df2019-03-16 11:31:40 -0700115 const Options& options = Options());
Weiwei Liu245d7912016-07-28 00:04:25 -0700116
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700117 ~PipelineInterestsAdaptive() override;
Weiwei Liu245d7912016-07-28 00:04:25 -0700118
119 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700120 * @brief Signals when the congestion window changes.
Weiwei Liu245d7912016-07-28 00:04:25 -0700121 *
Davide Pesavento70576402019-06-07 16:42:21 -0400122 * The callback function should be: `void(nanoseconds age, double cwnd)`, where `age` is the
123 * time since the pipeline started and `cwnd` is the new congestion window size (in segments).
Weiwei Liu245d7912016-07-28 00:04:25 -0700124 */
Davide Pesavento70576402019-06-07 16:42:21 -0400125 signal::Signal<PipelineInterestsAdaptive, time::nanoseconds, double> afterCwndChange;
Weiwei Liu245d7912016-07-28 00:04:25 -0700126
Davide Pesavento5e3773d2019-08-22 15:35:08 -0400127 struct RttSample
128 {
129 uint64_t segNum; ///< segment number on which this sample was taken
130 time::nanoseconds rtt; ///< measured RTT
131 time::nanoseconds sRtt; ///< smoothed RTT
132 time::nanoseconds rttVar; ///< RTT variation
133 time::nanoseconds rto; ///< retransmission timeout
134 };
135
136 /**
137 * @brief Signals when a new RTT sample has been taken.
138 */
139 signal::Signal<PipelineInterestsAdaptive, RttSample> afterRttMeasurement;
140
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700141protected:
142 DECLARE_SIGNAL_EMIT(afterCwndChange)
143
Weiwei Liu245d7912016-07-28 00:04:25 -0700144private:
145 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700146 * @brief Increase congestion window.
147 */
148 virtual void
149 increaseWindow() = 0;
150
151 /**
152 * @brief Decrease congestion window.
153 */
154 virtual void
155 decreaseWindow() = 0;
156
157private:
158 /**
159 * @brief Fetch all the segments between 0 and lastSegment of the specified prefix.
Weiwei Liu245d7912016-07-28 00:04:25 -0700160 *
schneiderklausd8197df2019-03-16 11:31:40 -0700161 * Starts the pipeline with an adaptive window algorithm to control the window size.
162 * The pipeline will fetch every segment until the last segment is successfully received
163 * or an error occurs.
Weiwei Liu245d7912016-07-28 00:04:25 -0700164 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500165 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700166 doRun() final;
167
168 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700169 * @brief Stop all fetch operations.
Weiwei Liu245d7912016-07-28 00:04:25 -0700170 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500171 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700172 doCancel() final;
173
174 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700175 * @brief Check RTO for all sent-but-not-acked segments.
Weiwei Liu245d7912016-07-28 00:04:25 -0700176 */
177 void
178 checkRto();
179
180 /**
181 * @param segNo the segment # of the to-be-sent Interest
182 * @param isRetransmission true if this is a retransmission
183 */
184 void
185 sendInterest(uint64_t segNo, bool isRetransmission);
186
187 void
188 schedulePackets();
189
190 void
191 handleData(const Interest& interest, const Data& data);
192
193 void
194 handleNack(const Interest& interest, const lp::Nack& nack);
195
196 void
197 handleLifetimeExpiration(const Interest& interest);
198
199 void
Davide Pesavento958896e2017-01-19 00:52:04 -0500200 recordTimeout();
201
202 void
203 enqueueForRetransmission(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700204
205 void
206 handleFail(uint64_t segNo, const std::string& reason);
207
Weiwei Liu245d7912016-07-28 00:04:25 -0700208 void
Davide Pesavento958896e2017-01-19 00:52:04 -0500209 cancelInFlightSegmentsGreaterThan(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700210
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400211PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Weiwei Liu245d7912016-07-28 00:04:25 -0700212 void
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +0000213 printSummary() const final;
Weiwei Liu245d7912016-07-28 00:04:25 -0700214
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700215PUBLIC_WITH_TESTS_ELSE_PROTECTED:
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000216 static constexpr double MIN_SSTHRESH = 2.0;
Weiwei Liu245d7912016-07-28 00:04:25 -0700217 const Options m_options;
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700218
219 double m_cwnd; ///< current congestion window size (in segments)
220 double m_ssthresh; ///< current slow start threshold
221
222PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Davide Pesavento5e3773d2019-08-22 15:35:08 -0400223 RttEstimatorWithStats& m_rttEstimator;
Weiwei Liu245d7912016-07-28 00:04:25 -0700224 Scheduler m_scheduler;
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500225 scheduler::ScopedEventId m_checkRtoEvent;
226
Weiwei Liu245d7912016-07-28 00:04:25 -0700227 uint64_t m_highData; ///< the highest segment number of the Data packet the consumer has received so far
228 uint64_t m_highInterest; ///< the highest segment number of the Interests the consumer has sent so far
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500229 uint64_t m_recPoint; ///< the value of m_highInterest when a packet loss event occurred,
230 ///< it remains fixed until the next packet loss event happens
Weiwei Liu245d7912016-07-28 00:04:25 -0700231
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500232 int64_t m_nInFlight; ///< # of segments in flight
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700233 int64_t m_nLossDecr; ///< # of window decreases caused by packet loss
234 int64_t m_nMarkDecr; ///< # of window decreases caused by congestion marks
235 int64_t m_nTimeouts; ///< # of timed out segments
236 int64_t m_nSkippedRetx; ///< # of segments queued for retransmission but received before the
237 ///< retransmission occurred
238 int64_t m_nRetransmitted; ///< # of retransmitted segments
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239 int64_t m_nCongMarks; ///< # of data packets with congestion mark
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400240 int64_t m_nSent; ///< # of interest packets sent out (including retransmissions)
Weiwei Liu245d7912016-07-28 00:04:25 -0700241
Davide Pesavento958896e2017-01-19 00:52:04 -0500242 std::unordered_map<uint64_t, SegmentInfo> m_segmentInfo; ///< keeps all the internal information
243 ///< on sent but not acked segments
244 std::unordered_map<uint64_t, int> m_retxCount; ///< maps segment number to its retransmission count;
Weiwei Liu245d7912016-07-28 00:04:25 -0700245 ///< if the count reaches to the maximum number of
246 ///< timeout/nack retries, the pipeline will be aborted
Davide Pesavento958896e2017-01-19 00:52:04 -0500247 std::queue<uint64_t> m_retxQueue;
248
Weiwei Liu245d7912016-07-28 00:04:25 -0700249 bool m_hasFailure;
250 uint64_t m_failedSegNo;
251 std::string m_failureReason;
252};
253
Weiwei Liu245d7912016-07-28 00:04:25 -0700254} // namespace chunks
255} // namespace ndn
256
schneiderklausd8197df2019-03-16 11:31:40 -0700257#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_ADAPTIVE_HPP