A Discrete-Event Network Simulator
API
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 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE("TcpYeah");
35 
36 TypeId
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",
51  UintegerValue(1),
53  MakeUintegerChecker<uint32_t>())
54  .AddAttribute("Delta",
55  "Log minimum fraction of cwnd to be removed on loss",
56  UintegerValue(3),
58  MakeUintegerChecker<uint32_t>())
59  .AddAttribute("Epsilon",
60  "Log maximum fraction to be removed on early decongestion",
61  UintegerValue(1),
63  MakeUintegerChecker<uint32_t>())
64  .AddAttribute("Phy",
65  "Maximum delta from base",
66  UintegerValue(8),
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 
148 void
149 TcpYeah::PktsAcked(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked, const Time& rtt)
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 
169 void
170 TcpYeah::EnableYeah(const SequenceNumber32& nextTxSequence)
171 {
172  NS_LOG_FUNCTION(this << nextTxSequence);
173 
174  m_doingYeahNow = true;
175  m_begSndNxt = nextTxSequence;
176  m_cntRtt = 0;
177  m_minRtt = Time::Max();
178 }
179 
180 void
182 {
183  NS_LOG_FUNCTION(this);
184 
185  m_doingYeahNow = false;
186 }
187 
188 void
190 {
191  NS_LOG_FUNCTION(this << tcb << newState);
192 
193  if (newState == TcpSocketState::CA_OPEN)
194  {
196  }
197  else
198  {
199  DisableYeah();
200  }
201 }
202 
203 void
204 TcpYeah::IncreaseWindow(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
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
307 
308  // Reset cntRtt & minRtt
309  m_cntRtt = 0;
310  m_minRtt = Time::Max();
311  }
312 }
313 
314 std::string
316 {
317  return "TcpYeah";
318 }
319 
320 uint32_t
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 min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:541
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.
uint32_t m_segmentSize
Segment size.
uint32_t GetCwndInSegments() const
Get cwnd in segments rather than bytes.
TcpCongState_t
Definition of the Congestion state machine.
@ CA_OPEN
Normal state, no dubious events.
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
TracedValue< uint32_t > m_cWnd
Congestion window.
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
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:931
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
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:243
#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.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46