blob: 492229fdd59f2513b6b749294ce4a81d996c8d45 [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 Pesavento11fc3eb2024-01-26 01:46:56 -05003 * Copyright (c) 2016-2024, 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#include "pipeline-interests-adaptive.hpp"
Davide Pesavento44b3b232017-12-23 16:58:25 -050030#include "data-fetcher.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070031
Davide Pesavento5748e822024-01-26 18:40:22 -050032#include <boost/lexical_cast.hpp>
Chavoosh Ghasemi3dae1092017-12-21 12:39:08 -070033#include <iomanip>
Davide Pesavento5748e822024-01-26 18:40:22 -050034#include <iostream>
Weiwei Liu245d7912016-07-28 00:04:25 -070035
Davide Pesaventob3570c62022-02-19 19:19:00 -050036namespace ndn::chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070037
Davide Pesavento5e3773d2019-08-22 15:35:08 -040038PipelineInterestsAdaptive::PipelineInterestsAdaptive(Face& face,
39 RttEstimatorWithStats& rttEstimator,
Davide Pesavento97a33b22019-10-17 22:10:47 -040040 const Options& opts)
41 : PipelineInterests(face, opts)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070042 , m_cwnd(m_options.initCwnd)
43 , m_ssthresh(m_options.initSsthresh)
Weiwei Liu245d7912016-07-28 00:04:25 -070044 , m_rttEstimator(rttEstimator)
Davide Pesavento7e9d7e42023-11-11 15:00:03 -050045 , m_scheduler(m_face.getIoContext())
Weiwei Liu245d7912016-07-28 00:04:25 -070046{
Weiwei Liu245d7912016-07-28 00:04:25 -070047}
48
schneiderklausd8197df2019-03-16 11:31:40 -070049PipelineInterestsAdaptive::~PipelineInterestsAdaptive()
Weiwei Liu245d7912016-07-28 00:04:25 -070050{
51 cancel();
52}
53
54void
schneiderklausd8197df2019-03-16 11:31:40 -070055PipelineInterestsAdaptive::doRun()
Weiwei Liu245d7912016-07-28 00:04:25 -070056{
Ryan Wickman034f30f2018-06-06 11:11:11 -050057 if (allSegmentsReceived()) {
58 cancel();
59 if (!m_options.isQuiet) {
60 printSummary();
61 }
62 return;
63 }
64
Weiwei Liu245d7912016-07-28 00:04:25 -070065 // schedule the event to check retransmission timer
Davide Pesaventobf2c5172019-03-20 19:08:09 -040066 m_checkRtoEvent = m_scheduler.schedule(m_options.rtoCheckInterval, [this] { checkRto(); });
Weiwei Liu245d7912016-07-28 00:04:25 -070067
Davide Pesavento958896e2017-01-19 00:52:04 -050068 schedulePackets();
Weiwei Liu245d7912016-07-28 00:04:25 -070069}
70
71void
schneiderklausd8197df2019-03-16 11:31:40 -070072PipelineInterestsAdaptive::doCancel()
Weiwei Liu245d7912016-07-28 00:04:25 -070073{
Davide Pesaventocd65c2c2017-01-15 16:10:38 -050074 m_checkRtoEvent.cancel();
Weiwei Liu245d7912016-07-28 00:04:25 -070075 m_segmentInfo.clear();
Weiwei Liu245d7912016-07-28 00:04:25 -070076}
77
78void
schneiderklausd8197df2019-03-16 11:31:40 -070079PipelineInterestsAdaptive::checkRto()
Weiwei Liu245d7912016-07-28 00:04:25 -070080{
81 if (isStopping())
82 return;
83
Davide Pesavento958896e2017-01-19 00:52:04 -050084 bool hasTimeout = false;
Sichen Song40eae032022-05-01 16:33:00 -070085 uint64_t highTimeoutSeg = 0;
Weiwei Liu245d7912016-07-28 00:04:25 -070086
87 for (auto& entry : m_segmentInfo) {
88 SegmentInfo& segInfo = entry.second;
Ryan Wickman2c9933c2018-06-12 11:51:51 -050089 if (segInfo.state != SegmentState::InRetxQueue) { // skip segments already in the retx queue
Davide Pesavento70576402019-06-07 16:42:21 -040090 auto timeElapsed = time::steady_clock::now() - segInfo.timeSent;
91 if (timeElapsed > segInfo.rto) { // timer expired?
schneiderklaus8ff3abd2019-03-12 22:15:12 -070092 m_nTimeouts++;
Davide Pesavento958896e2017-01-19 00:52:04 -050093 hasTimeout = true;
Sichen Song40eae032022-05-01 16:33:00 -070094 highTimeoutSeg = std::max(highTimeoutSeg, entry.first);
Davide Pesavento958896e2017-01-19 00:52:04 -050095 enqueueForRetransmission(entry.first);
Weiwei Liu245d7912016-07-28 00:04:25 -070096 }
97 }
98 }
99
Davide Pesavento958896e2017-01-19 00:52:04 -0500100 if (hasTimeout) {
Sichen Song40eae032022-05-01 16:33:00 -0700101 recordTimeout(highTimeoutSeg);
Davide Pesavento958896e2017-01-19 00:52:04 -0500102 schedulePackets();
Weiwei Liu245d7912016-07-28 00:04:25 -0700103 }
104
105 // schedule the next check after predefined interval
Davide Pesaventobf2c5172019-03-20 19:08:09 -0400106 m_checkRtoEvent = m_scheduler.schedule(m_options.rtoCheckInterval, [this] { checkRto(); });
Weiwei Liu245d7912016-07-28 00:04:25 -0700107}
108
109void
schneiderklausd8197df2019-03-16 11:31:40 -0700110PipelineInterestsAdaptive::sendInterest(uint64_t segNo, bool isRetransmission)
Weiwei Liu245d7912016-07-28 00:04:25 -0700111{
112 if (isStopping())
113 return;
114
Ryan Wickman034f30f2018-06-06 11:11:11 -0500115 if (m_hasFinalBlockId && segNo > m_lastSegmentNo)
Weiwei Liu245d7912016-07-28 00:04:25 -0700116 return;
117
118 if (!isRetransmission && m_hasFailure)
119 return;
120
121 if (m_options.isVerbose) {
Davide Pesavento958896e2017-01-19 00:52:04 -0500122 std::cerr << (isRetransmission ? "Retransmitting" : "Requesting")
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400123 << " segment #" << segNo << "\n";
Weiwei Liu245d7912016-07-28 00:04:25 -0700124 }
125
126 if (isRetransmission) {
Davide Pesavento958896e2017-01-19 00:52:04 -0500127 // keep track of retx count for this segment
128 auto ret = m_retxCount.emplace(segNo, 1);
Davide Pesaventob3570c62022-02-19 19:19:00 -0500129 if (!ret.second) { // not the first retransmission
Weiwei Liu245d7912016-07-28 00:04:25 -0700130 m_retxCount[segNo] += 1;
Davide Pesavento44b3b232017-12-23 16:58:25 -0500131 if (m_options.maxRetriesOnTimeoutOrNack != DataFetcher::MAX_RETRIES_INFINITE &&
132 m_retxCount[segNo] > m_options.maxRetriesOnTimeoutOrNack) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700133 return handleFail(segNo, "Reached the maximum number of retries (" +
Davide Pesavento11fc3eb2024-01-26 01:46:56 -0500134 std::to_string(m_options.maxRetriesOnTimeoutOrNack) +
135 ") while retrieving segment #" + std::to_string(segNo));
Weiwei Liu245d7912016-07-28 00:04:25 -0700136 }
137
138 if (m_options.isVerbose) {
139 std::cerr << "# of retries for segment #" << segNo
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400140 << " is " << m_retxCount[segNo] << "\n";
Weiwei Liu245d7912016-07-28 00:04:25 -0700141 }
142 }
Weiwei Liu245d7912016-07-28 00:04:25 -0700143 }
144
Davide Pesavento84d84772019-04-07 14:40:07 -0400145 auto interest = Interest()
146 .setName(Name(m_prefix).appendSegment(segNo))
Davide Pesavento84d84772019-04-07 14:40:07 -0400147 .setMustBeFresh(m_options.mustBeFresh)
148 .setInterestLifetime(m_options.interestLifetime);
Weiwei Liu245d7912016-07-28 00:04:25 -0700149
Junxiao Shi06d008c2019-02-04 08:26:59 +0000150 SegmentInfo& segInfo = m_segmentInfo[segNo];
151 segInfo.interestHdl = m_face.expressInterest(interest,
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400152 FORWARD_TO_MEM_FN(handleData),
153 FORWARD_TO_MEM_FN(handleNack),
154 FORWARD_TO_MEM_FN(handleLifetimeExpiration));
Junxiao Shi06d008c2019-02-04 08:26:59 +0000155 segInfo.timeSent = time::steady_clock::now();
156 segInfo.rto = m_rttEstimator.getEstimatedRto();
157
Weiwei Liu245d7912016-07-28 00:04:25 -0700158 m_nInFlight++;
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400159 m_nSent++;
Weiwei Liu245d7912016-07-28 00:04:25 -0700160
161 if (isRetransmission) {
Davide Pesavento958896e2017-01-19 00:52:04 -0500162 segInfo.state = SegmentState::Retransmitted;
Weiwei Liu245d7912016-07-28 00:04:25 -0700163 m_nRetransmitted++;
164 }
165 else {
166 m_highInterest = segNo;
Junxiao Shi06d008c2019-02-04 08:26:59 +0000167 segInfo.state = SegmentState::FirstTimeSent;
Weiwei Liu245d7912016-07-28 00:04:25 -0700168 }
169}
170
171void
schneiderklausd8197df2019-03-16 11:31:40 -0700172PipelineInterestsAdaptive::schedulePackets()
Weiwei Liu245d7912016-07-28 00:04:25 -0700173{
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500174 BOOST_ASSERT(m_nInFlight >= 0);
175 auto availableWindowSize = static_cast<int64_t>(m_cwnd) - m_nInFlight;
176
Weiwei Liu245d7912016-07-28 00:04:25 -0700177 while (availableWindowSize > 0) {
178 if (!m_retxQueue.empty()) { // do retransmission first
179 uint64_t retxSegNo = m_retxQueue.front();
180 m_retxQueue.pop();
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500181 if (m_segmentInfo.count(retxSegNo) == 0) {
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700182 m_nSkippedRetx++;
Weiwei Liu245d7912016-07-28 00:04:25 -0700183 continue;
184 }
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500185 // the segment is still in the map, that means it needs to be retransmitted
Weiwei Liu245d7912016-07-28 00:04:25 -0700186 sendInterest(retxSegNo, true);
187 }
188 else { // send next segment
189 sendInterest(getNextSegmentNo(), false);
190 }
191 availableWindowSize--;
192 }
193}
194
195void
schneiderklausd8197df2019-03-16 11:31:40 -0700196PipelineInterestsAdaptive::handleData(const Interest& interest, const Data& data)
Weiwei Liu245d7912016-07-28 00:04:25 -0700197{
198 if (isStopping())
199 return;
200
Davide Pesavento84d84772019-04-07 14:40:07 -0400201 // Interest was expressed with CanBePrefix=false
Weiwei Liu245d7912016-07-28 00:04:25 -0700202 BOOST_ASSERT(data.getName().equals(interest.getName()));
203
Davide Pesavento969cd5a2018-04-20 16:27:47 -0400204 if (!m_hasFinalBlockId && data.getFinalBlock()) {
205 m_lastSegmentNo = data.getFinalBlock()->toSegment();
Weiwei Liu245d7912016-07-28 00:04:25 -0700206 m_hasFinalBlockId = true;
207 cancelInFlightSegmentsGreaterThan(m_lastSegmentNo);
208 if (m_hasFailure && m_lastSegmentNo >= m_failedSegNo) {
209 // previously failed segment is part of the content
210 return onFailure(m_failureReason);
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +0000211 }
212 else {
Weiwei Liu245d7912016-07-28 00:04:25 -0700213 m_hasFailure = false;
214 }
215 }
216
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500217 uint64_t recvSegNo = getSegmentFromPacket(data);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500218 auto segIt = m_segmentInfo.find(recvSegNo);
219 if (segIt == m_segmentInfo.end()) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700220 return; // ignore already-received segment
221 }
222
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500223 SegmentInfo& segInfo = segIt->second;
Davide Pesaventoba560662019-06-26 22:45:44 -0400224 time::nanoseconds rtt = time::steady_clock::now() - segInfo.timeSent;
Weiwei Liu245d7912016-07-28 00:04:25 -0700225 if (m_options.isVerbose) {
226 std::cerr << "Received segment #" << recvSegNo
Davide Pesaventoba560662019-06-26 22:45:44 -0400227 << ", rtt=" << rtt.count() / 1e6 << "ms"
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400228 << ", rto=" << segInfo.rto.count() / 1e6 << "ms\n";
Weiwei Liu245d7912016-07-28 00:04:25 -0700229 }
230
Sichen Song40eae032022-05-01 16:33:00 -0700231 m_highData = std::max(m_highData, recvSegNo);
Davide Pesavento958896e2017-01-19 00:52:04 -0500232
233 // for segments in retx queue, we must not decrement m_nInFlight
234 // because it was already decremented when the segment timed out
235 if (segInfo.state != SegmentState::InRetxQueue) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700236 m_nInFlight--;
237 }
238
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239 // upon finding congestion mark, decrease the window size
240 // without retransmitting any packet
241 if (data.getCongestionMark() > 0) {
242 m_nCongMarks++;
243 if (!m_options.ignoreCongMarks) {
244 if (m_options.disableCwa || m_highData > m_recPoint) {
245 m_recPoint = m_highInterest; // react to only one congestion event (timeout or congestion mark)
246 // per RTT (conservative window adaptation)
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700247 m_nMarkDecr++;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000248 decreaseWindow();
249
250 if (m_options.isVerbose) {
251 std::cerr << "Received congestion mark, value = " << data.getCongestionMark()
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400252 << ", new cwnd = " << m_cwnd << "\n";
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000253 }
254 }
255 }
256 else {
257 increaseWindow();
258 }
259 }
260 else {
261 increaseWindow();
262 }
263
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400264 onData(data);
Weiwei Liu245d7912016-07-28 00:04:25 -0700265
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500266 // do not sample RTT for retransmitted segments
267 if ((segInfo.state == SegmentState::FirstTimeSent ||
268 segInfo.state == SegmentState::InRetxQueue) &&
269 m_retxCount.count(recvSegNo) == 0) {
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500270 auto nExpectedSamples = std::max<int64_t>((m_nInFlight + 1) >> 1, 1);
271 BOOST_ASSERT(nExpectedSamples > 0);
Davide Pesavento5e3773d2019-08-22 15:35:08 -0400272 m_rttEstimator.addMeasurement(rtt, static_cast<size_t>(nExpectedSamples));
273 afterRttMeasurement({recvSegNo, rtt,
274 m_rttEstimator.getSmoothedRtt(),
275 m_rttEstimator.getRttVariation(),
276 m_rttEstimator.getEstimatedRto()});
Weiwei Liu245d7912016-07-28 00:04:25 -0700277 }
278
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500279 // remove the entry associated with the received segment
280 m_segmentInfo.erase(segIt);
281
Ryan Wickman034f30f2018-06-06 11:11:11 -0500282 if (allSegmentsReceived()) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700283 cancel();
Davide Pesaventof6991e12018-01-08 20:58:50 -0500284 if (!m_options.isQuiet) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700285 printSummary();
286 }
287 }
288 else {
289 schedulePackets();
290 }
291}
292
293void
schneiderklausd8197df2019-03-16 11:31:40 -0700294PipelineInterestsAdaptive::handleNack(const Interest& interest, const lp::Nack& nack)
Weiwei Liu245d7912016-07-28 00:04:25 -0700295{
296 if (isStopping())
297 return;
298
299 if (m_options.isVerbose)
300 std::cerr << "Received Nack with reason " << nack.getReason()
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400301 << " for Interest " << interest << "\n";
Weiwei Liu245d7912016-07-28 00:04:25 -0700302
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500303 uint64_t segNo = getSegmentFromPacket(interest);
Weiwei Liu245d7912016-07-28 00:04:25 -0700304
305 switch (nack.getReason()) {
Davide Pesavento958896e2017-01-19 00:52:04 -0500306 case lp::NackReason::DUPLICATE:
307 // ignore duplicates
Weiwei Liu245d7912016-07-28 00:04:25 -0700308 break;
Davide Pesavento958896e2017-01-19 00:52:04 -0500309 case lp::NackReason::CONGESTION:
310 // treated the same as timeout for now
311 enqueueForRetransmission(segNo);
Sichen Song40eae032022-05-01 16:33:00 -0700312 recordTimeout(segNo);
Davide Pesavento958896e2017-01-19 00:52:04 -0500313 schedulePackets();
314 break;
315 default:
Weiwei Liu245d7912016-07-28 00:04:25 -0700316 handleFail(segNo, "Could not retrieve data for " + interest.getName().toUri() +
317 ", reason: " + boost::lexical_cast<std::string>(nack.getReason()));
318 break;
Weiwei Liu245d7912016-07-28 00:04:25 -0700319 }
320}
321
322void
schneiderklausd8197df2019-03-16 11:31:40 -0700323PipelineInterestsAdaptive::handleLifetimeExpiration(const Interest& interest)
Weiwei Liu245d7912016-07-28 00:04:25 -0700324{
325 if (isStopping())
326 return;
327
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700328 m_nTimeouts++;
Sichen Song40eae032022-05-01 16:33:00 -0700329
330 uint64_t segNo = getSegmentFromPacket(interest);
331 enqueueForRetransmission(segNo);
332 recordTimeout(segNo);
Davide Pesavento958896e2017-01-19 00:52:04 -0500333 schedulePackets();
Weiwei Liu245d7912016-07-28 00:04:25 -0700334}
335
336void
Sichen Song40eae032022-05-01 16:33:00 -0700337PipelineInterestsAdaptive::recordTimeout(uint64_t segNo)
Weiwei Liu245d7912016-07-28 00:04:25 -0700338{
Sichen Song40eae032022-05-01 16:33:00 -0700339 if (m_options.disableCwa || segNo > m_recPoint) {
340 // interests that are still outstanding during a timeout event
341 // should not trigger another window decrease later (bug #5202)
Weiwei Liu245d7912016-07-28 00:04:25 -0700342 m_recPoint = m_highInterest;
343
344 decreaseWindow();
345 m_rttEstimator.backoffRto();
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700346 m_nLossDecr++;
Weiwei Liu245d7912016-07-28 00:04:25 -0700347
348 if (m_options.isVerbose) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000349 std::cerr << "Packet loss event, new cwnd = " << m_cwnd
Davide Pesaventof8d9a532021-07-03 16:04:12 -0400350 << ", ssthresh = " << m_ssthresh << "\n";
Weiwei Liu245d7912016-07-28 00:04:25 -0700351 }
352 }
Davide Pesavento958896e2017-01-19 00:52:04 -0500353}
Weiwei Liu245d7912016-07-28 00:04:25 -0700354
Davide Pesavento958896e2017-01-19 00:52:04 -0500355void
schneiderklausd8197df2019-03-16 11:31:40 -0700356PipelineInterestsAdaptive::enqueueForRetransmission(uint64_t segNo)
Davide Pesavento958896e2017-01-19 00:52:04 -0500357{
358 BOOST_ASSERT(m_nInFlight > 0);
359 m_nInFlight--;
360 m_retxQueue.push(segNo);
361 m_segmentInfo.at(segNo).state = SegmentState::InRetxQueue;
Weiwei Liu245d7912016-07-28 00:04:25 -0700362}
363
364void
schneiderklausd8197df2019-03-16 11:31:40 -0700365PipelineInterestsAdaptive::handleFail(uint64_t segNo, const std::string& reason)
Weiwei Liu245d7912016-07-28 00:04:25 -0700366{
367 if (isStopping())
368 return;
369
370 // if the failed segment is definitely part of the content, raise a fatal error
371 if (m_hasFinalBlockId && segNo <= m_lastSegmentNo)
372 return onFailure(reason);
373
374 if (!m_hasFinalBlockId) {
375 m_segmentInfo.erase(segNo);
Davide Pesavento958896e2017-01-19 00:52:04 -0500376 m_nInFlight--;
Weiwei Liu245d7912016-07-28 00:04:25 -0700377
378 if (m_segmentInfo.empty()) {
379 onFailure("Fetching terminated but no final segment number has been found");
380 }
381 else {
382 cancelInFlightSegmentsGreaterThan(segNo);
383 m_hasFailure = true;
384 m_failedSegNo = segNo;
385 m_failureReason = reason;
386 }
387 }
388}
389
390void
schneiderklausd8197df2019-03-16 11:31:40 -0700391PipelineInterestsAdaptive::cancelInFlightSegmentsGreaterThan(uint64_t segNo)
Weiwei Liu245d7912016-07-28 00:04:25 -0700392{
393 for (auto it = m_segmentInfo.begin(); it != m_segmentInfo.end();) {
394 // cancel fetching all segments that follow
Davide Pesavento958896e2017-01-19 00:52:04 -0500395 if (it->first > segNo) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700396 it = m_segmentInfo.erase(it);
Davide Pesavento958896e2017-01-19 00:52:04 -0500397 m_nInFlight--;
Weiwei Liu245d7912016-07-28 00:04:25 -0700398 }
399 else {
400 ++it;
401 }
402 }
403}
404
405void
Davide Pesavento97a33b22019-10-17 22:10:47 -0400406PipelineInterestsAdaptive::printOptions() const
407{
408 PipelineInterests::printOptions();
409 std::cerr
410 << "\tInitial congestion window size = " << m_options.initCwnd << "\n"
411 << "\tInitial slow start threshold = " << m_options.initSsthresh << "\n"
412 << "\tAdditive increase step = " << m_options.aiStep << "\n"
413 << "\tMultiplicative decrease factor = " << m_options.mdCoef << "\n"
414 << "\tRTO check interval = " << m_options.rtoCheckInterval << "\n"
415 << "\tReact to congestion marks = " << (m_options.ignoreCongMarks ? "no" : "yes") << "\n"
416 << "\tConservative window adaptation = " << (m_options.disableCwa ? "no" : "yes") << "\n"
417 << "\tResetting window to " << (m_options.resetCwndToInit ?
418 "initial value" : "ssthresh") << " upon loss event\n";
419}
420
421void
schneiderklausd8197df2019-03-16 11:31:40 -0700422PipelineInterestsAdaptive::printSummary() const
Weiwei Liu245d7912016-07-28 00:04:25 -0700423{
Chavoosh Ghasemi4d36ed52017-10-31 22:26:25 +0000424 PipelineInterests::printSummary();
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700425 std::cerr << "Congestion marks: " << m_nCongMarks << " (caused " << m_nMarkDecr << " window decreases)\n"
426 << "Timeouts: " << m_nTimeouts << " (caused " << m_nLossDecr << " window decreases)\n"
427 << "Retransmitted segments: " << m_nRetransmitted
Davide Pesaventoba560662019-06-26 22:45:44 -0400428 << " (" << (m_nSent == 0 ? 0 : (m_nRetransmitted * 100.0 / m_nSent)) << "%)"
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700429 << ", skipped: " << m_nSkippedRetx << "\n"
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400430 << "RTT ";
431
Davide Pesaventoba560662019-06-26 22:45:44 -0400432 if (m_rttEstimator.getMinRtt() == time::nanoseconds::max() ||
433 m_rttEstimator.getMaxRtt() == time::nanoseconds::min()) {
Davide Pesavento70576402019-06-07 16:42:21 -0400434 std::cerr << "stats unavailable\n";
435 }
436 else {
437 std::cerr << "min/avg/max = " << std::fixed << std::setprecision(3)
Davide Pesaventoba560662019-06-26 22:45:44 -0400438 << m_rttEstimator.getMinRtt().count() / 1e6 << "/"
439 << m_rttEstimator.getAvgRtt().count() / 1e6 << "/"
440 << m_rttEstimator.getMaxRtt().count() / 1e6 << " ms\n";
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400441 }
Weiwei Liu245d7912016-07-28 00:04:25 -0700442}
443
444std::ostream&
445operator<<(std::ostream& os, SegmentState state)
446{
447 switch (state) {
448 case SegmentState::FirstTimeSent:
449 os << "FirstTimeSent";
450 break;
451 case SegmentState::InRetxQueue:
452 os << "InRetxQueue";
453 break;
454 case SegmentState::Retransmitted:
455 os << "Retransmitted";
456 break;
Weiwei Liu245d7912016-07-28 00:04:25 -0700457 }
Weiwei Liu245d7912016-07-28 00:04:25 -0700458 return os;
459}
460
Davide Pesaventob3570c62022-02-19 19:19:00 -0500461} // namespace ndn::chunks