A Discrete-Event Network Simulator
API
tcp-bic.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
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  */
18 #include "tcp-bic.h"
19 
20 #include "ns3/log.h"
21 #include "ns3/simulator.h"
22 
23 namespace ns3
24 {
25 
26 NS_LOG_COMPONENT_DEFINE("TcpBic");
28 
29 TypeId
31 {
32  static TypeId tid =
33  TypeId("ns3::TcpBic")
35  .AddConstructor<TcpBic>()
36  .SetGroupName("Internet")
37  .AddAttribute("FastConvergence",
38  "Turn on/off fast convergence.",
39  BooleanValue(true),
42  .AddAttribute("Beta",
43  "Beta for multiplicative decrease",
44  DoubleValue(0.8),
46  MakeDoubleChecker<double>(0.0))
47  .AddAttribute("MaxIncr",
48  "Limit on increment allowed during binary search",
49  UintegerValue(16),
51  MakeUintegerChecker<uint32_t>(1))
52  .AddAttribute("LowWnd",
53  "Threshold window size (in segments) for engaging BIC response",
54  UintegerValue(14),
56  MakeUintegerChecker<uint32_t>())
57  .AddAttribute("SmoothPart",
58  "Number of RTT needed to approach cWnd_max from "
59  "cWnd_max-BinarySearchCoefficient. It can be viewed as the gradient "
60  "of the slow start AIM phase: less this value is, "
61  "more steep the increment will be.",
62  UintegerValue(5),
64  MakeUintegerChecker<uint32_t>(1))
65  .AddAttribute("BinarySearchCoefficient",
66  "Inverse of the coefficient for the "
67  "binary search. Default 4, as in Linux",
68  UintegerValue(4),
70  MakeUintegerChecker<uint8_t>(2));
71  return tid;
72 }
73 
75  : TcpCongestionOps(),
76  m_cWndCnt(0),
77  m_lastMaxCwnd(0),
78  m_lastCwnd(0),
79  m_epochStart(Time::Min())
80 {
81  NS_LOG_FUNCTION(this);
82 }
83 
84 TcpBic::TcpBic(const TcpBic& sock)
85  : TcpCongestionOps(sock),
86  m_fastConvergence(sock.m_fastConvergence),
87  m_beta(sock.m_beta),
88  m_maxIncr(sock.m_maxIncr),
89  m_lowWnd(sock.m_lowWnd),
90  m_smoothPart(sock.m_smoothPart),
91  m_cWndCnt(sock.m_cWndCnt),
92  m_lastMaxCwnd(sock.m_lastMaxCwnd),
93  m_lastCwnd(sock.m_lastCwnd),
94  m_epochStart(sock.m_epochStart),
95  m_b(sock.m_b)
96 {
97  NS_LOG_FUNCTION(this);
98 }
99 
100 void
101 TcpBic::IncreaseWindow(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
102 {
103  NS_LOG_FUNCTION(this << tcb << segmentsAcked);
104 
105  if (tcb->m_cWnd < tcb->m_ssThresh)
106  {
107  tcb->m_cWnd += tcb->m_segmentSize;
108  segmentsAcked -= 1;
109 
110  NS_LOG_INFO("In SlowStart, updated to cwnd " << tcb->m_cWnd << " ssthresh "
111  << tcb->m_ssThresh);
112  }
113 
114  if (tcb->m_cWnd >= tcb->m_ssThresh && segmentsAcked > 0)
115  {
116  m_cWndCnt += segmentsAcked;
117  uint32_t cnt = Update(tcb);
118 
119  /* According to the BIC paper and RFC 6356 even once the new cwnd is
120  * calculated you must compare this to the number of ACKs received since
121  * the last cwnd update. If not enough ACKs have been received then cwnd
122  * cannot be updated.
123  */
124  if (m_cWndCnt > cnt)
125  {
126  tcb->m_cWnd += tcb->m_segmentSize;
127  m_cWndCnt = 0;
128  NS_LOG_INFO("In CongAvoid, updated to cwnd " << tcb->m_cWnd);
129  }
130  else
131  {
132  NS_LOG_INFO("Not enough segments have been ACKed to increment cwnd."
133  "Until now "
134  << m_cWndCnt);
135  }
136  }
137 }
138 
139 uint32_t
141 {
142  NS_LOG_FUNCTION(this << tcb);
143 
144  uint32_t segCwnd = tcb->GetCwndInSegments();
145  uint32_t cnt;
146 
147  m_lastCwnd = segCwnd;
148 
149  if (m_epochStart == Time::Min())
150  {
151  m_epochStart = Simulator::Now(); /* record the beginning of an epoch */
152  }
153 
154  if (segCwnd < m_lowWnd)
155  {
156  NS_LOG_INFO("Under lowWnd, compatibility mode. Behaving as NewReno");
157  cnt = segCwnd;
158  return cnt;
159  }
160 
161  if (segCwnd < m_lastMaxCwnd)
162  {
163  double dist = (m_lastMaxCwnd - segCwnd) / m_b;
164 
165  NS_LOG_INFO("cWnd = " << segCwnd << " under lastMax, " << m_lastMaxCwnd
166  << " and dist=" << dist);
167  if (dist > m_maxIncr)
168  {
169  /* Linear increase */
170  cnt = segCwnd / m_maxIncr;
171  NS_LOG_INFO("Linear increase (maxIncr=" << m_maxIncr << "), cnt=" << cnt);
172  }
173  else if (dist <= 1)
174  {
175  /* smoothed binary search increase: when our window is really
176  * close to the last maximum, we parameterize in m_smoothPart the number
177  * of RTT needed to reach that window.
178  */
179  cnt = (segCwnd * m_smoothPart) / m_b;
180 
181  NS_LOG_INFO("Binary search increase (smoothPart=" << m_smoothPart << "), cnt=" << cnt);
182  }
183  else
184  {
185  /* binary search increase */
186  cnt = static_cast<uint32_t>(segCwnd / dist);
187 
188  NS_LOG_INFO("Binary search increase, cnt=" << cnt);
189  }
190  }
191  else
192  {
193  NS_LOG_INFO("cWnd = " << segCwnd << " above last max, " << m_lastMaxCwnd);
194  if (segCwnd < m_lastMaxCwnd + m_b)
195  {
196  /* slow start AMD linear increase */
197  cnt = (segCwnd * m_smoothPart) / m_b;
198  NS_LOG_INFO("Slow start AMD, cnt=" << cnt);
199  }
200  else if (segCwnd < m_lastMaxCwnd + m_maxIncr * (m_b - 1))
201  {
202  /* slow start */
203  cnt = (segCwnd * (m_b - 1)) / (segCwnd - m_lastMaxCwnd);
204 
205  NS_LOG_INFO("Slow start, cnt=" << cnt);
206  }
207  else
208  {
209  /* linear increase */
210  cnt = segCwnd / m_maxIncr;
211 
212  NS_LOG_INFO("Linear, cnt=" << cnt);
213  }
214  }
215 
216  /* if in slow start or link utilization is very low. Code taken from Linux
217  * kernel, not sure of the source they take it. Usually, it is not reached,
218  * since if m_lastMaxCwnd is 0, we are (hopefully) in slow start.
219  */
220  if (m_lastMaxCwnd == 0)
221  {
222  if (cnt > 20) /* increase cwnd 5% per RTT */
223  {
224  cnt = 20;
225  }
226  }
227 
228  if (cnt == 0)
229  {
230  cnt = 1;
231  }
232 
233  return cnt;
234 }
235 
236 std::string
238 {
239  return "TcpBic";
240 }
241 
242 uint32_t
243 TcpBic::GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight)
244 {
245  NS_LOG_FUNCTION(this);
246 
247  uint32_t segCwnd = tcb->GetCwndInSegments();
248  uint32_t ssThresh = 0;
249 
251 
252  /* Wmax and fast convergence */
253  if (segCwnd < m_lastMaxCwnd && m_fastConvergence)
254  {
255  NS_LOG_INFO("Fast Convergence. Last max cwnd: " << m_lastMaxCwnd << " updated to "
256  << static_cast<uint32_t>(m_beta * segCwnd));
257  m_lastMaxCwnd = static_cast<uint32_t>(m_beta * segCwnd);
258  }
259  else
260  {
261  NS_LOG_INFO("Last max cwnd: " << m_lastMaxCwnd << " updated to " << segCwnd);
262  m_lastMaxCwnd = segCwnd;
263  }
264 
265  if (segCwnd < m_lowWnd)
266  {
267  ssThresh = std::max(2 * tcb->m_segmentSize, bytesInFlight / 2);
268  NS_LOG_INFO("Less than lowWindow, ssTh= " << ssThresh);
269  }
270  else
271  {
272  ssThresh = static_cast<uint32_t>(std::max(segCwnd * m_beta, 2.0) * tcb->m_segmentSize);
273  NS_LOG_INFO("More than lowWindow, ssTh= " << ssThresh);
274  }
275 
276  return ssThresh;
277 }
278 
281 {
282  return CopyObject<TcpBic>(this);
283 }
284 
285 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:42
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
BIC congestion control algorithm.
Definition: tcp-bic.h:82
bool m_fastConvergence
Enable or disable fast convergence algorithm.
Definition: tcp-bic.h:128
uint32_t m_lastMaxCwnd
Last maximum cWnd.
Definition: tcp-bic.h:136
uint32_t m_lowWnd
Lower bound on congestion window.
Definition: tcp-bic.h:131
static TypeId GetTypeId()
Get the type ID.
Definition: tcp-bic.cc:30
uint32_t GetSsThresh(Ptr< const TcpSocketState > tcb, uint32_t bytesInFlight) override
Get the slow start threshold after a loss event.
Definition: tcp-bic.cc:243
uint8_t m_b
Binary search coefficient.
Definition: tcp-bic.h:139
uint32_t m_lastCwnd
Last cWnd.
Definition: tcp-bic.h:137
uint32_t m_maxIncr
Maximum window increment.
Definition: tcp-bic.h:130
double m_beta
Beta for cubic multiplicative increase.
Definition: tcp-bic.h:129
virtual uint32_t Update(Ptr< TcpSocketState > tcb)
Bic window update after a new ack received.
Definition: tcp-bic.cc:140
TcpBic()
Constructor.
Definition: tcp-bic.cc:74
uint32_t m_smoothPart
Number of RTT needed to reach Wmax from Wmax-B.
Definition: tcp-bic.h:132
void IncreaseWindow(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked) override
Congestion avoidance algorithm implementation.
Definition: tcp-bic.cc:101
Time m_epochStart
Beginning of an epoch.
Definition: tcp-bic.h:138
uint32_t m_cWndCnt
cWnd integer-to-float counter
Definition: tcp-bic.h:135
Ptr< TcpCongestionOps > Fork() override
Copy the congestion control algorithm across sockets.
Definition: tcp-bic.cc:280
std::string GetName() const override
Get the name of the congestion control algorithm.
Definition: tcp-bic.cc:237
Congestion control abstract class.
uint32_t m_segmentSize
Segment size.
uint32_t GetCwndInSegments() const
Get cwnd in segments rather than bytes.
TracedValue< uint32_t > m_cWnd
Congestion window.
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:287
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
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:229
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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 AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46