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