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