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 
52 TypeId
54 {
55  static TypeId tid = TypeId("ns3::TcpWestwood")
57  .AddConstructor<TcpWestwood>()
58  .AddTraceSource("CongestionWindow", "The TCP connection's congestion window",
60  .AddAttribute("FilterType", "Use this to choose no filter or Tustin's approximation filter",
63  .AddAttribute("ProtocolType", "Use this to let the code run as Westwood or WestwoodPlus",
67  .AddTraceSource("EstimatedBW", "The estimated bandwidth",
69  return tid;
70 }
71 
73  m_inFastRec(false),
74  m_currentBW(0),
75  m_lastSampleBW(0),
76  m_lastBW(0),
77  m_minRtt(0),
78  m_lastAck(0),
79  m_prevAckNo(0),
80  m_accountedFor(0),
81  m_ackedSegments(0),
82  m_IsCount(false)
83 {
84  NS_LOG_FUNCTION (this);
85 }
86 
88  TcpSocketBase(sock),
89  m_cWnd(sock.m_cWnd),
90  m_ssThresh(sock.m_ssThresh),
91  m_initialCWnd(sock.m_initialCWnd),
92  m_inFastRec(false),
93  m_currentBW(sock.m_currentBW),
94  m_lastSampleBW(sock.m_lastSampleBW),
95  m_lastBW(sock.m_lastBW),
96  m_minRtt(sock.m_minRtt),
97  m_lastAck(sock.m_lastAck),
98  m_prevAckNo(sock.m_prevAckNo),
99  m_accountedFor(sock.m_accountedFor),
100  m_pType(sock.m_pType),
101  m_fType(sock.m_fType),
102  m_IsCount(sock.m_IsCount)
103 {
104  NS_LOG_FUNCTION (this);
105  NS_LOG_LOGIC ("Invoked the copy constructor");
106  NS_LOG_INFO ("m_minRtt at copy constructor" << m_minRtt);
107 }
108 
110 {
111 }
112 
113 int
115 {
116  NS_LOG_FUNCTION (this);
117  InitializeCwnd();
118  return TcpSocketBase::Listen();
119 }
120 
121 int
123 {
124  NS_LOG_FUNCTION (this << address);
125  InitializeCwnd();
126  return TcpSocketBase::Connect(address);
127 }
128 
129 uint32_t
131 {
132  NS_LOG_FUNCTION (this);
133  return std::min (m_rWnd.Get (), m_cWnd.Get ());
134 }
135 
138 {
139  NS_LOG_FUNCTION (this);
140  return CopyObject<TcpWestwood>(this);
141 }
142 
143 void
145 { // Same as Reno
146  NS_LOG_FUNCTION (this << seq);
147  NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
148  " cwnd " << m_cWnd <<
149  " ssthresh " << m_ssThresh);
150 
151  // Check for exit condition of fast recovery
152  if (m_inFastRec)
153  {// First new ACK after fast recovery, reset cwnd as in Reno
154  m_cWnd = m_ssThresh;
155  m_inFastRec = false;
156  NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
157  };
158 
159  // Increase of cwnd based on current phase (slow start or congestion avoidance)
160  if (m_cWnd < m_ssThresh)
161  { // Slow start mode, add one segSize to cWnd as in Reno
163  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
164  }
165  else
166  { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Reno
167  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
168  adder = std::max(1.0, adder);
169  m_cWnd += static_cast<uint32_t>(adder);
170  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
171  }
172 
173  // Complete newAck processing
175 }
176 
177 void
179 {
180  NS_LOG_FUNCTION (this);
181  int acked = 0;
182  if ((0 != (tcpHeader.GetFlags () & TcpHeader::ACK)) && tcpHeader.GetAckNumber() >= m_prevAckNo)
183  {// It is a duplicate ACK or a new ACK. Old ACK is ignored.
185  {// For Westwood, calculate the number of ACKed segments and estimate the BW
186  acked = CountAck (tcpHeader);
187  EstimateBW (acked, tcpHeader, Time(0));
188  }
190  {// For Weswood+, calculate the number of ACKed segments and update m_ackedSegments
191  if (m_IsCount)
192  {
193  acked = CountAck (tcpHeader);
194  UpdateAckedSegments (acked);
195  }
196  }
197  }
198 
199  TcpSocketBase::ReceivedAck (packet, tcpHeader);
200 }
201 
202 void
203 TcpWestwood::EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt)
204 {
205  NS_LOG_FUNCTION (this);
207  {
208  // Get the time when the current ACK is received
209  double currentAck = static_cast<double> (Simulator::Now().GetSeconds());
210  // Calculate the BW
211  m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
212  // Update the last ACK time
213  m_lastAck = currentAck;
214  }
216  {
217  // Calculate the BW
219  // Reset m_ackedSegments and m_IsCount for the next sampling
220  m_ackedSegments = 0;
221  m_IsCount = false;
222  }
223 
224  // Filter the BW sample
225  Filtering();
226 }
227 
228 int
230 {
231  NS_LOG_FUNCTION (this);
232 
233  // Calculate the number of acknowledged segments based on the received ACK number
234  int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
235 
236  if (cumul_ack == 0)
237  {// A DUPACK counts for 1 segment delivered successfully
238  m_accountedFor++;
239  cumul_ack = 1;
240  }
241  if (cumul_ack > 1)
242  {// A delayed ACK or a cumulative ACK after a retransmission
243  // Check how much new data it ACKs
244  if (m_accountedFor >= cumul_ack)
245  {
246  m_accountedFor -= cumul_ack;
247  cumul_ack = 1;
248  }
249  else if (m_accountedFor < cumul_ack)
250  {
251  cumul_ack -= m_accountedFor;
252  m_accountedFor = 0;
253  }
254  }
255 
256  // Update the previous ACK number
257  m_prevAckNo = tcpHeader.GetAckNumber();
258 
259  return cumul_ack;
260 }
261 
262 void
264 {
265  m_ackedSegments += acked;
266 }
267 
268 void
269 TcpWestwood::DupAck (const TcpHeader& header, uint32_t count)
270 {
271  NS_LOG_FUNCTION (this << count << m_cWnd);
272 
273  if (count == 3 && !m_inFastRec)
274  {// Triple duplicate ACK triggers fast retransmit
275  // Adjust cwnd and ssthresh based on the estimated BW
276  m_ssThresh = m_currentBW * static_cast<double> (m_minRtt.GetSeconds());
277  if (m_cWnd > m_ssThresh)
278  {
279  m_cWnd = m_ssThresh;
280  }
281  m_inFastRec = true;
282  NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh);
283  DoRetransmit ();
284  }
285  else if (m_inFastRec)
286  {// Increase cwnd for every additional DUPACK as in Reno
288  NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
290  }
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION (this);
297  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
298  m_inFastRec = false;
299 
300  // If erroneous timeout in closed/timed-wait state, just return
301  if (m_state == CLOSED || m_state == TIME_WAIT)
302  return;
303  // If all data are received, just return
305  return;
306 
307  // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
308  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
310 
311  // Restart from highest ACK
313  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
314  ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
315 
316  // Double the next RTO
317  m_rtt->IncreaseMultiplier();
318 
319  // Retransmit the packet
320  DoRetransmit();
321 }
322 
323 void
325 {
327 
328  // Calculate m_lastRtt
329  TcpSocketBase::EstimateRtt (tcpHeader);
330 
331  // Update minRtt
332  if (m_minRtt == 0)
333  {
335  }
336  else
337  {
338  if (m_lastRtt < m_minRtt)
339  {
341  }
342  }
343 
344  // For Westwood+, start running a clock on the currently estimated RTT if possible
345  // to trigger a new BW sampling event
347  {
348  if(m_lastRtt != 0 && m_state == ESTABLISHED && !m_IsCount)
349  {
350  m_IsCount = true;
353  }
354  }
355 }
356 
357 void
359 {
360  NS_LOG_FUNCTION (this);
361 
362  double alpha = 0.9;
363 
364  if (m_fType == TcpWestwood::NONE)
365  {
366  }
367  else if (m_fType == TcpWestwood::TUSTIN)
368  {
369  double sample_bwe = m_currentBW;
370  m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSampleBW) / 2));
371  m_lastSampleBW = sample_bwe;
373  }
374 }
375 
376 void
377 TcpWestwood::SetSegSize (uint32_t size)
378 {
379  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetSegSize() cannot change segment size after connection started.");
380  m_segmentSize = size;
381 }
382 
383 void
384 TcpWestwood::SetSSThresh (uint32_t threshold)
385 {
386  NS_LOG_FUNCTION (this);
387  m_ssThresh = threshold;
388 }
389 
390 uint32_t
392 {
393  NS_LOG_FUNCTION (this);
394  return m_ssThresh;
395 }
396 
397 void
399 {
400  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetInitialCwnd() cannot change initial cwnd after connection started.");
401  m_initialCWnd = cwnd;
402 }
403 
404 uint32_t
406 {
407  NS_LOG_FUNCTION (this);
408  return m_initialCWnd;
409 }
410 
411 void
413 {
414  NS_LOG_FUNCTION (this);
415  /*
416  * Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
417  * not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
418  * m_segmentSize are set by the attribute system in ns3::TcpSocket.
419  */
421 }
422 
423 } // namespace ns3
void InitializeCwnd(void)
Initialize cwnd at the beginning of a connection.
EventId m_bwEstimateEvent
The BW estimation event for Westwood+.
Definition: tcp-westwood.h:183
int CountAck(const TcpHeader &tcpHeader)
Calculate the number of acknowledged packets upon the receipt of an ACK packet.
virtual int Listen(void)
Listen for incoming connections.
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
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
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
uint8_t GetFlags() const
Definition: tcp-header.cc:109
TracedValue< Time > m_lastRtt
Last RTT sample collected.
SequenceNumber32 HeadSequence(void) const
Returns the first byte's sequence number.
SequenceNumber32 GetAckNumber() const
Definition: tcp-header.cc:101
double m_lastBW
Last bandwidth sample after being filtered.
Definition: tcp-westwood.h:173
int m_accountedFor
The number of received DUPACKs.
Definition: tcp-westwood.h:177
uint32_t m_ssThresh
Slow Start Threshold.
Definition: tcp-westwood.h:167
virtual void NewAck(SequenceNumber32 const &seq)
Update buffers w.r.t.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
virtual void DupAck(const TcpHeader &t, uint32_t count)
Received dupack (duplicate ACK)
#define NS_LOG_INFO(msg)
Definition: log.h:298
uint32_t m_segmentSize
Segment size.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Definition: log.h:309
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:824
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received an ACK packet.
T Get(void) const
Definition: traced-value.h:97
TracedValue< TcpStates_t > m_state
TCP state.
virtual uint32_t Window(void)
Return the max possible number of unacked bytes.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
virtual void Retransmit(void)
Halving cwnd and call DoRetransmit()
virtual int Listen(void)
Listen for incoming connections.
a polymophic address class
Definition: address.h:86
TcpTxBuffer m_txBuffer
Tx buffer.
double GetSeconds(void) const
Definition: nstime.h:274
TracedValue< uint32_t > m_cWnd
Congestion window.
Definition: tcp-westwood.h:166
enum FilterType m_fType
0 for none, 1 for Tustin
Definition: tcp-westwood.h:179
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
hold variables of type 'enum'
Definition: enum.h:37
void Filtering(void)
Tustin filter.
virtual uint32_t GetInitialCwnd(void) const
Get the initial Congestion Window.
NS_LOG_COMPONENT_DEFINE("TcpWestwood")
virtual void SetSSThresh(uint32_t threshold)
Set the Slow Start Threshold.
A base class for implementation of a stream socket using TCP.
Ptr< RttEstimator > m_rtt
Round trip time estimator.
bool m_inFastRec
Currently in fast recovery if TRUE.
Definition: tcp-westwood.h:169
#define NS_LOG_LOGIC(msg)
Definition: log.h:368
void UpdateAckedSegments(int acked)
Update the total number of acknowledged packets during the current RTT.
double m_lastAck
The time last ACK was received.
Definition: tcp-westwood.h:175
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Header for the Transmission Control Protocol.
Definition: tcp-header.h:43
SequenceNumber32 m_prevAckNo
Previously received ACK number.
Definition: tcp-westwood.h:176
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-westwood.cc:53
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
virtual void SetSegSize(uint32_t size)
Set the segment size.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:118
virtual ~TcpWestwood(void)
virtual void NewAck(SequenceNumber32 const &seq)
Update buffers w.r.t.
int m_ackedSegments
The number of segments ACKed between RTTs.
Definition: tcp-westwood.h:181
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Process the newly received ACK.
bool m_connected
Connection established.
virtual void SetInitialCwnd(uint32_t cwnd)
Set the initial Congestion Window.
virtual Ptr< TcpSocketBase > Fork(void)
Call CopyObject<> to clone me.
double m_lastSampleBW
Last bandwidth sample.
Definition: tcp-westwood.h:172
TracedValue< double > m_currentBW
Current value of the estimated BW.
Definition: tcp-westwood.h:171
bool m_IsCount
Start keeping track of m_ackedSegments for Westwood+ if TRUE.
Definition: tcp-westwood.h:182
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Definition: event-id.cc:47
void EstimateBW(int acked, const TcpHeader &tcpHeader, Time rtt)
Estimate the network's bandwidth.
virtual uint32_t GetSSThresh(void) const
Get the Slow Start Threshold.
uint32_t m_initialCWnd
Initial cWnd value.
Definition: tcp-westwood.h:168
Time m_minRtt
Minimum RTT.
Definition: tcp-westwood.h:174
tuple address
Definition: first.py:37
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
a unique identifier for an interface.
Definition: type-id.h:49
virtual void EstimateRtt(const TcpHeader &header)
Estimate the RTT, record the minimum value, and run a clock on the RTT to trigger Westwood+ bandwidth...
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611
bool SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
TracedValue< uint32_t > m_rWnd
Flow control window at remote side.
virtual void DoRetransmit(void)
Retransmit the oldest packet.
An implementation of a stream socket using TCP.
Definition: tcp-westwood.h:62
enum ProtocolType m_pType
0 for Westwood, 1 for Westwood+
Definition: tcp-westwood.h:178