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-tx-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 <iostream>
22
#include <algorithm>
23
#include <cstring>
24
25
#include "ns3/packet.h"
26
#include "ns3/fatal-error.h"
27
#include "ns3/log.h"
28
29
#include "
tcp-tx-buffer.h
"
30
31
NS_LOG_COMPONENT_DEFINE
(
"TcpTxBuffer"
);
32
33
namespace
ns3 {
34
35
TypeId
36
TcpTxBuffer::GetTypeId
(
void
)
37
{
38
static
TypeId
tid =
TypeId
(
"ns3::TcpTxBuffer"
)
39
.
SetParent
<
Object
> ()
40
.AddConstructor<TcpTxBuffer> ()
41
.AddTraceSource (
"UnackSequence"
,
42
"First unacknowledged sequence number (SND.UNA)"
,
43
MakeTraceSourceAccessor
(&
TcpTxBuffer::m_firstByteSeq
))
44
;
45
return
tid;
46
}
47
48
/* A user is supposed to create a TcpSocket through a factory. In TcpSocket,
49
* there are attributes SndBufSize and RcvBufSize to control the default Tx and
50
* Rx window sizes respectively, with default of 128 KiByte. The attribute
51
* SndBufSize is passed to TcpTxBuffer by TcpSocketBase::SetSndBufSize() and in
52
* turn, TcpTxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value
53
* initialized below is insignificant.
54
*/
55
TcpTxBuffer::TcpTxBuffer
(uint32_t n)
56
: m_firstByteSeq (n), m_size (0), m_maxBuffer (32768), m_data (0)
57
{
58
}
59
60
TcpTxBuffer::~TcpTxBuffer
(
void
)
61
{
62
}
63
64
SequenceNumber32
65
TcpTxBuffer::HeadSequence
(
void
)
const
66
{
67
return
m_firstByteSeq
;
68
}
69
70
SequenceNumber32
71
TcpTxBuffer::TailSequence
(
void
)
const
72
{
73
return
m_firstByteSeq
+
SequenceNumber32
(
m_size
);
74
}
75
76
uint32_t
77
TcpTxBuffer::Size
(
void
)
const
78
{
79
return
m_size
;
80
}
81
82
uint32_t
83
TcpTxBuffer::MaxBufferSize
(
void
)
const
84
{
85
return
m_maxBuffer
;
86
}
87
88
void
89
TcpTxBuffer::SetMaxBufferSize
(uint32_t n)
90
{
91
m_maxBuffer
= n;
92
}
93
94
uint32_t
95
TcpTxBuffer::Available
(
void
)
const
96
{
97
return
m_maxBuffer
-
m_size
;
98
}
99
100
bool
101
TcpTxBuffer::Add
(
Ptr<Packet>
p)
102
{
103
NS_LOG_FUNCTION
(
this
<< p);
104
NS_LOG_LOGIC
(
"Packet of size "
<< p->
GetSize
() <<
" appending to window starting at "
105
<<
m_firstByteSeq
<<
", availSize="
<<
Available
());
106
if
(p->
GetSize
() <=
Available
())
107
{
108
if
(p->
GetSize
() > 0)
109
{
110
m_data
.push_back (p);
111
m_size
+= p->
GetSize
();
112
NS_LOG_LOGIC
(
"Updated size="
<<
m_size
<<
", lastSeq="
<<
m_firstByteSeq
+
SequenceNumber32
(
m_size
));
113
}
114
return
true
;
115
}
116
NS_LOG_LOGIC
(
"Rejected. Not enough room to buffer packet."
);
117
return
false
;
118
}
119
120
uint32_t
121
TcpTxBuffer::SizeFromSequence
(
const
SequenceNumber32
& seq)
const
122
{
123
NS_LOG_FUNCTION
(
this
<< seq);
124
// Sequence of last byte in buffer
125
SequenceNumber32
lastSeq =
m_firstByteSeq
+
SequenceNumber32
(
m_size
);
126
// Non-negative size
127
NS_LOG_LOGIC
(
"HeadSeq="
<<
m_firstByteSeq
<<
", lastSeq="
<< lastSeq <<
", size="
<<
m_size
<<
128
", returns "
<< lastSeq - seq);
129
return
lastSeq - seq;
130
}
131
132
Ptr<Packet>
133
TcpTxBuffer::CopyFromSequence
(uint32_t numBytes,
const
SequenceNumber32
& seq)
134
{
135
NS_LOG_FUNCTION
(
this
<< numBytes << seq);
136
uint32_t s = std::min (numBytes,
SizeFromSequence
(seq));
// Real size to extract. Insure not beyond end of data
137
if
(s == 0)
138
{
139
return
Create<Packet> ();
// Empty packet returned
140
}
141
if
(
m_data
.size () == 0)
142
{
// No actual data, just return dummy-data packet of correct size
143
return
Create<Packet> (s);
144
}
145
146
// Extract data from the buffer and return
147
uint32_t offset = seq -
m_firstByteSeq
.
Get
();
148
uint32_t count = 0;
// Offset of the first byte of a packet in the buffer
149
uint32_t pktSize = 0;
150
bool
beginFound =
false
;
151
int
pktCount = 0;
152
Ptr<Packet>
outPacket;
153
NS_LOG_LOGIC
(
"There are "
<<
m_data
.size () <<
" number of packets in buffer"
);
154
for
(
BufIterator
i =
m_data
.begin (); i !=
m_data
.end (); ++i)
155
{
156
pktCount++;
157
pktSize = (*i)->GetSize ();
158
if
(!beginFound)
159
{
// Look for first fragment
160
if
(count + pktSize > offset)
161
{
162
NS_LOG_LOGIC
(
"First byte found in packet #"
<< pktCount <<
" at buffer offset "
<< count
163
<<
", packet len="
<< pktSize);
164
beginFound =
true
;
165
uint32_t packetOffset = offset - count;
166
uint32_t fragmentLength = count + pktSize - offset;
167
if
(fragmentLength >= s)
168
{
// Data to be copied falls entirely in this packet
169
return
(*i)->CreateFragment (packetOffset, s);
170
}
171
else
172
{
// This packet only fulfills part of the request
173
outPacket = (*i)->
CreateFragment
(packetOffset, fragmentLength);
174
}
175
NS_LOG_LOGIC
(
"Output packet is now of size "
<< outPacket->
GetSize
());
176
}
177
}
178
else
if
(count + pktSize >= offset + s)
179
{
// Last packet fragment found
180
NS_LOG_LOGIC
(
"Last byte found in packet #"
<< pktCount <<
" at buffer offset "
<< count
181
<<
", packet len="
<< pktSize);
182
uint32_t fragmentLength = offset + s - count;
183
Ptr<Packet>
endFragment = (*i)->
CreateFragment
(0, fragmentLength);
184
outPacket->
AddAtEnd
(endFragment);
185
NS_LOG_LOGIC
(
"Output packet is now of size "
<< outPacket->
GetSize
());
186
break
;
187
}
188
else
189
{
190
NS_LOG_LOGIC
(
"Appending to output the packet #"
<< pktCount <<
" of offset "
<< count <<
" len="
<< pktSize);
191
outPacket->
AddAtEnd
(*i);
192
NS_LOG_LOGIC
(
"Output packet is now of size "
<< outPacket->
GetSize
());
193
}
194
count += pktSize;
195
}
196
NS_ASSERT
(outPacket->
GetSize
() == s);
197
return
outPacket;
198
}
199
200
void
201
TcpTxBuffer::SetHeadSequence
(
const
SequenceNumber32
& seq)
202
{
203
NS_LOG_FUNCTION
(
this
<< seq);
204
m_firstByteSeq
= seq;
205
}
206
207
void
208
TcpTxBuffer::DiscardUpTo
(
const
SequenceNumber32
& seq)
209
{
210
NS_LOG_FUNCTION
(
this
<< seq);
211
NS_LOG_LOGIC
(
"current data size="
<<
m_size
<<
", headSeq="
<<
m_firstByteSeq
<<
", maxBuffer="
<<
m_maxBuffer
212
<<
", numPkts="
<<
m_data
.size ());
213
// Cases do not need to scan the buffer
214
if
(
m_firstByteSeq
>= seq)
return
;
215
216
// Scan the buffer and discard packets
217
uint32_t offset = seq -
m_firstByteSeq
.
Get
();
// Number of bytes to remove
218
uint32_t pktSize;
219
NS_LOG_LOGIC
(
"Offset="
<< offset);
220
BufIterator
i =
m_data
.begin ();
221
while
(i !=
m_data
.end ())
222
{
223
if
(offset > (*i)->GetSize ())
224
{
// This packet is behind the seqnum. Remove this packet from the buffer
225
pktSize = (*i)->GetSize ();
226
m_size
-= pktSize;
227
offset -= pktSize;
228
m_firstByteSeq
+= pktSize;
229
i =
m_data
.erase (i);
230
NS_LOG_LOGIC
(
"Removed one packet of size "
<< pktSize <<
", offset="
<< offset);
231
}
232
else
if
(offset > 0)
233
{
// Part of the packet is behind the seqnum. Fragment
234
pktSize = (*i)->GetSize () - offset;
235
*i = (*i)->CreateFragment (offset, pktSize);
236
m_size
-= offset;
237
m_firstByteSeq
+= offset;
238
NS_LOG_LOGIC
(
"Fragmented one packet by size "
<< offset <<
", new size="
<< pktSize);
239
break
;
240
}
241
}
242
// Catching the case of ACKing a FIN
243
if
(
m_size
== 0)
244
{
245
m_firstByteSeq
= seq;
246
}
247
NS_LOG_LOGIC
(
"size="
<<
m_size
<<
" headSeq="
<<
m_firstByteSeq
<<
" maxBuffer="
<<
m_maxBuffer
248
<<
" numPkts="
<<
m_data
.size ());
249
NS_ASSERT
(
m_firstByteSeq
== seq);
250
}
251
252
}
// namepsace ns3
src
internet
model
tcp-tx-buffer.cc
Generated on Fri Dec 21 2012 19:00:38 for ns-3 by
1.8.1.2