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-newreno.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-newreno.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
(
"TcpNewReno"
);
32
33
namespace
ns3 {
34
35
NS_OBJECT_ENSURE_REGISTERED
(TcpNewReno);
36
37
TypeId
38
TcpNewReno::GetTypeId
(
void
)
39
{
40
static
TypeId
tid =
TypeId
(
"ns3::TcpNewReno"
)
41
.
SetParent
<
TcpSocketBase
> ()
42
.AddConstructor<TcpNewReno> ()
43
.AddAttribute (
"ReTxThreshold"
,
"Threshold for fast retransmit"
,
44
UintegerValue
(3),
45
MakeUintegerAccessor (&
TcpNewReno::m_retxThresh
),
46
MakeUintegerChecker<uint32_t> ())
47
.AddAttribute (
"LimitedTransmit"
,
"Enable limited transmit"
,
48
BooleanValue
(
false
),
49
MakeBooleanAccessor (&
TcpNewReno::m_limitedTx
),
50
MakeBooleanChecker ())
51
.AddTraceSource (
"CongestionWindow"
,
52
"The TCP connection's congestion window"
,
53
MakeTraceSourceAccessor
(&
TcpNewReno::m_cWnd
))
54
;
55
return
tid;
56
}
57
58
TcpNewReno::TcpNewReno
(
void
)
59
: m_retxThresh (3),
// mute valgrind, actual value set by the attribute system
60
m_inFastRec (false),
61
m_limitedTx (false)
// mute valgrind, actual value set by the attribute system
62
{
63
NS_LOG_FUNCTION
(
this
);
64
}
65
66
TcpNewReno::TcpNewReno
(
const
TcpNewReno
& sock)
67
:
TcpSocketBase
(sock),
68
m_cWnd (sock.m_cWnd),
69
m_ssThresh (sock.m_ssThresh),
70
m_initialCWnd (sock.m_initialCWnd),
71
m_retxThresh (sock.m_retxThresh),
72
m_inFastRec (false),
73
m_limitedTx (sock.m_limitedTx)
74
{
75
NS_LOG_FUNCTION
(
this
);
76
NS_LOG_LOGIC
(
"Invoked the copy constructor"
);
77
}
78
79
TcpNewReno::~TcpNewReno
(
void
)
80
{
81
}
82
84
int
85
TcpNewReno::Listen
(
void
)
86
{
87
NS_LOG_FUNCTION
(
this
);
88
InitializeCwnd
();
89
return
TcpSocketBase::Listen
();
90
}
91
93
int
94
TcpNewReno::Connect
(
const
Address
& address)
95
{
96
NS_LOG_FUNCTION
(
this
<< address);
97
InitializeCwnd
();
98
return
TcpSocketBase::Connect
(address);
99
}
100
102
uint32_t
103
TcpNewReno::Window
(
void
)
104
{
105
NS_LOG_FUNCTION
(
this
);
106
return
std::min (
m_rWnd
.
Get
(),
m_cWnd
.
Get
());
107
}
108
109
Ptr<TcpSocketBase>
110
TcpNewReno::Fork
(
void
)
111
{
112
return
CopyObject<TcpNewReno> (
this
);
113
}
114
116
void
117
TcpNewReno::NewAck
(
const
SequenceNumber32
& seq)
118
{
119
NS_LOG_FUNCTION
(
this
<< seq);
120
NS_LOG_LOGIC
(
"TcpNewReno receieved ACK for seq "
<< seq <<
121
" cwnd "
<<
m_cWnd
<<
122
" ssthresh "
<<
m_ssThresh
);
123
124
// Check for exit condition of fast recovery
125
if
(
m_inFastRec
&& seq <
m_recover
)
126
{
// Partial ACK, partial window deflation (RFC2582 sec.3 bullet #5 paragraph 3)
127
m_cWnd
-= seq -
m_txBuffer
.
HeadSequence
();
128
m_cWnd
+=
m_segmentSize
;
// increase cwnd
129
NS_LOG_INFO
(
"Partial ACK in fast recovery: cwnd set to "
<<
m_cWnd
);
130
TcpSocketBase::NewAck
(seq);
// update m_nextTxSequence and send new data if allowed by window
131
DoRetransmit
();
// Assume the next seq is lost. Retransmit lost packet
132
return
;
133
}
134
else
if
(
m_inFastRec
&& seq >=
m_recover
)
135
{
// Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1)
136
m_cWnd
= std::min (
m_ssThresh
,
BytesInFlight
() +
m_segmentSize
);
137
m_inFastRec
=
false
;
138
NS_LOG_INFO
(
"Received full ACK. Leaving fast recovery with cwnd set to "
<<
m_cWnd
);
139
}
140
141
// Increase of cwnd based on current phase (slow start or congestion avoidance)
142
if
(
m_cWnd
<
m_ssThresh
)
143
{
// Slow start mode, add one segSize to cWnd. Default m_ssThresh is 65535. (RFC2001, sec.1)
144
m_cWnd
+=
m_segmentSize
;
145
NS_LOG_INFO
(
"In SlowStart, updated to cwnd "
<<
m_cWnd
<<
" ssthresh "
<<
m_ssThresh
);
146
}
147
else
148
{
// Congestion avoidance mode, increase by (segSize*segSize)/cwnd. (RFC2581, sec.3.1)
149
// To increase cwnd for one segSize per RTT, it should be (ackBytes*segSize)/cwnd
150
double
adder =
static_cast<
double
>
(
m_segmentSize
*
m_segmentSize
) /
m_cWnd
.
Get
();
151
adder = std::max (1.0, adder);
152
m_cWnd
+=
static_cast<
uint32_t
>
(adder);
153
NS_LOG_INFO
(
"In CongAvoid, updated to cwnd "
<<
m_cWnd
<<
" ssthresh "
<<
m_ssThresh
);
154
}
155
156
// Complete newAck processing
157
TcpSocketBase::NewAck
(seq);
158
}
159
161
void
162
TcpNewReno::DupAck
(
const
TcpHeader
& t, uint32_t count)
163
{
164
NS_LOG_FUNCTION
(
this
<< count);
165
if
(count ==
m_retxThresh
&& !
m_inFastRec
)
166
{
// triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet #1)
167
m_ssThresh
= std::max (2 *
m_segmentSize
,
BytesInFlight
() / 2);
168
m_cWnd
=
m_ssThresh
+ 3 *
m_segmentSize
;
169
m_recover
=
m_highTxMark
;
170
m_inFastRec
=
true
;
171
NS_LOG_INFO
(
"Triple dupack. Enter fast recovery mode. Reset cwnd to "
<<
m_cWnd
<<
172
", ssthresh to "
<<
m_ssThresh
<<
" at fast recovery seqnum "
<<
m_recover
);
173
DoRetransmit
();
174
}
175
else
if
(
m_inFastRec
)
176
{
// Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3)
177
m_cWnd
+=
m_segmentSize
;
178
NS_LOG_INFO
(
"Dupack in fast recovery mode. Increase cwnd to "
<<
m_cWnd
);
179
SendPendingData
(
m_connected
);
180
}
181
else
if
(!
m_inFastRec
&&
m_limitedTx
&&
m_txBuffer
.
SizeFromSequence
(
m_nextTxSequence
) > 0)
182
{
// RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit
183
NS_LOG_INFO
(
"Limited transmit"
);
184
uint32_t sz =
SendDataPacket
(
m_nextTxSequence
,
m_segmentSize
,
true
);
185
m_nextTxSequence
+= sz;
// Advance next tx sequence
186
};
187
}
188
190
void
191
TcpNewReno::Retransmit
(
void
)
192
{
193
NS_LOG_FUNCTION
(
this
);
194
NS_LOG_LOGIC
(
this
<<
" ReTxTimeout Expired at time "
<<
Simulator::Now
().GetSeconds ());
195
m_inFastRec
=
false
;
196
197
// If erroneous timeout in closed/timed-wait state, just return
198
if
(
m_state
==
CLOSED
||
m_state
==
TIME_WAIT
)
return
;
199
// If all data are received (non-closing socket and nothing to send), just return
200
if
(
m_state
<=
ESTABLISHED
&&
m_txBuffer
.
HeadSequence
() >=
m_highTxMark
)
return
;
201
202
// According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight
203
// size and cwnd is set to 1*MSS, then the lost packet is retransmitted and
204
// TCP back to slow start
205
m_ssThresh
= std::max (2 *
m_segmentSize
,
BytesInFlight
() / 2);
206
m_cWnd
=
m_segmentSize
;
207
m_nextTxSequence
=
m_txBuffer
.
HeadSequence
();
// Restart from highest Ack
208
NS_LOG_INFO
(
"RTO. Reset cwnd to "
<<
m_cWnd
<<
209
", ssthresh to "
<<
m_ssThresh
<<
", restart from seqnum "
<<
m_nextTxSequence
);
210
m_rtt
->
IncreaseMultiplier
();
// Double the next RTO
211
DoRetransmit
();
// Retransmit the packet
212
}
213
214
void
215
TcpNewReno::SetSegSize
(uint32_t size)
216
{
217
NS_ABORT_MSG_UNLESS
(
m_state
==
CLOSED
,
"TcpNewReno::SetSegSize() cannot change segment size after connection started."
);
218
m_segmentSize
= size;
219
}
220
221
void
222
TcpNewReno::SetSSThresh
(uint32_t threshold)
223
{
224
m_ssThresh
= threshold;
225
}
226
227
uint32_t
228
TcpNewReno::GetSSThresh
(
void
)
const
229
{
230
return
m_ssThresh
;
231
}
232
233
void
234
TcpNewReno::SetInitialCwnd
(uint32_t cwnd)
235
{
236
NS_ABORT_MSG_UNLESS
(
m_state
==
CLOSED
,
"TcpNewReno::SetInitialCwnd() cannot change initial cwnd after connection started."
);
237
m_initialCWnd
= cwnd;
238
}
239
240
uint32_t
241
TcpNewReno::GetInitialCwnd
(
void
)
const
242
{
243
return
m_initialCWnd
;
244
}
245
246
void
247
TcpNewReno::InitializeCwnd
(
void
)
248
{
249
/*
250
* Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
251
* not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
252
* m_segmentSize are set by the attribute system in ns3::TcpSocket.
253
*/
254
m_cWnd
=
m_initialCWnd
*
m_segmentSize
;
255
}
256
257
}
// namespace ns3
src
internet
model
tcp-newreno.cc
Generated on Tue May 14 2013 11:08:23 for ns-3 by
1.8.1.2