A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tcp-westwood.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 ResiliNets, ITTC, University of Kansas
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 <annguyen@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 Experimentation 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_node->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
53 {
54  static TypeId tid = TypeId("ns3::TcpWestwood")
56  .AddConstructor<TcpWestwood>()
57  .AddTraceSource("CongestionWindow", "The TCP connection's congestion window",
59  .AddAttribute("FilterType", "Use this to choose no filter or Tustin's approximation filter",
62  .AddAttribute("ProtocolType", "Use this to let the code run as Westwood or WestwoodPlus",
66  .AddTraceSource("EstimatedBW", "The estimated bandwidth",
68  return tid;
69 }
70 
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 
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  m_pType(sock.m_pType),
100  m_fType(sock.m_fType),
101  m_IsCount(sock.m_IsCount)
102 {
103  NS_LOG_FUNCTION (this);
104  NS_LOG_LOGIC ("Invoked the copy constructor");
105  NS_LOG_INFO ("m_minRtt at copy constructor" << m_minRtt);
106 }
107 
109 {
110 }
111 
112 int
114 {
115  NS_LOG_FUNCTION (this);
116  InitializeCwnd();
117  return TcpSocketBase::Listen();
118 }
119 
120 int
122 {
123  NS_LOG_FUNCTION (this << address);
124  InitializeCwnd();
125  return TcpSocketBase::Connect(address);
126 }
127 
128 uint32_t
130 {
131  NS_LOG_FUNCTION (this);
132  return std::min (m_rWnd.Get (), m_cWnd.Get ());
133 }
134 
137 {
138  NS_LOG_FUNCTION (this);
139  return CopyObject<TcpWestwood>(this);
140 }
141 
142 void
144 { // Same as Reno
145  NS_LOG_FUNCTION (this << seq);
146  NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
147  " cwnd " << m_cWnd <<
148  " ssthresh " << m_ssThresh);
149 
150  // Check for exit condition of fast recovery
151  if (m_inFastRec)
152  {// First new ACK after fast recovery, reset cwnd as in Reno
153  m_cWnd = m_ssThresh;
154  m_inFastRec = false;
155  NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
156  };
157 
158  // Increase of cwnd based on current phase (slow start or congestion avoidance)
159  if (m_cWnd < m_ssThresh)
160  { // Slow start mode, add one segSize to cWnd as in Reno
162  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
163  }
164  else
165  { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Reno
166  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
167  adder = std::max(1.0, adder);
168  m_cWnd += static_cast<uint32_t>(adder);
169  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
170  }
171 
172  // Complete newAck processing
174 }
175 
176 void
178 {
179  NS_LOG_FUNCTION (this);
180  int acked = 0;
181  if ((0 != (tcpHeader.GetFlags () & TcpHeader::ACK)) && tcpHeader.GetAckNumber() >= m_prevAckNo)
182  {// It is a duplicate ACK or a new ACK. Old ACK is ignored.
184  {// For Westwood, calculate the number of ACKed segments and estimate the BW
185  acked = CountAck (tcpHeader);
186  EstimateBW (acked, tcpHeader, Time(0));
187  }
189  {// For Weswood+, calculate the number of ACKed segments and update m_ackedSegments
190  if (m_IsCount)
191  {
192  acked = CountAck (tcpHeader);
193  UpdateAckedSegments (acked);
194  }
195  }
196  }
197 
198  TcpSocketBase::ReceivedAck (packet, tcpHeader);
199 }
200 
201 void
202 TcpWestwood::EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt)
203 {
204  NS_LOG_FUNCTION (this);
206  {
207  // Get the time when the current ACK is received
208  double currentAck = static_cast<double> (Simulator::Now().GetSeconds());
209  // Calculate the BW
210  m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
211  // Update the last ACK time
212  m_lastAck = currentAck;
213  }
215  {
216  // Calculate the BW
218  // Reset m_ackedSegments and m_IsCount for the next sampling
219  m_ackedSegments = 0;
220  m_IsCount = false;
221  }
222 
223  // Filter the BW sample
224  Filtering();
225 }
226 
227 int
229 {
230  NS_LOG_FUNCTION (this);
231 
232  // Calculate the number of acknowledged segments based on the received ACK number
233  int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
234 
235  if (cumul_ack == 0)
236  {// A DUPACK counts for 1 segment delivered successfully
237  m_accountedFor++;
238  cumul_ack = 1;
239  }
240  if (cumul_ack > 1)
241  {// A delayed ACK or a cumulative ACK after a retransmission
242  // Check how much new data it ACKs
243  if (m_accountedFor >= cumul_ack)
244  {
245  m_accountedFor -= cumul_ack;
246  cumul_ack = 1;
247  }
248  else if (m_accountedFor < cumul_ack)
249  {
250  cumul_ack -= m_accountedFor;
251  m_accountedFor = 0;
252  }
253  }
254 
255  // Update the previous ACK number
256  m_prevAckNo = tcpHeader.GetAckNumber();
257 
258  return cumul_ack;
259 }
260 
261 void
263 {
264  m_ackedSegments += acked;
265 }
266 
267 void
268 TcpWestwood::DupAck (const TcpHeader& header, uint32_t count)
269 {
270  NS_LOG_FUNCTION (this << count << m_cWnd);
271 
272  if (count == 3 && !m_inFastRec)
273  {// Triple duplicate ACK triggers fast retransmit
274  // Adjust cwnd and ssthresh based on the estimated BW
275  m_ssThresh = m_currentBW * static_cast<double> (m_minRtt.GetSeconds());
276  if (m_cWnd > m_ssThresh)
277  {
278  m_cWnd = m_ssThresh;
279  }
280  m_inFastRec = true;
281  NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh);
282  DoRetransmit ();
283  }
284  else if (m_inFastRec)
285  {// Increase cwnd for every additional DUPACK as in Reno
287  NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
289  }
290 }
291 
292 void
294 {
295  NS_LOG_FUNCTION (this);
296  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
297  m_inFastRec = false;
298 
299  // If erroneous timeout in closed/timed-wait state, just return
300  if (m_state == CLOSED || m_state == TIME_WAIT)
301  return;
302  // If all data are received, just return
304  return;
305 
306  // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
307  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
309 
310  // Restart from highest ACK
312  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
313  ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
314 
315  // Double the next RTO
316  m_rtt->IncreaseMultiplier();
317 
318  // Retransmit the packet
319  DoRetransmit();
320 }
321 
322 void
324 {
326 
327  // Calculate m_lastRtt
328  TcpSocketBase::EstimateRtt (tcpHeader);
329 
330  // Update minRtt
331  if (m_minRtt == 0)
332  {
334  }
335  else
336  {
337  if (m_lastRtt < m_minRtt)
338  {
340  }
341  }
342 
343  // For Westwood+, start running a clock on the currently estimated RTT if possible
344  // to trigger a new BW sampling event
346  {
347  if(m_lastRtt != 0 && m_state == ESTABLISHED && !m_IsCount)
348  {
349  m_IsCount = true;
352  }
353  }
354 }
355 
356 void
358 {
359  NS_LOG_FUNCTION (this);
360 
361  double alpha = 0.9;
362 
363  if (m_fType == TcpWestwood::NONE)
364  {
365  }
366  else if (m_fType == TcpWestwood::TUSTIN)
367  {
368  double sample_bwe = m_currentBW;
369  m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSampleBW) / 2));
370  m_lastSampleBW = sample_bwe;
372  }
373 }
374 
375 void
376 TcpWestwood::SetSegSize (uint32_t size)
377 {
378  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetSegSize() cannot change segment size after connection started.");
379  m_segmentSize = size;
380 }
381 
382 void
383 TcpWestwood::SetSSThresh (uint32_t threshold)
384 {
385  NS_LOG_FUNCTION (this);
386  m_ssThresh = threshold;
387 }
388 
389 uint32_t
391 {
392  NS_LOG_FUNCTION (this);
393  return m_ssThresh;
394 }
395 
396 void
398 {
399  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetInitialCwnd() cannot change initial cwnd after connection started.");
400  m_initialCWnd = cwnd;
401 }
402 
403 uint32_t
405 {
406  NS_LOG_FUNCTION (this);
407  return m_initialCWnd;
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION (this);
414  /*
415  * Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
416  * not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
417  * m_segmentSize are set by the attribute system in ns3::TcpSocket.
418  */
420 }
421 
422 } // namespace ns3
void InitializeCwnd(void)
EventId m_bwEstimateEvent
Definition: tcp-westwood.h:216
int CountAck(const TcpHeader &tcpHeader)
virtual int Listen(void)
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
virtual void EstimateRtt(const TcpHeader &)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
Definition: enum.cc:178
virtual void ReceivedAck(Ptr< Packet >, const TcpHeader &)
uint8_t GetFlags() const
Definition: tcp-header.cc:108
TracedValue< Time > m_lastRtt
SequenceNumber32 HeadSequence(void) const
SequenceNumber32 GetAckNumber() const
Definition: tcp-header.cc:100
uint32_t m_ssThresh
Definition: tcp-westwood.h:200
virtual void NewAck(SequenceNumber32 const &seq)
#define NS_LOG_INFO(msg)
Definition: log.h:264
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
TracedValue< SequenceNumber32 > m_nextTxSequence
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:824
T Get(void) const
Definition: traced-value.h:97
TracedValue< TcpStates_t > m_state
virtual uint32_t Window(void)
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
virtual void Retransmit(void)
virtual int Listen(void)
a polymophic address class
Definition: address.h:86
TcpTxBuffer m_txBuffer
double GetSeconds(void) const
Definition: nstime.h:266
TracedValue< uint32_t > m_cWnd
Definition: tcp-westwood.h:199
enum FilterType m_fType
Definition: tcp-westwood.h:212
hold variables of type 'enum'
Definition: enum.h:37
void Filtering(void)
virtual uint32_t GetInitialCwnd(void) const
NS_LOG_COMPONENT_DEFINE("TcpWestwood")
virtual void SetSSThresh(uint32_t threshold)
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
virtual void DupAck(const TcpHeader &header, uint32_t count)
A base class for implementation of a stream socket using TCP.
Ptr< RttEstimator > m_rtt
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void UpdateAckedSegments(int acked)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Header for the Transmission Control Protocol.
Definition: tcp-header.h:43
SequenceNumber32 m_prevAckNo
Definition: tcp-westwood.h:209
virtual int Connect(const Address &address)
static TypeId GetTypeId(void)
Definition: tcp-westwood.cc:52
static Time Now(void)
Definition: simulator.cc:180
virtual void SetSegSize(uint32_t size)
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:118
virtual ~TcpWestwood(void)
virtual void NewAck(SequenceNumber32 const &seq)
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
virtual void SetInitialCwnd(uint32_t cwnd)
virtual Ptr< TcpSocketBase > Fork(void)
TracedValue< double > m_currentBW
Definition: tcp-westwood.h:204
void Cancel(void)
Definition: event-id.cc:47
void EstimateBW(int acked, const TcpHeader &tcpHeader, Time rtt)
virtual uint32_t GetSSThresh(void) const
uint32_t m_initialCWnd
Definition: tcp-westwood.h:201
tuple address
Definition: first.py:37
virtual int Connect(const Address &address)
a unique identifier for an interface.
Definition: type-id.h:49
virtual void EstimateRtt(const TcpHeader &header)
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
bool SendPendingData(bool withAck=false)
TracedValue< uint32_t > m_rWnd
virtual void DoRetransmit(void)
An implementation of a stream socket using TCP.
Definition: tcp-westwood.h:62
enum ProtocolType m_pType
Definition: tcp-westwood.h:211