Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(12)

Side by Side Diff: src/internet/model/tcp-westwood.cc

Issue 7227059: TCP Westwood and Westwood+ Implementation
Patch Set: Created 12 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/internet/model/tcp-westwood.h ('k') | src/internet/wscript » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2013 Siddharth Gangadhar, Truc Anh N. Nguyen, Greeshma Umapathi
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Siddharth Gangadhar <siddharth@ittc.ku.edu>, Truc Anh N. Nguyen <ann guyen@ittc.ku.edu>,
19 * and Greeshma Umapathi
20 *
21 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
22 * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
23 * Information and Telecommunication Technology Center (ITTC)
24 * and Department of Electrical Engineering and Computer Science
25 * The University of Kansas Lawrence, KS USA.
26 *
27 * Work supported in part by NSF FIND (Future Internet Design) Program
28 * under grant CNS-0626918 (Postmodern Internet Architecture),
29 * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimenta tion on GENI),
30 * US Department of Defense (DoD), and ITTC at The University of Kansas.
31 */
32
33 #define NS_LOG_APPEND_CONTEXT \
34 if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_n ode->GetId () << "] "; }
35
36 #include "tcp-westwood.h"
37 #include "ns3/log.h"
38 #include "ns3/trace-source-accessor.h"
39 #include "ns3/simulator.h"
40 #include "ns3/abort.h"
41 #include "ns3/node.h"
42 #include "ns3/sequence-number.h"
43 #include "rtt-estimator.h"
44
45 NS_LOG_COMPONENT_DEFINE("TcpWestwood");
46
47 namespace ns3 {
48
49 NS_OBJECT_ENSURE_REGISTERED(TcpWestwood);
50
51 TypeId
52 TcpWestwood::GetTypeId (void)
53 {
54 static TypeId tid = TypeId("ns3::TcpWestwood")
55 .SetParent<TcpSocketBase>()
56 .AddConstructor<TcpWestwood>()
57 .AddTraceSource("CongestionWindow", "The TCP connection's congestion windo w",
58 MakeTraceSourceAccessor(&TcpWestwood::m_cWnd))
59 .AddAttribute("FilterType", "Use this to choose no filter or Tustin's appr oximation filter",
60 EnumValue(TcpWestwood::TUSTIN), MakeEnumAccessor(&TcpWestwoo d::m_fType),
61 MakeEnumChecker(TcpWestwood::NONE, "None", TcpWestwood::TUST IN, "Tustin"))
62 .AddAttribute("ProtocolType", "Use this to let the code run as Westwood or WestwoodPlus",
63 EnumValue(TcpWestwood::WESTWOOD),
64 MakeEnumAccessor(&TcpWestwood::m_pType),
65 MakeEnumChecker(TcpWestwood::WESTWOOD, "Westwood",TcpWestwoo d::WESTWOODPLUS, "WestwoodPlus"))
66 .AddTraceSource("EstimatedBW", "The estimated bandwidth",
67 MakeTraceSourceAccessor(&TcpWestwood::m_currentBW));
68 return tid;
69 }
70
71 TcpWestwood::TcpWestwood (void) :
72 m_inFastRec(false),
73 m_currentBW(0),
74 m_lastSampleBW(0),
75 m_lastBW(0),
76 m_minRtt(0),
77 m_lastAck(0),
78 m_prevAckNo(0),
79 m_accountedFor(0),
80 m_ackedSegments(0),
81 m_IsCount(false)
82 {
83 NS_LOG_FUNCTION (this);
84 }
85
86 TcpWestwood::TcpWestwood (const TcpWestwood& sock) :
87 TcpSocketBase(sock),
88 m_cWnd(sock.m_cWnd),
89 m_ssThresh(sock.m_ssThresh),
90 m_initialCWnd(sock.m_initialCWnd),
91 m_inFastRec(false),
92 m_currentBW(sock.m_currentBW),
93 m_lastSampleBW(sock.m_lastSampleBW),
94 m_lastBW(sock.m_lastBW),
95 m_minRtt(sock.m_minRtt),
96 m_lastAck(sock.m_lastAck),
97 m_prevAckNo(sock.m_prevAckNo),
98 m_accountedFor(sock.m_accountedFor)
99 {
100 NS_LOG_FUNCTION (this);
101 NS_LOG_LOGIC ("Invoked the copy constructor");
102 NS_LOG_INFO ("m_minRtt at copy constructor" << m_minRtt);
103 }
104
105 TcpWestwood::~TcpWestwood (void)
106 {
107 }
108
109 int
110 TcpWestwood::Listen (void)
111 {
112 NS_LOG_FUNCTION (this);
113 InitializeCwnd();
114 return TcpSocketBase::Listen();
115 }
116
117 int
118 TcpWestwood::Connect (const Address & address)
119 {
120 NS_LOG_FUNCTION (this << address);
121 InitializeCwnd();
122 return TcpSocketBase::Connect(address);
123 }
124
125 uint32_t
126 TcpWestwood::Window (void)
127 {
128 NS_LOG_FUNCTION (this);
129 return std::min (m_rWnd.Get (), m_cWnd.Get ());
130 }
131
132 Ptr<TcpSocketBase>
133 TcpWestwood::Fork (void)
134 {
135 NS_LOG_FUNCTION (this);
136 return CopyObject<TcpWestwood>(this);
137 }
138
139 void
140 TcpWestwood::NewAck (const SequenceNumber32& seq)
141 { // Same as Reno
142 NS_LOG_FUNCTION (this << seq);
143 NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
144 " cwnd " << m_cWnd <<
145 " ssthresh " << m_ssThresh);
146
147 // Check for exit condition of fast recovery
148 if (m_inFastRec)
149 {// First new ACK after fast recovery, reset cwnd as in Reno
150 m_cWnd = m_ssThresh;
151 m_inFastRec = false;
152 NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
153 };
154
155 // Increase of cwnd based on current phase (slow start or congestion avoidance )
156 if (m_cWnd < m_ssThresh)
157 { // Slow start mode, add one segSize to cWnd as in Reno
158 m_cWnd += m_segmentSize;
159 NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
160 }
161 else
162 { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Ren o
163 double adder = static_cast<double>(m_segmentSize * m_segmentSize) / m_cWnd .Get();
164 adder = std::max(1.0, adder);
165 m_cWnd += static_cast<uint32_t>(adder);
166 NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
167 }
168
169 // Complete newAck processing
170 TcpSocketBase::NewAck(seq);
171 }
172
173 void
174 TcpWestwood::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
175 {
176 NS_LOG_FUNCTION (this);
177 int acked = 0;
178 if (0 != (tcpHeader.GetFlags () & TcpHeader::ACK))
179 {// It is an ACK
180 if (m_pType == TcpWestwood::WESTWOOD)
181 {// For Westwood, calculate the number of ACKed segments and estimate th e BW
182 acked = CountAck (tcpHeader);
183 EstimateBW (acked, tcpHeader, Time(0));
184 }
185 else if (m_pType == TcpWestwood::WESTWOODPLUS)
186 {// For Weswood+, calculate the number of ACKed segments and update m_ac kedSegments
187 if (m_IsCount)
188 {
189 acked = CountAck (tcpHeader);
190 UpdateAckedSegments (acked);
191 }
192 }
193 }
194
195 TcpSocketBase::ReceivedAck (packet, tcpHeader);
196 }
197
198 void
199 TcpWestwood::EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt)
200 {
201 NS_LOG_FUNCTION (this);
202 if (m_pType == TcpWestwood::WESTWOOD)
203 {
204 // Get the time when the current ACK is received
205 double currentAck = static_cast<double>(Simulator::Now().GetSeconds());
206 // Calculate the BW
207 m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
208 // Update the last ACK time
209 m_lastAck = currentAck;
210 }
211 else if (m_pType == TcpWestwood::WESTWOODPLUS)
212 {
213 // Calculate the BW
214 m_currentBW = m_ackedSegments * m_segmentSize / rtt.GetSeconds();
215 // Reset m_ackedSegments and m_IsCount for the next sampling
216 m_ackedSegments = 0;
217 m_IsCount = false;
218 }
219
220 // Filter the BW sample
221 Filtering();
222 }
223
224 int
bpswenson 2013/02/08 15:54:12 Does this correctly handle acks received out of or
225 TcpWestwood::CountAck (const TcpHeader& tcpHeader)
226 {
227 NS_LOG_FUNCTION (this);
228
229 // Calculate the number of acknowledged segments based on the received ACK num ber
230 int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
231
232 if (cumul_ack == 0)
233 {// A DUPACK counts for 1 segment delivered successfully
234 m_accountedFor++;
235 cumul_ack = 1;
236 }
237 if (cumul_ack > 1)
238 {// A delayed ACK or a cumulative ACK after a retransmission
239 // Check how much new data it ACKs
240 if (m_accountedFor >= cumul_ack)
241 {
242 m_accountedFor -= cumul_ack;
243 cumul_ack = 1;
244 }
245 else if (m_accountedFor < cumul_ack)
246 {
247 cumul_ack -= m_accountedFor;
248 m_accountedFor = 0;
249 }
250 }
251
252 // Update the previous ACK number
253 m_prevAckNo = tcpHeader.GetAckNumber();
254
255 return cumul_ack;
256 }
257
258 void
259 TcpWestwood::UpdateAckedSegments (int acked)
260 {
261 m_ackedSegments += acked;
262 }
263
264 void
265 TcpWestwood::DupAck (const TcpHeader& header, uint32_t count)
266 {
267 NS_LOG_FUNCTION (this << count << m_cWnd);
268
269 if (count == 3 && !m_inFastRec)
270 {// Triple duplicate ACK triggers fast retransmit
271 // Adjust cwnd and ssthresh based on the estimated BW
272 m_ssThresh = m_currentBW * static_cast<double>(m_minRtt.GetSeconds());
273 if (m_cWnd > m_ssThresh)
274 {
275 m_cWnd = m_ssThresh;
276 }
277 m_inFastRec = true;
278 NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh);
279 DoRetransmit ();
280 }
281 else if (m_inFastRec)
282 {// Increase cwnd for every additional DUPACK as in Reno
283 m_cWnd += m_segmentSize;
284 NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
285 SendPendingData (m_connected);
286 }
287 }
288
289 void
290 TcpWestwood::Retransmit (void)
291 {
292 NS_LOG_FUNCTION (this);
293 NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().Get Seconds ());
294 m_inFastRec = false;
295
296 // If erroneous timeout in closed/timed-wait state, just return
297 if (m_state == CLOSED || m_state == TIME_WAIT)
298 return;
299 // If all data are received, just return
300 if (m_txBuffer.HeadSequence() >= m_nextTxSequence)
301 return;
302
303 // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
304 m_ssThresh = std::max (static_cast<double>(2 * m_segmentSize), m_currentBW.Get () * static_cast<double>(m_minRtt.GetSeconds()));
bpswenson 2013/02/08 15:54:12 From looking at other code it looks like the stand
305 m_cWnd = m_segmentSize;
306
307 // Restart from highest ACK
308 m_nextTxSequence = m_txBuffer.HeadSequence();
309 NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
310 ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequ ence);
311
312 // Double the next RTO
313 m_rtt->IncreaseMultiplier();
314
315 // Retransmit the packet
316 DoRetransmit();
317 }
318
319 void
320 TcpWestwood::EstimateRtt (const TcpHeader& tcpHeader)
321 {
322 NS_LOG_FUNCTION_NOARGS ();
323
324 // Calculate m_lastRtt
325 TcpSocketBase::EstimateRtt (tcpHeader);
326
327 // Update minRtt
328 if (m_minRtt == 0)
329 {
330 m_minRtt = m_lastRtt;
331 }
332 else
333 {
334 if (m_lastRtt < m_minRtt)
335 {
336 m_minRtt = m_lastRtt;
337 }
338 }
339
340 // For Westwood+, start running a clock on the currently estimated RTT if poss ible
341 // to trigger a new BW sampling event
342 if (m_pType == TcpWestwood::WESTWOODPLUS)
343 {
344 if(m_lastRtt != 0 && m_state == ESTABLISHED && !m_IsCount)
345 {
346 m_IsCount = true;
347 m_bwEstimateEvent.Cancel();
348 m_bwEstimateEvent = Simulator::Schedule (m_lastRtt, &TcpWestwood::Estim ateBW,this,m_ackedSegments,tcpHeader,m_lastRtt);
349 }
350 }
351 }
352
353 void
354 TcpWestwood::Filtering ()
355 {
356 NS_LOG_FUNCTION (this);
357
358 double alpha = 0.9;
359
360 if (m_fType == TcpWestwood::NONE)
361 {
362 }
363 else if (m_fType == TcpWestwood::TUSTIN)
364 {
365 double sample_bwe = m_currentBW;
366 m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSam pleBW) / 2));
367 m_lastSampleBW = sample_bwe;
368 m_lastBW = m_currentBW;
369 }
370 }
371
372 void
373 TcpWestwood::SetSegSize (uint32_t size)
374 {
375 NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetSegSize() cannot chang e segment size after connection started.");
376 m_segmentSize = size;
377 }
378
379 void
380 TcpWestwood::SetSSThresh (uint32_t threshold)
381 {
382 NS_LOG_FUNCTION (this);
383 m_ssThresh = threshold;
384 }
385
386 uint32_t
387 TcpWestwood::GetSSThresh (void) const
388 {
389 NS_LOG_FUNCTION (this);
390 return m_ssThresh;
391 }
392
393 void
394 TcpWestwood::SetInitialCwnd (uint32_t cwnd)
395 {
396 NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetInitialCwnd() cannot c hange initial cwnd after connection started.");
397 m_initialCWnd = cwnd;
398 }
399
400 uint32_t
401 TcpWestwood::GetInitialCwnd (void) const
402 {
403 NS_LOG_FUNCTION (this);
404 return m_initialCWnd;
405 }
406
407 void
408 TcpWestwood::InitializeCwnd(void)
409 {
410 NS_LOG_FUNCTION (this);
411 /*
412 * Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
413 * not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
414 * m_segmentSize are set by the attribute system in ns3::TcpSocket.
415 */
416 m_cWnd = m_initialCWnd * m_segmentSize;
417 }
418
419 } // namespace ns3
OLDNEW
« no previous file with comments | « src/internet/model/tcp-westwood.h ('k') | src/internet/wscript » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b