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  .AddTraceSource ("SlowStartThreshold",
60  "TCP slow start threshold (bytes)",
62  .AddAttribute("FilterType", "Use this to choose no filter or Tustin's approximation filter",
65  .AddAttribute("ProtocolType", "Use this to let the code run as Westwood or WestwoodPlus",
69  .AddTraceSource("EstimatedBW", "The estimated bandwidth",
71  return tid;
72 }
73 
75  m_inFastRec(false),
76  m_currentBW(0),
77  m_lastSampleBW(0),
78  m_lastBW(0),
79  m_minRtt(0),
80  m_lastAck(0),
81  m_prevAckNo(0),
82  m_accountedFor(0),
83  m_ackedSegments(0),
84  m_IsCount(false)
85 {
86  NS_LOG_FUNCTION (this);
87 }
88 
90  TcpSocketBase(sock),
91  m_cWnd(sock.m_cWnd),
92  m_ssThresh(sock.m_ssThresh),
93  m_initialCWnd(sock.m_initialCWnd),
94  m_initialSsThresh (sock.m_initialSsThresh),
95  m_inFastRec(false),
96  m_currentBW(sock.m_currentBW),
97  m_lastSampleBW(sock.m_lastSampleBW),
98  m_lastBW(sock.m_lastBW),
99  m_minRtt(sock.m_minRtt),
100  m_lastAck(sock.m_lastAck),
101  m_prevAckNo(sock.m_prevAckNo),
102  m_accountedFor(sock.m_accountedFor),
103  m_pType(sock.m_pType),
104  m_fType(sock.m_fType),
105  m_IsCount(sock.m_IsCount)
106 {
107  NS_LOG_FUNCTION (this);
108  NS_LOG_LOGIC ("Invoked the copy constructor");
109  NS_LOG_INFO ("m_minRtt at copy constructor" << m_minRtt);
110 }
111 
113 {
114 }
115 
116 int
118 {
119  NS_LOG_FUNCTION (this);
120  InitializeCwnd();
121  return TcpSocketBase::Listen();
122 }
123 
124 int
126 {
127  NS_LOG_FUNCTION (this << address);
128  InitializeCwnd();
129  return TcpSocketBase::Connect(address);
130 }
131 
132 uint32_t
134 {
135  NS_LOG_FUNCTION (this);
136  return std::min (m_rWnd.Get (), m_cWnd.Get ());
137 }
138 
141 {
142  NS_LOG_FUNCTION (this);
143  return CopyObject<TcpWestwood>(this);
144 }
145 
146 void
148 { // Same as Reno
149  NS_LOG_FUNCTION (this << seq);
150  NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
151  " cwnd " << m_cWnd <<
152  " ssthresh " << m_ssThresh);
153 
154  // Check for exit condition of fast recovery
155  if (m_inFastRec)
156  {// First new ACK after fast recovery, reset cwnd as in Reno
157  m_cWnd = m_ssThresh;
158  m_inFastRec = false;
159  NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
160  };
161 
162  // Increase of cwnd based on current phase (slow start or congestion avoidance)
163  if (m_cWnd < m_ssThresh)
164  { // Slow start mode, add one segSize to cWnd as in Reno
166  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
167  }
168  else
169  { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Reno
170  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
171  adder = std::max(1.0, adder);
172  m_cWnd += static_cast<uint32_t>(adder);
173  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
174  }
175 
176  // Complete newAck processing
178 }
179 
180 void
182 {
183  NS_LOG_FUNCTION (this);
184  int acked = 0;
185  if ((0 != (tcpHeader.GetFlags () & TcpHeader::ACK)) && tcpHeader.GetAckNumber() >= m_prevAckNo)
186  {// It is a duplicate ACK or a new ACK. Old ACK is ignored.
188  {// For Westwood, calculate the number of ACKed segments and estimate the BW
189  acked = CountAck (tcpHeader);
190  EstimateBW (acked, tcpHeader, Time(0));
191  }
193  {// For Weswood+, calculate the number of ACKed segments and update m_ackedSegments
194  if (m_IsCount)
195  {
196  acked = CountAck (tcpHeader);
197  UpdateAckedSegments (acked);
198  }
199  }
200  }
201 
202  TcpSocketBase::ReceivedAck (packet, tcpHeader);
203 }
204 
205 void
206 TcpWestwood::EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt)
207 {
208  NS_LOG_FUNCTION (this);
210  {
211  // Get the time when the current ACK is received
212  double currentAck = static_cast<double> (Simulator::Now().GetSeconds());
213  // Calculate the BW
214  m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
215  // Update the last ACK time
216  m_lastAck = currentAck;
217  }
219  {
220  // Calculate the BW
222  // Reset m_ackedSegments and m_IsCount for the next sampling
223  m_ackedSegments = 0;
224  m_IsCount = false;
225  }
226 
227  // Filter the BW sample
228  Filtering();
229 }
230 
231 int
233 {
234  NS_LOG_FUNCTION (this);
235 
236  // Calculate the number of acknowledged segments based on the received ACK number
237  int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
238 
239  if (cumul_ack == 0)
240  {// A DUPACK counts for 1 segment delivered successfully
241  m_accountedFor++;
242  cumul_ack = 1;
243  }
244  if (cumul_ack > 1)
245  {// A delayed ACK or a cumulative ACK after a retransmission
246  // Check how much new data it ACKs
247  if (m_accountedFor >= cumul_ack)
248  {
249  m_accountedFor -= cumul_ack;
250  cumul_ack = 1;
251  }
252  else if (m_accountedFor < cumul_ack)
253  {
254  cumul_ack -= m_accountedFor;
255  m_accountedFor = 0;
256  }
257  }
258 
259  // Update the previous ACK number
260  m_prevAckNo = tcpHeader.GetAckNumber();
261 
262  return cumul_ack;
263 }
264 
265 void
267 {
268  m_ackedSegments += acked;
269 }
270 
271 void
272 TcpWestwood::DupAck (const TcpHeader& header, uint32_t count)
273 {
274  NS_LOG_FUNCTION (this << count << m_cWnd);
275 
276  if (count == 3 && !m_inFastRec)
277  {// Triple duplicate ACK triggers fast retransmit
278  // Adjust cwnd and ssthresh based on the estimated BW
279  m_ssThresh = uint32_t(m_currentBW * static_cast<double> (m_minRtt.GetSeconds()));
280  if (m_cWnd > m_ssThresh)
281  {
282  m_cWnd = m_ssThresh;
283  }
284  m_inFastRec = true;
285  NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh);
286  DoRetransmit ();
287  }
288  else if (m_inFastRec)
289  {// Increase cwnd for every additional DUPACK as in Reno
291  NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
293  }
294 }
295 
296 void
298 {
299  NS_LOG_FUNCTION (this);
300  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
301  m_inFastRec = false;
302 
303  // If erroneous timeout in closed/timed-wait state, just return
304  if (m_state == CLOSED || m_state == TIME_WAIT)
305  return;
306  // If all data are received, just return
308  return;
309 
310  // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
311  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
313 
314  // Restart from highest ACK
316  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
317  ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
318 
319  // Double the next RTO
320  m_rtt->IncreaseMultiplier();
321 
322  // Retransmit the packet
323  DoRetransmit();
324 }
325 
326 void
328 {
330 
331  // Calculate m_lastRtt
332  TcpSocketBase::EstimateRtt (tcpHeader);
333 
334  // Update minRtt
335  if (m_minRtt == Time (0))
336  {
338  }
339  else
340  {
341  if (m_lastRtt < m_minRtt)
342  {
344  }
345  }
346 
347  // For Westwood+, start running a clock on the currently estimated RTT if possible
348  // to trigger a new BW sampling event
350  {
351  if(m_lastRtt != Time (0) && m_state == ESTABLISHED && !m_IsCount)
352  {
353  m_IsCount = true;
356  }
357  }
358 }
359 
360 void
362 {
363  NS_LOG_FUNCTION (this);
364 
365  double alpha = 0.9;
366 
367  if (m_fType == TcpWestwood::NONE)
368  {
369  }
370  else if (m_fType == TcpWestwood::TUSTIN)
371  {
372  double sample_bwe = m_currentBW;
373  m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSampleBW) / 2));
374  m_lastSampleBW = sample_bwe;
376  }
377 }
378 
379 void
380 TcpWestwood::SetSegSize (uint32_t size)
381 {
382  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetSegSize() cannot change segment size after connection started.");
383  m_segmentSize = size;
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION (this);
390  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "TcpWestwood::SetSSThresh() cannot change initial ssThresh after connection started.");
391  m_initialSsThresh = threshold;
392 }
393 
394 uint32_t
396 {
397  NS_LOG_FUNCTION (this);
398  return m_initialSsThresh;
399 }
400 
401 void
403 {
404  NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetInitialCwnd() cannot change initial cwnd after connection started.");
405  m_initialCWnd = cwnd;
406 }
407 
408 uint32_t
410 {
411  NS_LOG_FUNCTION (this);
412  return m_initialCWnd;
413 }
414 
415 void
417 {
418  NS_LOG_FUNCTION (this);
419  /*
420  * Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
421  * not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
422  * m_segmentSize are set by the attribute system in ns3::TcpSocket.
423  */
426 }
427 
428 } // 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:184
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.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:95
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
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
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:133
TracedValue< Time > m_lastRtt
Last RTT sample collected.
SequenceNumber32 HeadSequence(void) const
Returns the first byte's sequence number.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:121
double m_lastBW
Last bandwidth sample after being filtered.
Definition: tcp-westwood.h:174
int m_accountedFor
The number of received DUPACKs.
Definition: tcp-westwood.h:178
virtual void NewAck(SequenceNumber32 const &seq)
Update buffers w.r.t.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual void DupAck(const TcpHeader &t, uint32_t count)
Received dupack (duplicate ACK)
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
uint32_t m_segmentSize
Segment size.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
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:825
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received an ACK packet.
T Get(void) const
Definition: traced-value.h:99
TracedValue< TcpStates_t > m_state
TCP state.
virtual uint32_t Window(void)
Return the max possible number of unacked bytes.
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
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:322
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:180
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.
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:170
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
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:176
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
SequenceNumber32 m_prevAckNo
Previously received ACK number.
Definition: tcp-westwood.h:177
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:52
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
TracedValue< uint32_t > m_ssThresh
Slow Start Threshold.
Definition: tcp-westwood.h:167
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:182
uint32_t m_initialSsThresh
Initial Slow Start Threshold value.
Definition: tcp-westwood.h:169
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Process the newly received ACK.
bool m_connected
Connection established.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:136
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:173
virtual uint32_t GetInitialSSThresh(void) const
Get the initial Slow Start Threshold.
TracedValue< double > m_currentBW
Current value of the estimated BW.
Definition: tcp-westwood.h:172
bool m_IsCount
Start keeping track of m_ackedSegments for Westwood+ if TRUE.
Definition: tcp-westwood.h:183
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.
uint32_t m_initialCWnd
Initial cWnd value.
Definition: tcp-westwood.h:168
Time m_minRtt
Minimum RTT.
Definition: tcp-westwood.h:175
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:610
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.
virtual void SetInitialSSThresh(uint32_t threshold)
Set the initial Slow Start Threshold.
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:179