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