blob: 7b7aad852abe995a549c544aef81f1dbe7ac607e [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 Pesaventob3570c62022-02-19 19:19:00 -05003 * Copyright (c) 2016-2022, 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
Weiwei Liu245d7912016-07-28 00:04:25 -070032#include "pipeline-interests.hpp"
33
Davide Pesavento70576402019-06-07 16:42:21 -040034#include <ndn-cxx/util/rtt-estimator.hpp>
Davide Pesaventoa0e6b602021-01-21 19:47:04 -050035#include <ndn-cxx/util/signal.hpp>
Davide Pesavento70576402019-06-07 16:42:21 -040036
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
Davide Pesaventob3570c62022-02-19 19:19:00 -050040namespace ndn::chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070041
Davide Pesavento5e3773d2019-08-22 15:35:08 -040042using util::RttEstimatorWithStats;
Davide Pesavento70576402019-06-07 16:42:21 -040043
Weiwei Liu245d7912016-07-28 00:04:25 -070044/**
45 * @brief indicates the state of the segment
46 */
47enum class SegmentState {
48 FirstTimeSent, ///< segment has been sent for the first time
49 InRetxQueue, ///< segment is in retransmission queue
50 Retransmitted, ///< segment has been retransmitted
Weiwei Liu245d7912016-07-28 00:04:25 -070051};
52
53std::ostream&
54operator<<(std::ostream& os, SegmentState state);
55
56/**
57 * @brief Wraps up information that's necessary for segment transmission
58 */
59struct SegmentInfo
60{
Junxiao Shi06d008c2019-02-04 08:26:59 +000061 ScopedPendingInterestHandle interestHdl;
Davide Pesaventof8d9a532021-07-03 16:04:12 -040062 time::steady_clock::time_point timeSent;
Davide Pesaventoba560662019-06-26 22:45:44 -040063 time::nanoseconds rto;
Davide Pesavento958896e2017-01-19 00:52:04 -050064 SegmentState state;
Weiwei Liu245d7912016-07-28 00:04:25 -070065};
66
67/**
68 * @brief Service for retrieving Data via an Interest pipeline
69 *
schneiderklausd8197df2019-03-16 11:31:40 -070070 * Retrieves all segmented Data under the specified prefix by maintaining a dynamic
Weiwei Liu245d7912016-07-28 00:04:25 -070071 * congestion window combined with a Conservative Loss Adaptation algorithm. For details,
72 * please refer to the description in section "Interest pipeline types in ndncatchunks" of
73 * tools/chunks/README.md
74 *
75 * Provides retrieved Data on arrival with no ordering guarantees. Data is delivered to the
76 * PipelineInterests' user via callback immediately upon arrival.
77 */
schneiderklausd8197df2019-03-16 11:31:40 -070078class PipelineInterestsAdaptive : public PipelineInterests
Weiwei Liu245d7912016-07-28 00:04:25 -070079{
80public:
Weiwei Liu245d7912016-07-28 00:04:25 -070081 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -070082 * @brief Constructor.
Weiwei Liu245d7912016-07-28 00:04:25 -070083 *
84 * Configures the pipelining service without specifying the retrieval namespace. After this
85 * configuration the method run must be called to start the Pipeline.
86 */
Davide Pesavento97a33b22019-10-17 22:10:47 -040087 PipelineInterestsAdaptive(Face& face, RttEstimatorWithStats& rttEstimator, const Options& opts);
Weiwei Liu245d7912016-07-28 00:04:25 -070088
Klaus Schneider9e5122b2019-03-19 17:03:25 -070089 ~PipelineInterestsAdaptive() override;
Weiwei Liu245d7912016-07-28 00:04:25 -070090
91 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -070092 * @brief Signals when the congestion window changes.
Weiwei Liu245d7912016-07-28 00:04:25 -070093 *
Davide Pesavento70576402019-06-07 16:42:21 -040094 * The callback function should be: `void(nanoseconds age, double cwnd)`, where `age` is the
95 * time since the pipeline started and `cwnd` is the new congestion window size (in segments).
Weiwei Liu245d7912016-07-28 00:04:25 -070096 */
Davide Pesaventoa0e6b602021-01-21 19:47:04 -050097 util::Signal<PipelineInterestsAdaptive, time::nanoseconds, double> afterCwndChange;
Weiwei Liu245d7912016-07-28 00:04:25 -070098
Davide Pesavento5e3773d2019-08-22 15:35:08 -040099 struct RttSample
100 {
101 uint64_t segNum; ///< segment number on which this sample was taken
102 time::nanoseconds rtt; ///< measured RTT
103 time::nanoseconds sRtt; ///< smoothed RTT
104 time::nanoseconds rttVar; ///< RTT variation
105 time::nanoseconds rto; ///< retransmission timeout
106 };
107
108 /**
109 * @brief Signals when a new RTT sample has been taken.
110 */
Davide Pesaventoa0e6b602021-01-21 19:47:04 -0500111 util::Signal<PipelineInterestsAdaptive, RttSample> afterRttMeasurement;
Davide Pesavento5e3773d2019-08-22 15:35:08 -0400112
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700113protected:
114 DECLARE_SIGNAL_EMIT(afterCwndChange)
115
Davide Pesavento97a33b22019-10-17 22:10:47 -0400116 void
117 printOptions() const;
118
Weiwei Liu245d7912016-07-28 00:04:25 -0700119private:
120 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700121 * @brief Increase congestion window.
122 */
123 virtual void
124 increaseWindow() = 0;
125
126 /**
127 * @brief Decrease congestion window.
128 */
129 virtual void
130 decreaseWindow() = 0;
131
132private:
133 /**
134 * @brief Fetch all the segments between 0 and lastSegment of the specified prefix.
Weiwei Liu245d7912016-07-28 00:04:25 -0700135 *
schneiderklausd8197df2019-03-16 11:31:40 -0700136 * Starts the pipeline with an adaptive window algorithm to control the window size.
137 * The pipeline will fetch every segment until the last segment is successfully received
138 * or an error occurs.
Weiwei Liu245d7912016-07-28 00:04:25 -0700139 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500140 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700141 doRun() final;
142
143 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700144 * @brief Stop all fetch operations.
Weiwei Liu245d7912016-07-28 00:04:25 -0700145 */
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500146 void
Weiwei Liu245d7912016-07-28 00:04:25 -0700147 doCancel() final;
148
149 /**
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700150 * @brief Check RTO for all sent-but-not-acked segments.
Weiwei Liu245d7912016-07-28 00:04:25 -0700151 */
152 void
153 checkRto();
154
155 /**
156 * @param segNo the segment # of the to-be-sent Interest
157 * @param isRetransmission true if this is a retransmission
158 */
159 void
160 sendInterest(uint64_t segNo, bool isRetransmission);
161
162 void
163 schedulePackets();
164
165 void
166 handleData(const Interest& interest, const Data& data);
167
168 void
169 handleNack(const Interest& interest, const lp::Nack& nack);
170
171 void
172 handleLifetimeExpiration(const Interest& interest);
173
174 void
Sichen Song40eae032022-05-01 16:33:00 -0700175 recordTimeout(uint64_t segNo);
Davide Pesavento958896e2017-01-19 00:52:04 -0500176
177 void
178 enqueueForRetransmission(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700179
180 void
181 handleFail(uint64_t segNo, const std::string& reason);
182
Weiwei Liu245d7912016-07-28 00:04:25 -0700183 void
Davide Pesavento958896e2017-01-19 00:52:04 -0500184 cancelInFlightSegmentsGreaterThan(uint64_t segNo);
Weiwei Liu245d7912016-07-28 00:04:25 -0700185
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400186PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Weiwei Liu245d7912016-07-28 00:04:25 -0700187 void
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +0000188 printSummary() const final;
Weiwei Liu245d7912016-07-28 00:04:25 -0700189
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700190PUBLIC_WITH_TESTS_ELSE_PROTECTED:
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000191 static constexpr double MIN_SSTHRESH = 2.0;
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700192
193 double m_cwnd; ///< current congestion window size (in segments)
194 double m_ssthresh; ///< current slow start threshold
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700195 RttEstimatorWithStats& m_rttEstimator;
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700196
197PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Weiwei Liu245d7912016-07-28 00:04:25 -0700198 Scheduler m_scheduler;
Davide Pesaventocd65c2c2017-01-15 16:10:38 -0500199 scheduler::ScopedEventId m_checkRtoEvent;
200
Davide Pesaventob3570c62022-02-19 19:19:00 -0500201 uint64_t m_highData = 0; ///< the highest segment number of the Data packet the consumer has received so far
202 uint64_t m_highInterest = 0; ///< the highest segment number of the Interests the consumer has sent so far
203 uint64_t m_recPoint = 0; ///< the value of m_highInterest when a packet loss event occurred,
204 ///< it remains fixed until the next packet loss event happens
Weiwei Liu245d7912016-07-28 00:04:25 -0700205
Davide Pesaventob3570c62022-02-19 19:19:00 -0500206 int64_t m_nInFlight = 0; ///< # of segments in flight
207 int64_t m_nLossDecr = 0; ///< # of window decreases caused by packet loss
208 int64_t m_nMarkDecr = 0; ///< # of window decreases caused by congestion marks
209 int64_t m_nTimeouts = 0; ///< # of timed out segments
210 int64_t m_nSkippedRetx = 0; ///< # of segments queued for retransmission but received before the
211 ///< retransmission occurred
212 int64_t m_nRetransmitted = 0; ///< # of retransmitted segments
213 int64_t m_nCongMarks = 0; ///< # of data packets with congestion mark
214 int64_t m_nSent = 0; ///< # of interest packets sent out (including retransmissions)
Weiwei Liu245d7912016-07-28 00:04:25 -0700215
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
Davide Pesaventob3570c62022-02-19 19:19:00 -0500223 bool m_hasFailure = false;
224 uint64_t m_failedSegNo = 0;
Weiwei Liu245d7912016-07-28 00:04:25 -0700225 std::string m_failureReason;
226};
227
Davide Pesaventob3570c62022-02-19 19:19:00 -0500228} // namespace ndn::chunks
Weiwei Liu245d7912016-07-28 00:04:25 -0700229
schneiderklausd8197df2019-03-16 11:31:40 -0700230#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_ADAPTIVE_HPP