A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
23namespace ns3
24{
25
28
29TypeId
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.",
64 MakeUintegerChecker<uint32_t>(1))
65 .AddAttribute("BinarySearchCoefficient",
66 "Inverse of the coefficient for the "
67 "binary search. Default 4, as in Linux",
70 MakeUintegerChecker<uint8_t>(2));
71 return tid;
72}
73
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
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
100void
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
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
236std::string
238{
239 return "TcpBic";
240}
241
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 Min(a, b)
AttributeValue implementation for Boolean.
Definition: boolean.h:37
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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.
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:932
Hold an unsigned integer type.
Definition: uinteger.h:45
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
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_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.