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 == Time (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 != Time (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)
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.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
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
Definition: tcp-header.cc:108
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:100
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.
#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
Definition: nstime.h:272
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.
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)
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: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:52
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.
#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: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: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.
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