A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-yeah.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
18 *
19 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
20 * ResiliNets Research Group https://resilinets.org/
21 * Information and Telecommunication Technology Center (ITTC)
22 * and Department of Electrical Engineering and Computer Science
23 * The University of Kansas Lawrence, KS USA.
24 */
25
26#include "tcp-yeah.h"
27
28#include "ns3/log.h"
29
30namespace ns3
31{
32
35
36TypeId
38{
39 static TypeId tid =
40 TypeId("ns3::TcpYeah")
42 .AddConstructor<TcpYeah>()
43 .SetGroupName("Internet")
44 .AddAttribute("Alpha",
45 "Maximum backlog allowed at the bottleneck queue",
46 UintegerValue(80),
48 MakeUintegerChecker<uint32_t>())
49 .AddAttribute("Gamma",
50 "Fraction of queue to be removed per RTT",
53 MakeUintegerChecker<uint32_t>())
54 .AddAttribute("Delta",
55 "Log minimum fraction of cwnd to be removed on loss",
58 MakeUintegerChecker<uint32_t>())
59 .AddAttribute("Epsilon",
60 "Log maximum fraction to be removed on early decongestion",
63 MakeUintegerChecker<uint32_t>())
64 .AddAttribute("Phy",
65 "Maximum delta from base",
68 MakeUintegerChecker<uint32_t>())
69 .AddAttribute("Rho",
70 "Minimum # of consecutive RTT to consider competition on loss",
71 UintegerValue(16),
73 MakeUintegerChecker<uint32_t>())
74 .AddAttribute("Zeta",
75 "Minimum # of state switches to reset m_renoCount",
76 UintegerValue(50),
78 MakeUintegerChecker<uint32_t>())
79 .AddAttribute("StcpAiFactor",
80 "STCP additive increase factor",
81 UintegerValue(100),
83 MakeUintegerChecker<uint32_t>());
84 return tid;
85}
86
88 : TcpNewReno(),
89 m_alpha(80),
90 m_gamma(1),
91 m_delta(3),
92 m_epsilon(1),
93 m_phy(8),
94 m_rho(16),
95 m_zeta(50),
96 m_stcpAiFactor(100),
97 m_stcp(nullptr),
98 m_baseRtt(Time::Max()),
99 m_minRtt(Time::Max()),
100 m_cntRtt(0),
101 m_doingYeahNow(true),
102 m_begSndNxt(0),
103 m_lastQ(0),
104 m_doingRenoNow(0),
105 m_renoCount(2),
106 m_fastCount(0)
107{
108 NS_LOG_FUNCTION(this);
109 m_stcp = CreateObject<TcpScalable>();
110 m_stcp->SetAttribute("AIFactor", static_cast<UintegerValue>(m_stcpAiFactor));
111}
112
114 : TcpNewReno(sock),
115 m_alpha(sock.m_alpha),
116 m_gamma(sock.m_gamma),
117 m_delta(sock.m_delta),
118 m_epsilon(sock.m_epsilon),
119 m_phy(sock.m_phy),
120 m_rho(sock.m_rho),
121 m_zeta(sock.m_zeta),
122 m_stcpAiFactor(sock.m_stcpAiFactor),
123 m_baseRtt(sock.m_baseRtt),
124 m_minRtt(sock.m_minRtt),
125 m_cntRtt(sock.m_cntRtt),
126 m_doingYeahNow(sock.m_doingYeahNow),
127 m_begSndNxt(sock.m_begSndNxt),
128 m_lastQ(sock.m_lastQ),
129 m_doingRenoNow(sock.m_doingRenoNow),
130 m_renoCount(sock.m_renoCount),
131 m_fastCount(sock.m_fastCount)
132{
133 NS_LOG_FUNCTION(this);
134 m_stcp = CopyObject(sock.m_stcp);
135}
136
138{
139 NS_LOG_FUNCTION(this);
140}
141
144{
145 return CopyObject<TcpYeah>(this);
146}
147
148void
150{
151 NS_LOG_FUNCTION(this << tcb << segmentsAcked << rtt);
152
153 if (rtt.IsZero())
154 {
155 return;
156 }
157
158 m_minRtt = std::min(m_minRtt, rtt);
159 NS_LOG_DEBUG("Updated m_minRtt = " << m_minRtt.GetMilliSeconds() << " ms");
160
161 m_baseRtt = std::min(m_baseRtt, rtt);
162 NS_LOG_DEBUG("Updated m_baseRtt = " << m_baseRtt.GetMilliSeconds() << " ms");
163
164 // Update RTT counter
165 m_cntRtt++;
166 NS_LOG_DEBUG("Updated m_cntRtt = " << m_cntRtt);
167}
168
169void
171{
172 NS_LOG_FUNCTION(this << nextTxSequence);
173
174 m_doingYeahNow = true;
175 m_begSndNxt = nextTxSequence;
176 m_cntRtt = 0;
178}
179
180void
182{
183 NS_LOG_FUNCTION(this);
184
185 m_doingYeahNow = false;
186}
187
188void
190{
191 NS_LOG_FUNCTION(this << tcb << newState);
192
193 if (newState == TcpSocketState::CA_OPEN)
194 {
195 EnableYeah(tcb->m_nextTxSequence);
196 }
197 else
198 {
199 DisableYeah();
200 }
201}
202
203void
205{
206 NS_LOG_FUNCTION(this << tcb << segmentsAcked);
207
208 if (tcb->m_cWnd < tcb->m_ssThresh)
209 {
210 NS_LOG_LOGIC("In slow start, invoke NewReno slow start.");
211 TcpNewReno::SlowStart(tcb, segmentsAcked);
212 }
213 else if (!m_doingRenoNow)
214 { // Fast mode
215 NS_LOG_LOGIC("In Fast mode, increment cwnd according to STCP rule.");
216 m_stcp->IncreaseWindow(tcb, segmentsAcked);
217 NS_LOG_INFO("In Fast mode, updated to cwnd " << tcb->m_cWnd << " ssthresh "
218 << tcb->m_ssThresh);
219 }
220 else
221 { // Behave like NewReno
222 TcpNewReno::CongestionAvoidance(tcb, segmentsAcked);
223 }
224
225 if (tcb->m_lastAckedSeq >= m_begSndNxt)
226 { // A YeAH cycle has finished, we do YeAH cwnd adjustment every RTT.
227
228 NS_LOG_LOGIC("A YeAH cycle has finished, check if enough RTT samples.");
229 /*
230 * We perform YeAH calculations only if we got enough RTT samples to
231 * insure that at least 1 of those samples wasn't from a delayed ACK.
232 */
233 if (m_cntRtt > 2)
234 {
235 NS_LOG_LOGIC("Enough RTT samples to perform YeAH calculations");
236 /*
237 * We have enough RTT samples to perform YeAH algorithm.
238 * Now we need to determine if we should operate in Fast or Slow mode,
239 * and if we should execute the precautionary decongestion algorithm.
240 */
241
242 uint32_t segCwnd = tcb->GetCwndInSegments();
243
244 // Calculate the extra number of packets in queue
245 // Naming convention: minRtt is the minimum RTT of this round,
246 // baseRtt is the minimum RTT of the entire transmission.
248 Time rttQueue = m_minRtt - m_baseRtt;
249
250 // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
251 double bw = segCwnd / m_minRtt.GetSeconds();
252 auto queue = static_cast<uint32_t>(bw * rttQueue.GetSeconds());
253 NS_LOG_DEBUG("Queue backlog = " << queue << " given by cwnd = " << segCwnd
254 << ", minRtt = " << m_minRtt.GetMilliSeconds()
255 << " ms, baseRtt = " << m_baseRtt.GetMilliSeconds()
256 << " ms");
257
258 double L = rttQueue.GetSeconds() / m_baseRtt.GetSeconds();
259 NS_LOG_DEBUG("Network congestion level = " << L);
260
261 if (queue > m_alpha || L > (1 / m_phy))
262 { // Slow mode
263 if (queue > m_alpha && segCwnd > m_renoCount)
264 { // Precautionary decongestion
265 NS_LOG_LOGIC("Execute the precautionary decongestion.");
266 uint32_t reduction = std::min(queue / m_gamma, segCwnd >> m_epsilon);
267 segCwnd -= reduction;
268 segCwnd = std::max(segCwnd, m_renoCount);
269 tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
270 tcb->m_ssThresh = tcb->m_cWnd;
271
272 NS_LOG_INFO("In Slow mode, after precautionary decongestion, "
273 "updated to cwnd "
274 << tcb->m_cWnd << " ssthresh " << tcb->m_ssThresh);
275 }
276
277 if (m_renoCount <= 2)
278 {
279 m_renoCount = std::max(segCwnd >> 1, static_cast<uint32_t>(2));
280 }
281 else
282 {
283 m_renoCount++;
284 }
285
287 NS_LOG_DEBUG("In Slow mode, updated to m_renoCount = "
288 << m_renoCount << " m_doingRenoNow = " << m_doingRenoNow);
289 }
290 else
291 { // Fast mode
292 m_fastCount++;
293 if (m_fastCount > m_zeta)
294 { // Reset renoCount
295 m_renoCount = 2;
296 m_fastCount = 0;
297 }
298 m_doingRenoNow = 0;
299 NS_LOG_DEBUG("In Fast mode, updated to m_renoCount = "
300 << m_renoCount << " m_doingRenoNow = " << m_doingRenoNow);
301 }
302 m_lastQ = queue;
303 }
304
305 // Save the current right edge for next Yeah cycle
306 m_begSndNxt = tcb->m_nextTxSequence;
307
308 // Reset cntRtt & minRtt
309 m_cntRtt = 0;
311 }
312}
313
314std::string
316{
317 return "TcpYeah";
318}
319
322{
323 NS_LOG_FUNCTION(this << tcb << bytesInFlight);
324 uint32_t reduction;
325 uint32_t segBytesInFlight = bytesInFlight / tcb->m_segmentSize;
326
327 if (m_doingRenoNow < m_rho)
328 { // Not competing with Reno flows
329 NS_LOG_LOGIC("Not competing with Reno flows upon loss");
330 reduction = m_lastQ;
331 reduction = std::max(reduction, segBytesInFlight >> m_delta);
332 reduction = std::min(reduction, std::max(segBytesInFlight >> 1, 2U));
333 }
334 else
335 { // Competing with Reno flows
336 NS_LOG_LOGIC("Competing with Reno flows upon loss");
337 reduction = std::max(segBytesInFlight >> 1, static_cast<uint32_t>(2));
338 }
339
340 NS_LOG_INFO("Reduction amount upon loss = " << reduction);
341
342 m_fastCount = 0;
343 m_renoCount = std::max(m_renoCount >> 1, static_cast<uint32_t>(2));
344
345 // Allow, at least, 2 segment to go out
346 uint32_t ret =
347 std::max(bytesInFlight - (reduction * tcb->m_segmentSize), 2U * tcb->m_segmentSize);
348 return ret;
349}
350
351} // namespace ns3
#define Max(a, b)
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:592
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
The NewReno implementation.
virtual uint32_t SlowStart(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked)
Tcp NewReno slow start algorithm.
virtual void CongestionAvoidance(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked)
NewReno congestion avoidance.
TcpCongState_t
Definition of the Congestion state machine.
@ CA_OPEN
Normal state, no dubious events.
An implementation of TCP YeAH.
Definition: tcp-yeah.h:73
Time m_minRtt
Minimum of all RTTs measured within last RTT.
Definition: tcp-yeah.h:177
uint32_t m_zeta
Minimum number of state switches to reset m_renoCount.
Definition: tcp-yeah.h:172
void IncreaseWindow(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked) override
Adjust cwnd following YeAH dual-mode algorithm.
Definition: tcp-yeah.cc:204
void PktsAcked(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked, const Time &rtt) override
Compute RTTs needed to execute YeAH algorithm.
Definition: tcp-yeah.cc:149
Ptr< TcpCongestionOps > Fork() override
Copy the congestion control algorithm across sockets.
Definition: tcp-yeah.cc:143
uint32_t m_renoCount
Estimated cwnd of competing Reno flow.
Definition: tcp-yeah.h:183
bool m_doingYeahNow
If true, do YeAH for this RTT.
Definition: tcp-yeah.h:179
void CongestionStateSet(Ptr< TcpSocketState > tcb, const TcpSocketState::TcpCongState_t newState) override
Enable/disable YeAH algorithm depending on the congestion state.
Definition: tcp-yeah.cc:189
static TypeId GetTypeId()
Get the type ID.
Definition: tcp-yeah.cc:37
uint32_t m_cntRtt
Number of RTT measurements during last RTT.
Definition: tcp-yeah.h:178
std::string GetName() const override
Get the name of the congestion control algorithm.
Definition: tcp-yeah.cc:315
uint32_t m_lastQ
Last number of packets in the bottleneck queue.
Definition: tcp-yeah.h:181
uint32_t GetSsThresh(Ptr< const TcpSocketState > tcb, uint32_t bytesInFlight) override
Get slow start threshold upon the receipt of 3 dupACKs.
Definition: tcp-yeah.cc:321
SequenceNumber32 m_begSndNxt
Right edge during last RTT.
Definition: tcp-yeah.h:180
uint32_t m_stcpAiFactor
STCP additive increase parameter.
Definition: tcp-yeah.h:174
Ptr< TcpScalable > m_stcp
TcpScalable object.
Definition: tcp-yeah.h:175
uint32_t m_alpha
Maximum backlog allowed at the bottleneck queue; Q_max in the paper.
Definition: tcp-yeah.h:164
uint32_t m_phy
Maximum delta from base.
Definition: tcp-yeah.h:169
uint32_t m_epsilon
Log maximum fraction to be removed on early decongestion.
Definition: tcp-yeah.h:168
void EnableYeah(const SequenceNumber32 &nextTxSequence)
Enable YeAH algorithm to start taking YeAH samples.
Definition: tcp-yeah.cc:170
uint32_t m_doingRenoNow
Number of RTTs in "Slow" mode.
Definition: tcp-yeah.h:182
uint32_t m_rho
Minimum number of consecutive RTT to consider competition with Reno flows on loss.
Definition: tcp-yeah.h:170
TcpYeah()
Create an unbound tcp socket.
Definition: tcp-yeah.cc:87
void DisableYeah()
Stop taking YeAH samples.
Definition: tcp-yeah.cc:181
uint32_t m_fastCount
Number of RTTs in "Fast" mode.
Definition: tcp-yeah.h:184
Time m_baseRtt
Minimum of all YeAH RTT measurements seen during connection.
Definition: tcp-yeah.h:176
uint32_t m_gamma
Fraction of queue to be removed per RTT when precautionary decongestion executed.
Definition: tcp-yeah.h:165
uint32_t m_delta
Log minimum fraction of cwnd to be removed on loss.
Definition: tcp-yeah.h:167
~TcpYeah() override
Definition: tcp-yeah.cc:137
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:408
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:297
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Every class exported by the ns3 library is enclosed in the ns3 namespace.