A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-vegas.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-vegas.h"
27
28#include "tcp-socket-state.h"
29
30#include "ns3/log.h"
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("TcpVegas");
37
38TypeId
40{
41 static TypeId tid = TypeId("ns3::TcpVegas")
43 .AddConstructor<TcpVegas>()
44 .SetGroupName("Internet")
45 .AddAttribute("Alpha",
46 "Lower bound of packets in network",
49 MakeUintegerChecker<uint32_t>())
50 .AddAttribute("Beta",
51 "Upper bound of packets in network",
54 MakeUintegerChecker<uint32_t>())
55 .AddAttribute("Gamma",
56 "Limit on increase",
59 MakeUintegerChecker<uint32_t>());
60 return tid;
61}
62
64 : TcpNewReno(),
65 m_alpha(2),
66 m_beta(4),
67 m_gamma(1),
68 m_baseRtt(Time::Max()),
69 m_minRtt(Time::Max()),
70 m_cntRtt(0),
71 m_doingVegasNow(true),
72 m_begSndNxt(0)
73{
74 NS_LOG_FUNCTION(this);
75}
76
78 : TcpNewReno(sock),
79 m_alpha(sock.m_alpha),
80 m_beta(sock.m_beta),
81 m_gamma(sock.m_gamma),
82 m_baseRtt(sock.m_baseRtt),
83 m_minRtt(sock.m_minRtt),
84 m_cntRtt(sock.m_cntRtt),
85 m_doingVegasNow(true),
86 m_begSndNxt(0)
87{
88 NS_LOG_FUNCTION(this);
89}
90
92{
93 NS_LOG_FUNCTION(this);
94}
95
98{
99 return CopyObject<TcpVegas>(this);
100}
101
102void
104{
105 NS_LOG_FUNCTION(this << tcb << segmentsAcked << rtt);
106
107 if (rtt.IsZero())
108 {
109 return;
110 }
111
112 m_minRtt = std::min(m_minRtt, rtt);
113 NS_LOG_DEBUG("Updated m_minRtt = " << m_minRtt);
114
115 m_baseRtt = std::min(m_baseRtt, rtt);
116 NS_LOG_DEBUG("Updated m_baseRtt = " << m_baseRtt);
117
118 // Update RTT counter
119 m_cntRtt++;
120 NS_LOG_DEBUG("Updated m_cntRtt = " << m_cntRtt);
121}
122
123void
125{
126 NS_LOG_FUNCTION(this << tcb);
127
128 m_doingVegasNow = true;
129 m_begSndNxt = tcb->m_nextTxSequence;
130 m_cntRtt = 0;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this);
138
139 m_doingVegasNow = false;
140}
141
142void
144{
145 NS_LOG_FUNCTION(this << tcb << newState);
146 if (newState == TcpSocketState::CA_OPEN)
147 {
148 EnableVegas(tcb);
149 }
150 else
151 {
152 DisableVegas();
153 }
154}
155
156void
158{
159 NS_LOG_FUNCTION(this << tcb << segmentsAcked);
160
161 if (!m_doingVegasNow)
162 {
163 // If Vegas is not on, we follow NewReno algorithm
164 NS_LOG_LOGIC("Vegas is not turned on, we follow NewReno algorithm.");
165 TcpNewReno::IncreaseWindow(tcb, segmentsAcked);
166 return;
167 }
168
169 if (tcb->m_lastAckedSeq >= m_begSndNxt)
170 { // A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.
171
172 NS_LOG_LOGIC("A Vegas cycle has finished, we adjust cwnd once per RTT.");
173
174 // Save the current right edge for next Vegas cycle
175 m_begSndNxt = tcb->m_nextTxSequence;
176
177 /*
178 * We perform Vegas calculations only if we got enough RTT samples to
179 * insure that at least 1 of those samples wasn't from a delayed ACK.
180 */
181 if (m_cntRtt <= 2)
182 { // We do not have enough RTT samples, so we should behave like Reno
184 "We do not have enough RTT samples to do Vegas, so we behave like NewReno.");
185 TcpNewReno::IncreaseWindow(tcb, segmentsAcked);
186 }
187 else
188 {
189 NS_LOG_LOGIC("We have enough RTT samples to perform Vegas calculations");
190 /*
191 * We have enough RTT samples to perform Vegas algorithm.
192 * Now we need to determine if cwnd should be increased or decreased
193 * based on the calculated difference between the expected rate and actual sending
194 * rate and the predefined thresholds (alpha, beta, and gamma).
195 */
196 uint32_t diff;
197 uint32_t targetCwnd;
198 uint32_t segCwnd = tcb->GetCwndInSegments();
199
200 /*
201 * Calculate the cwnd we should have. baseRtt is the minimum RTT
202 * per-connection, minRtt is the minimum RTT in this window
203 *
204 * little trick:
205 * desidered throughput is currentCwnd * baseRtt
206 * target cwnd is throughput / minRtt
207 */
208 double tmp = m_baseRtt.GetSeconds() / m_minRtt.GetSeconds();
209 targetCwnd = static_cast<uint32_t>(segCwnd * tmp);
210 NS_LOG_DEBUG("Calculated targetCwnd = " << targetCwnd);
211 NS_ASSERT(segCwnd >= targetCwnd); // implies baseRtt <= minRtt
212
213 /*
214 * Calculate the difference between the expected cWnd and
215 * the actual cWnd
216 */
217 diff = segCwnd - targetCwnd;
218 NS_LOG_DEBUG("Calculated diff = " << diff);
219
220 if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh))
221 {
222 /*
223 * We are going too fast. We need to slow down and change from
224 * slow-start to linear increase/decrease mode by setting cwnd
225 * to target cwnd. We add 1 because of the integer truncation.
226 */
227 NS_LOG_LOGIC("We are going too fast. We need to slow down and "
228 "change to linear increase/decrease mode.");
229 segCwnd = std::min(segCwnd, targetCwnd + 1);
230 tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
231 tcb->m_ssThresh = GetSsThresh(tcb, 0);
232 NS_LOG_DEBUG("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);
233 }
234 else if (tcb->m_cWnd < tcb->m_ssThresh)
235 { // Slow start mode
236 NS_LOG_LOGIC("We are in slow start and diff < m_gamma, so we "
237 "follow NewReno slow start");
238 TcpNewReno::SlowStart(tcb, segmentsAcked);
239 }
240 else
241 { // Linear increase/decrease mode
242 NS_LOG_LOGIC("We are in linear increase/decrease mode");
243 if (diff > m_beta)
244 {
245 // We are going too fast, so we slow down
246 NS_LOG_LOGIC("We are going too fast, so we slow down by decrementing cwnd");
247 segCwnd--;
248 tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
249 tcb->m_ssThresh = GetSsThresh(tcb, 0);
250 NS_LOG_DEBUG("Updated cwnd = " << tcb->m_cWnd
251 << " ssthresh=" << tcb->m_ssThresh);
252 }
253 else if (diff < m_alpha)
254 {
255 // We are going too slow (having too little data in the network),
256 // so we speed up.
257 NS_LOG_LOGIC("We are going too slow, so we speed up by incrementing cwnd");
258 segCwnd++;
259 tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
260 NS_LOG_DEBUG("Updated cwnd = " << tcb->m_cWnd
261 << " ssthresh=" << tcb->m_ssThresh);
262 }
263 else
264 {
265 // We are going at the right speed
266 NS_LOG_LOGIC("We are sending at the right speed");
267 }
268 }
269 tcb->m_ssThresh = std::max(tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);
270 NS_LOG_DEBUG("Updated ssThresh = " << tcb->m_ssThresh);
271 }
272
273 // Reset cntRtt & minRtt every RTT
274 m_cntRtt = 0;
276 }
277 else if (tcb->m_cWnd < tcb->m_ssThresh)
278 {
279 TcpNewReno::SlowStart(tcb, segmentsAcked);
280 }
281}
282
283std::string
285{
286 return "TcpVegas";
287}
288
291{
292 NS_LOG_FUNCTION(this << tcb << bytesInFlight);
293 return std::max(std::min(tcb->m_ssThresh.Get(), tcb->m_cWnd.Get() - tcb->m_segmentSize),
294 2 * tcb->m_segmentSize);
295}
296
297} // namespace ns3
#define Max(a, b)
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.
void IncreaseWindow(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked) override
Try to increase the cWnd following the NewReno specification.
TcpCongState_t
Definition of the Congestion state machine.
@ CA_OPEN
Normal state, no dubious events.
An implementation of TCP Vegas.
Definition: tcp-vegas.h:66
uint32_t GetSsThresh(Ptr< const TcpSocketState > tcb, uint32_t bytesInFlight) override
Get slow start threshold following Vegas principle.
Definition: tcp-vegas.cc:290
void DisableVegas()
Stop taking Vegas samples.
Definition: tcp-vegas.cc:135
~TcpVegas() override
Definition: tcp-vegas.cc:91
uint32_t m_cntRtt
Number of RTT measurements during last RTT.
Definition: tcp-vegas.h:162
std::string GetName() const override
Get the name of the congestion control algorithm.
Definition: tcp-vegas.cc:284
Ptr< TcpCongestionOps > Fork() override
Copy the congestion control algorithm across sockets.
Definition: tcp-vegas.cc:97
uint32_t m_alpha
Alpha threshold, lower bound of packets in network.
Definition: tcp-vegas.h:157
uint32_t m_beta
Beta threshold, upper bound of packets in network.
Definition: tcp-vegas.h:158
void IncreaseWindow(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked) override
Adjust cwnd following Vegas linear increase/decrease algorithm.
Definition: tcp-vegas.cc:157
bool m_doingVegasNow
If true, do Vegas for this RTT.
Definition: tcp-vegas.h:163
void EnableVegas(Ptr< TcpSocketState > tcb)
Enable Vegas algorithm to start taking Vegas samples.
Definition: tcp-vegas.cc:124
Time m_minRtt
Minimum of all RTT measurements within last RTT.
Definition: tcp-vegas.h:161
void PktsAcked(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked, const Time &rtt) override
Compute RTTs needed to execute Vegas algorithm.
Definition: tcp-vegas.cc:103
void CongestionStateSet(Ptr< TcpSocketState > tcb, const TcpSocketState::TcpCongState_t newState) override
Enable/disable Vegas algorithm depending on the congestion state.
Definition: tcp-vegas.cc:143
TcpVegas()
Create an unbound tcp socket.
Definition: tcp-vegas.cc:63
Time m_baseRtt
Minimum of all Vegas RTT measurements seen during connection.
Definition: tcp-vegas.h:160
uint32_t m_gamma
Gamma threshold, limit on increase.
Definition: tcp-vegas.h:159
static TypeId GetTypeId()
Get the type ID.
Definition: tcp-vegas.cc:39
SequenceNumber32 m_begSndNxt
Right edge during last RTT.
Definition: tcp-vegas.h:164
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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_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.