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-rx-buffer.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
#include "ns3/packet.h"
22
#include "ns3/fatal-error.h"
23
#include "ns3/log.h"
24
#include "
tcp-rx-buffer.h
"
25
26
NS_LOG_COMPONENT_DEFINE
(
"TcpRxBuffer"
);
27
28
namespace
ns3 {
29
30
TypeId
31
TcpRxBuffer::GetTypeId
(
void
)
32
{
33
static
TypeId
tid =
TypeId
(
"ns3::TcpRxBuffer"
)
34
.
SetParent
<
Object
> ()
35
.AddConstructor<TcpRxBuffer> ()
36
.AddTraceSource (
"NextRxSequence"
,
37
"Next sequence number expected (RCV.NXT)"
,
38
MakeTraceSourceAccessor
(&
TcpRxBuffer::m_nextRxSeq
))
39
;
40
return
tid;
41
}
42
43
/* A user is supposed to create a TcpSocket through a factory. In TcpSocket,
44
* there are attributes SndBufSize and RcvBufSize to control the default Tx and
45
* Rx window sizes respectively, with default of 128 KiByte. The attribute
46
* RcvBufSize is passed to TcpRxBuffer by TcpSocketBase::SetRcvBufSize() and in
47
* turn, TcpRxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value
48
* initialized below is insignificant.
49
*/
50
TcpRxBuffer::TcpRxBuffer
(uint32_t n)
51
: m_nextRxSeq (n), m_gotFin (false), m_size (0), m_maxBuffer (32768), m_availBytes (0)
52
{
53
}
54
55
TcpRxBuffer::~TcpRxBuffer
()
56
{
57
}
58
59
SequenceNumber32
60
TcpRxBuffer::NextRxSequence
(
void
)
const
61
{
62
return
m_nextRxSeq
;
63
}
64
65
void
66
TcpRxBuffer::SetNextRxSequence
(
const
SequenceNumber32
& s)
67
{
68
m_nextRxSeq
= s;
69
}
70
71
uint32_t
72
TcpRxBuffer::MaxBufferSize
(
void
)
const
73
{
74
return
m_maxBuffer
;
75
}
76
77
void
78
TcpRxBuffer::SetMaxBufferSize
(uint32_t s)
79
{
80
m_maxBuffer
= s;
81
}
82
83
uint32_t
84
TcpRxBuffer::Size
(
void
)
const
85
{
86
return
m_size
;
87
}
88
89
uint32_t
90
TcpRxBuffer::Available
()
const
91
{
92
return
m_availBytes
;
93
}
94
95
void
96
TcpRxBuffer::IncNextRxSequence
()
97
{
98
NS_LOG_FUNCTION
(
this
);
99
// Increment nextRxSeq is valid only if we don't have any data buffered,
100
// this is supposed to be called only during the three-way handshake
101
NS_ASSERT
(
m_size
== 0);
102
m_nextRxSeq
++;
103
}
104
105
// Return the lowest sequence number that this TcpRxBuffer cannot accept
106
SequenceNumber32
107
TcpRxBuffer::MaxRxSequence
(
void
)
const
108
{
109
if
(
m_gotFin
)
110
{
// No data allowed beyond FIN
111
return
m_finSeq
;
112
}
113
else
if
(
m_data
.size ())
114
{
// No data allowed beyond Rx window allowed
115
return
m_data
.begin ()->first +
SequenceNumber32
(
m_maxBuffer
);
116
}
117
return
m_nextRxSeq
+
SequenceNumber32
(
m_maxBuffer
);
118
}
119
120
void
121
TcpRxBuffer::SetFinSequence
(
const
SequenceNumber32
& s)
122
{
123
NS_LOG_FUNCTION
(
this
);
124
125
m_gotFin
=
true
;
126
m_finSeq
= s;
127
if
(
m_nextRxSeq
==
m_finSeq
) ++
m_nextRxSeq
;
128
}
129
130
bool
131
TcpRxBuffer::Finished
(
void
)
132
{
133
return
(
m_gotFin
&&
m_finSeq
<
m_nextRxSeq
);
134
}
135
136
bool
137
TcpRxBuffer::Add
(
Ptr<Packet>
p,
TcpHeader
const
& tcph)
138
{
139
NS_LOG_FUNCTION
(
this
<< p << tcph);
140
141
uint32_t pktSize = p->
GetSize
();
142
SequenceNumber32
headSeq = tcph.
GetSequenceNumber
();
143
SequenceNumber32
tailSeq = headSeq +
SequenceNumber32
(pktSize);
144
NS_LOG_LOGIC
(
"Add pkt "
<< p <<
" len="
<< pktSize <<
" seq="
<< headSeq
145
<<
", when NextRxSeq="
<<
m_nextRxSeq
<<
", buffsize="
<<
m_size
);
146
147
// Trim packet to fit Rx window specification
148
if
(headSeq <
m_nextRxSeq
) headSeq =
m_nextRxSeq
;
149
if
(
m_data
.size ())
150
{
151
SequenceNumber32 maxSeq =
m_data
.begin ()->first +
SequenceNumber32
(
m_maxBuffer
);
152
if
(maxSeq < tailSeq) tailSeq = maxSeq;
153
if
(tailSeq < headSeq) headSeq = tailSeq;
154
}
155
// Remove overlapped bytes from packet
156
BufIterator
i =
m_data
.begin ();
157
while
(i !=
m_data
.end () && i->first <= tailSeq)
158
{
159
SequenceNumber32 lastByteSeq = i->first +
SequenceNumber32
(i->second->GetSize ());
160
if
(lastByteSeq > headSeq)
161
{
162
if
(i->first > headSeq && lastByteSeq < tailSeq)
163
{
// Rare case: Existing packet is embedded fully in the new packet
164
m_size
-= i->second->GetSize ();
165
m_data
.erase (i++);
166
continue
;
167
}
168
if
(i->first <= headSeq)
169
{
// Incoming head is overlapped
170
headSeq = lastByteSeq;
171
}
172
if
(lastByteSeq >= tailSeq)
173
{
// Incoming tail is overlapped
174
tailSeq = i->first;
175
}
176
}
177
++i;
178
}
179
// We now know how much we are going to store, trim the packet
180
if
(headSeq >= tailSeq)
181
{
182
NS_LOG_LOGIC
(
"Nothing to buffer"
);
183
return
false
;
// Nothing to buffer anyway
184
}
185
else
186
{
187
uint32_t
start
= headSeq - tcph.
GetSequenceNumber
();
188
uint32_t length = tailSeq - headSeq;
189
p = p->
CreateFragment
(start, length);
190
NS_ASSERT
(length == p->
GetSize
());
191
}
192
// Insert packet into buffer
193
NS_ASSERT
(
m_data
.find (headSeq) ==
m_data
.end ());
// Shouldn't be there yet
194
m_data
[ headSeq ] = p;
195
NS_LOG_LOGIC
(
"Buffered packet of seqno="
<< headSeq <<
" len="
<< p->
GetSize
());
196
// Update variables
197
m_size
+= p->
GetSize
();
// Occupancy
198
for
(
BufIterator
i = m_data.begin (); i != m_data.end (); ++i)
199
{
200
if
(i->first <
m_nextRxSeq
)
201
{
202
continue
;
203
}
204
else
if
(i->first >
m_nextRxSeq
)
205
{
206
break
;
207
};
208
m_nextRxSeq
= i->first +
SequenceNumber32
(i->second->GetSize ());
209
m_availBytes
+= i->second->GetSize ();
210
}
211
NS_LOG_LOGIC
(
"Updated buffer occupancy="
<< m_size <<
" nextRxSeq="
<<
m_nextRxSeq
);
212
if
(
m_gotFin
&&
m_nextRxSeq
==
m_finSeq
)
213
{
// Account for the FIN packet
214
++
m_nextRxSeq
;
215
};
216
return
true
;
217
}
218
219
Ptr<Packet>
220
TcpRxBuffer::Extract
(uint32_t maxSize)
221
{
222
NS_LOG_FUNCTION
(
this
<< maxSize);
223
224
uint32_t extractSize = std::min (maxSize,
m_availBytes
);
225
NS_LOG_LOGIC
(
"Requested to extract "
<< extractSize <<
" bytes from TcpRxBuffer of size="
<<
m_size
);
226
if
(extractSize == 0)
return
0;
// No contiguous block to return
227
NS_ASSERT
(
m_data
.size ());
// At least we have something to extract
228
Ptr<Packet>
outPkt = Create<Packet> ();
// The packet that contains all the data to return
229
BufIterator
i;
230
while
(extractSize)
231
{
// Check the buffered data for delivery
232
i =
m_data
.begin ();
233
NS_ASSERT
(i->first <=
m_nextRxSeq
);
// in-sequence data expected
234
// Check if we send the whole pkt or just a partial
235
uint32_t pktSize = i->second->GetSize ();
236
if
(pktSize <= extractSize)
237
{
// Whole packet is extracted
238
outPkt->AddAtEnd (i->second);
239
m_data
.erase (i);
240
m_size
-= pktSize;
241
m_availBytes
-= pktSize;
242
extractSize -= pktSize;
243
}
244
else
245
{
// Partial is extracted and done
246
outPkt->AddAtEnd (i->second->CreateFragment (0, extractSize));
247
m_data
[i->first +
SequenceNumber32
(extractSize)] = i->second->CreateFragment (extractSize, pktSize - extractSize);
248
m_data
.erase (i);
249
m_size
-= extractSize;
250
m_availBytes
-= extractSize;
251
extractSize = 0;
252
}
253
}
254
if
(outPkt->GetSize () == 0)
255
{
256
NS_LOG_LOGIC
(
"Nothing extracted."
);
257
return
0;
258
}
259
NS_LOG_LOGIC
(
"Extracted "
<< outPkt->GetSize ( ) <<
" bytes, bufsize="
<<
m_size
260
<<
", num pkts in buffer="
<<
m_data
.size ());
261
return
outPkt;
262
}
263
264
}
//namepsace ns3
src
internet
model
tcp-rx-buffer.cc
Generated on Tue Nov 13 2012 10:32:15 for ns-3 by
1.8.1.2