A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tcp-reno.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 Adrian Sai-wah Tam
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  * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
19  */
20 
21 #define NS_LOG_APPEND_CONTEXT \
22  if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
23 
24 #include "tcp-reno.h"
25 #include "ns3/log.h"
26 #include "ns3/trace-source-accessor.h"
27 #include "ns3/simulator.h"
28 #include "ns3/abort.h"
29 #include "ns3/node.h"
30 
31 NS_LOG_COMPONENT_DEFINE ("TcpReno");
32 
33 namespace ns3 {
34 
35 NS_OBJECT_ENSURE_REGISTERED (TcpReno);
36 
37 TypeId
38 TcpReno::GetTypeId (void)
39 {
40  static TypeId tid = TypeId ("ns3::TcpReno")
41  .SetParent<TcpSocketBase> ()
42  .AddConstructor<TcpReno> ()
43  .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
44  UintegerValue (3),
45  MakeUintegerAccessor (&TcpReno::m_retxThresh),
46  MakeUintegerChecker<uint32_t> ())
47  .AddTraceSource ("CongestionWindow",
48  "The TCP connection's congestion window",
49  MakeTraceSourceAccessor (&TcpReno::m_cWnd))
50  ;
51  return tid;
52 }
53 
54 TcpReno::TcpReno (void) : m_retxThresh (3), m_inFastRec (false)
55 {
56  NS_LOG_FUNCTION (this);
57 }
58 
59 TcpReno::TcpReno (const TcpReno& sock)
60  : TcpSocketBase (sock),
61  m_cWnd (sock.m_cWnd),
62  m_ssThresh (sock.m_ssThresh),
63  m_initialCWnd (sock.m_initialCWnd),
64  m_retxThresh (sock.m_retxThresh),
65  m_inFastRec (false)
66 {
67  NS_LOG_FUNCTION (this);
68  NS_LOG_LOGIC ("Invoked the copy constructor");
69 }
70 
71 TcpReno::~TcpReno (void)
72 {
73 }
74 
76 int
78 {
79  NS_LOG_FUNCTION (this);
80  InitializeCwnd ();
81  return TcpSocketBase::Listen ();
82 }
83 
85 int
86 TcpReno::Connect (const Address & address)
87 {
88  NS_LOG_FUNCTION (this << address);
89  InitializeCwnd ();
90  return TcpSocketBase::Connect (address);
91 }
92 
94 uint32_t
96 {
97  NS_LOG_FUNCTION (this);
98  return std::min (m_rWnd.Get (), m_cWnd.Get ());
99 }
100 
102 TcpReno::Fork (void)
103 {
104  return CopyObject<TcpReno> (this);
105 }
106 
108 void
110 {
111  NS_LOG_FUNCTION (this << seq);
112  NS_LOG_LOGIC ("TcpReno receieved ACK for seq " << seq <<
113  " cwnd " << m_cWnd <<
114  " ssthresh " << m_ssThresh);
115 
116  // Check for exit condition of fast recovery
117  if (m_inFastRec)
118  { // RFC2001, sec.4; RFC2581, sec.3.2
119  // First new ACK after fast recovery: reset cwnd
120  m_cWnd = m_ssThresh;
121  m_inFastRec = false;
122  NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
123  };
124 
125  // Increase of cwnd based on current phase (slow start or congestion avoidance)
126  if (m_cWnd < m_ssThresh)
127  { // Slow start mode, add one segSize to cWnd. Default m_ssThresh is 65535. (RFC2001, sec.1)
128  m_cWnd += m_segmentSize;
129  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
130  }
131  else
132  { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd. (RFC2581, sec.3.1)
133  // To increase cwnd for one segSize per RTT, it should be (ackBytes*segSize)/cwnd
134  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get ();
135  adder = std::max (1.0, adder);
136  m_cWnd += static_cast<uint32_t> (adder);
137  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
138  }
139 
140  // Complete newAck processing
141  TcpSocketBase::NewAck (seq);
142 }
143 
144 // Fast recovery and fast retransmit
145 void
146 TcpReno::DupAck (const TcpHeader& t, uint32_t count)
147 {
148  NS_LOG_FUNCTION (this << "t " << count);
149  if (count == m_retxThresh && !m_inFastRec)
150  { // triple duplicate ack triggers fast retransmit (RFC2581, sec.3.2)
151  m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2);
152  m_cWnd = m_ssThresh + 3 * m_segmentSize;
153  m_inFastRec = true;
154  NS_LOG_INFO ("Triple dupack. Reset cwnd to " << m_cWnd << ", ssthresh to " << m_ssThresh);
155  DoRetransmit ();
156  }
157  else if (m_inFastRec)
158  { // In fast recovery, inc cwnd for every additional dupack (RFC2581, sec.3.2)
159  m_cWnd += m_segmentSize;
160  NS_LOG_INFO ("Increased cwnd to " << m_cWnd);
161  SendPendingData (m_connected);
162  };
163 }
164 
165 // Retransmit timeout
166 void TcpReno::Retransmit (void)
167 {
168  NS_LOG_FUNCTION (this);
169  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
170  m_inFastRec = false;
171 
172  // If erroneous timeout in closed/timed-wait state, just return
173  if (m_state == CLOSED || m_state == TIME_WAIT) return;
174  // If all data are received (non-closing socket and nothing to send), just return
175  if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return;
176 
177  // According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight
178  // size and cwnd is set to 1*MSS, then the lost packet is retransmitted and
179  // TCP back to slow start
180  m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2);
181  m_cWnd = m_segmentSize;
182  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
183  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
184  ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
185  m_rtt->IncreaseMultiplier (); // Double the next RTO
186  DoRetransmit (); // Retransmit the packet
187 }
188 
189 void
190 TcpReno::SetSegSize (uint32_t size)
191 {
192  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "TcpReno::SetSegSize() cannot change segment size after connection started.");
193  m_segmentSize = size;
194 }
195 
196 void
197 TcpReno::SetSSThresh (uint32_t threshold)
198 {
199  m_ssThresh = threshold;
200 }
201 
202 uint32_t
203 TcpReno::GetSSThresh (void) const
204 {
205  return m_ssThresh;
206 }
207 
208 void
209 TcpReno::SetInitialCwnd (uint32_t cwnd)
210 {
211  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "TcpReno::SetInitialCwnd() cannot change initial cwnd after connection started.");
212  m_initialCWnd = cwnd;
213 }
214 
215 uint32_t
216 TcpReno::GetInitialCwnd (void) const
217 {
218  return m_initialCWnd;
219 }
220 
221 void
222 TcpReno::InitializeCwnd (void)
223 {
224  /*
225  * Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
226  * not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
227  * m_segmentSize are set by the attribute system in ns3::TcpSocket.
228  */
229  m_cWnd = m_initialCWnd * m_segmentSize;
230 }
231 
232 } // namespace ns3
virtual int Listen(void)
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
SequenceNumber32 HeadSequence(void) const
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual int Listen(void)
Definition: tcp-reno.cc:77
#define NS_LOG_INFO(msg)
Definition: log.h:264
virtual void NewAck(const SequenceNumber32 &seq)
Definition: tcp-reno.cc:109
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
a polymophic address class
Definition: address.h:86
An implementation of a stream socket using TCP.
Definition: tcp-reno.h:38
virtual int Connect(const Address &address)
Definition: tcp-reno.cc:86
A base class for implementation of a stream socket using TCP.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Header for the Transmission Control Protocol.
Definition: tcp-header.h:43
virtual int Connect(const Address &address)
static Time Now(void)
Definition: simulator.cc:179
TcpReno(void)
Definition: tcp-reno.cc:54
bool SendPendingData(bool withAck=false)
virtual uint32_t Window(void)
Definition: tcp-reno.cc:95