A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
tcp-reno.cc
Go to the documentation of this file.
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
77
TcpReno::Listen
(
void
)
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
95
TcpReno::Window
(
void
)
96
{
97
NS_LOG_FUNCTION
(
this
);
98
return
std::min (
m_rWnd
.
Get
(),
m_cWnd
.
Get
());
99
}
100
101
Ptr<TcpSocketBase>
102
TcpReno::Fork
(
void
)
103
{
104
return
CopyObject<TcpReno> (
this
);
105
}
106
108
void
109
TcpReno::NewAck
(
const
SequenceNumber32
& seq)
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
src
internet
model
tcp-reno.cc
Generated on Tue May 14 2013 11:08:23 for ns-3 by
1.8.1.2