author | Peter D. Barnes, Jr. <barnes26@llnl.gov> |
Thu, 02 Oct 2014 21:17:48 -0700 | |
changeset 10978 | 754c8256c35c |
parent 10968 | 2d29fee2b7b8 |
child 11151 | 5c9ec4cf871f |
permissions | -rw-r--r-- |
6694 | 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> |
|
9063
32755d0516f4
Bug 1237 - code cleanups related to includes
Vedran Miletić <rivanvx@gmail.com>
parents:
7256
diff
changeset
|
23 |
#include <cstring> |
32755d0516f4
Bug 1237 - code cleanups related to includes
Vedran Miletić <rivanvx@gmail.com>
parents:
7256
diff
changeset
|
24 |
|
6694 | 25 |
#include "ns3/packet.h" |
26 |
#include "ns3/fatal-error.h" |
|
27 |
#include "ns3/log.h" |
|
9063
32755d0516f4
Bug 1237 - code cleanups related to includes
Vedran Miletić <rivanvx@gmail.com>
parents:
7256
diff
changeset
|
28 |
|
6694 | 29 |
#include "tcp-tx-buffer.h" |
30 |
||
10968
2d29fee2b7b8
[Bug 1551] Redux: NS_LOG_COMPONENT_DEFINE inside or outside of ns3 namespace?
Peter D. Barnes, Jr. <barnes26@llnl.gov>
parents:
9063
diff
changeset
|
31 |
namespace ns3 { |
6694 | 32 |
|
10968
2d29fee2b7b8
[Bug 1551] Redux: NS_LOG_COMPONENT_DEFINE inside or outside of ns3 namespace?
Peter D. Barnes, Jr. <barnes26@llnl.gov>
parents:
9063
diff
changeset
|
33 |
NS_LOG_COMPONENT_DEFINE ("TcpTxBuffer"); |
6694 | 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)", |
|
10978
754c8256c35c
TracedValue callback function signatures.
Peter D. Barnes, Jr. <barnes26@llnl.gov>
parents:
10968
diff
changeset
|
43 |
MakeTraceSourceAccessor (&TcpTxBuffer::m_firstByteSeq), |
754c8256c35c
TracedValue callback function signatures.
Peter D. Barnes, Jr. <barnes26@llnl.gov>
parents:
10968
diff
changeset
|
44 |
"ns3::SequenceNumber32TracedValueCallback") |
6694 | 45 |
; |
46 |
return tid; |
|
47 |
} |
|
48 |
||
49 |
/* A user is supposed to create a TcpSocket through a factory. In TcpSocket, |
|
50 |
* there are attributes SndBufSize and RcvBufSize to control the default Tx and |
|
51 |
* Rx window sizes respectively, with default of 128 KiByte. The attribute |
|
52 |
* SndBufSize is passed to TcpTxBuffer by TcpSocketBase::SetSndBufSize() and in |
|
53 |
* turn, TcpTxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value |
|
54 |
* initialized below is insignificant. |
|
55 |
*/ |
|
56 |
TcpTxBuffer::TcpTxBuffer (uint32_t n) |
|
7256
b04ba6772f8c
rerun check-style.py at default level to enforce space after function name
Tom Henderson <tomh@tomh.org>
parents:
7176
diff
changeset
|
57 |
: m_firstByteSeq (n), m_size (0), m_maxBuffer (32768), m_data (0) |
6694 | 58 |
{ |
59 |
} |
|
60 |
||
61 |
TcpTxBuffer::~TcpTxBuffer (void) |
|
62 |
{ |
|
63 |
} |
|
64 |
||
65 |
SequenceNumber32 |
|
66 |
TcpTxBuffer::HeadSequence (void) const |
|
67 |
{ |
|
68 |
return m_firstByteSeq; |
|
69 |
} |
|
70 |
||
71 |
SequenceNumber32 |
|
72 |
TcpTxBuffer::TailSequence (void) const |
|
73 |
{ |
|
74 |
return m_firstByteSeq + SequenceNumber32 (m_size); |
|
75 |
} |
|
76 |
||
77 |
uint32_t |
|
78 |
TcpTxBuffer::Size (void) const |
|
79 |
{ |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
80 |
return m_size; |
6694 | 81 |
} |
82 |
||
83 |
uint32_t |
|
84 |
TcpTxBuffer::MaxBufferSize (void) const |
|
85 |
{ |
|
86 |
return m_maxBuffer; |
|
87 |
} |
|
88 |
||
89 |
void |
|
90 |
TcpTxBuffer::SetMaxBufferSize (uint32_t n) |
|
91 |
{ |
|
92 |
m_maxBuffer = n; |
|
93 |
} |
|
94 |
||
95 |
uint32_t |
|
96 |
TcpTxBuffer::Available (void) const |
|
97 |
{ |
|
98 |
return m_maxBuffer - m_size; |
|
99 |
} |
|
100 |
||
101 |
bool |
|
102 |
TcpTxBuffer::Add (Ptr<Packet> p) |
|
103 |
{ |
|
104 |
NS_LOG_FUNCTION (this << p); |
|
105 |
NS_LOG_LOGIC ("Packet of size " << p->GetSize () << " appending to window starting at " |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
106 |
<< m_firstByteSeq << ", availSize="<< Available ()); |
6694 | 107 |
if (p->GetSize () <= Available ()) |
108 |
{ |
|
109 |
if (p->GetSize () > 0) |
|
110 |
{ |
|
111 |
m_data.push_back (p); |
|
112 |
m_size += p->GetSize (); |
|
113 |
NS_LOG_LOGIC ("Updated size=" << m_size << ", lastSeq=" << m_firstByteSeq + SequenceNumber32 (m_size)); |
|
114 |
} |
|
115 |
return true; |
|
116 |
} |
|
117 |
NS_LOG_LOGIC ("Rejected. Not enough room to buffer packet."); |
|
118 |
return false; |
|
119 |
} |
|
120 |
||
121 |
uint32_t |
|
122 |
TcpTxBuffer::SizeFromSequence (const SequenceNumber32& seq) const |
|
123 |
{ |
|
124 |
NS_LOG_FUNCTION (this << seq); |
|
125 |
// Sequence of last byte in buffer |
|
126 |
SequenceNumber32 lastSeq = m_firstByteSeq + SequenceNumber32 (m_size); |
|
127 |
// Non-negative size |
|
128 |
NS_LOG_LOGIC ("HeadSeq=" << m_firstByteSeq << ", lastSeq=" << lastSeq << ", size=" << m_size << |
|
129 |
", returns " << lastSeq - seq); |
|
130 |
return lastSeq - seq; |
|
131 |
} |
|
132 |
||
133 |
Ptr<Packet> |
|
134 |
TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq) |
|
135 |
{ |
|
136 |
NS_LOG_FUNCTION (this << numBytes << seq); |
|
137 |
uint32_t s = std::min (numBytes, SizeFromSequence (seq)); // Real size to extract. Insure not beyond end of data |
|
138 |
if (s == 0) |
|
139 |
{ |
|
140 |
return Create<Packet> (); // Empty packet returned |
|
141 |
} |
|
142 |
if (m_data.size () == 0) |
|
143 |
{ // No actual data, just return dummy-data packet of correct size |
|
144 |
return Create<Packet> (s); |
|
145 |
} |
|
146 |
||
147 |
// Extract data from the buffer and return |
|
148 |
uint32_t offset = seq - m_firstByteSeq.Get (); |
|
149 |
uint32_t count = 0; // Offset of the first byte of a packet in the buffer |
|
150 |
uint32_t pktSize = 0; |
|
151 |
bool beginFound = false; |
|
152 |
int pktCount = 0; |
|
153 |
Ptr<Packet> outPacket; |
|
154 |
NS_LOG_LOGIC ("There are " << m_data.size () << " number of packets in buffer"); |
|
155 |
for (BufIterator i = m_data.begin (); i != m_data.end (); ++i) |
|
156 |
{ |
|
157 |
pktCount++; |
|
158 |
pktSize = (*i)->GetSize (); |
|
159 |
if (!beginFound) |
|
160 |
{ // Look for first fragment |
|
161 |
if (count + pktSize > offset) |
|
162 |
{ |
|
163 |
NS_LOG_LOGIC ("First byte found in packet #" << pktCount << " at buffer offset " << count |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
164 |
<< ", packet len=" << pktSize); |
6694 | 165 |
beginFound = true; |
166 |
uint32_t packetOffset = offset - count; |
|
167 |
uint32_t fragmentLength = count + pktSize - offset; |
|
168 |
if (fragmentLength >= s) |
|
169 |
{ // Data to be copied falls entirely in this packet |
|
170 |
return (*i)->CreateFragment (packetOffset, s); |
|
171 |
} |
|
172 |
else |
|
173 |
{ // This packet only fulfills part of the request |
|
174 |
outPacket = (*i)->CreateFragment (packetOffset, fragmentLength); |
|
175 |
} |
|
176 |
NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ()); |
|
177 |
} |
|
178 |
} |
|
179 |
else if (count + pktSize >= offset + s) |
|
180 |
{ // Last packet fragment found |
|
181 |
NS_LOG_LOGIC ("Last byte found in packet #" << pktCount << " at buffer offset " << count |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
182 |
<< ", packet len=" << pktSize); |
6694 | 183 |
uint32_t fragmentLength = offset + s - count; |
184 |
Ptr<Packet> endFragment = (*i)->CreateFragment (0, fragmentLength); |
|
185 |
outPacket->AddAtEnd (endFragment); |
|
186 |
NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ()); |
|
187 |
break; |
|
188 |
} |
|
189 |
else |
|
190 |
{ |
|
191 |
NS_LOG_LOGIC ("Appending to output the packet #" << pktCount << " of offset " << count << " len=" << pktSize); |
|
192 |
outPacket->AddAtEnd (*i); |
|
193 |
NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ()); |
|
194 |
} |
|
195 |
count += pktSize; |
|
196 |
} |
|
197 |
NS_ASSERT (outPacket->GetSize () == s); |
|
198 |
return outPacket; |
|
199 |
} |
|
200 |
||
201 |
void |
|
202 |
TcpTxBuffer::SetHeadSequence (const SequenceNumber32& seq) |
|
203 |
{ |
|
204 |
NS_LOG_FUNCTION (this << seq); |
|
205 |
m_firstByteSeq = seq; |
|
206 |
} |
|
207 |
||
208 |
void |
|
209 |
TcpTxBuffer::DiscardUpTo (const SequenceNumber32& seq) |
|
210 |
{ |
|
211 |
NS_LOG_FUNCTION (this << seq); |
|
212 |
NS_LOG_LOGIC ("current data size=" << m_size << ", headSeq=" << m_firstByteSeq << ", maxBuffer=" << m_maxBuffer |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
213 |
<< ", numPkts=" << m_data.size ()); |
6694 | 214 |
// Cases do not need to scan the buffer |
215 |
if (m_firstByteSeq >= seq) return; |
|
216 |
||
217 |
// Scan the buffer and discard packets |
|
218 |
uint32_t offset = seq - m_firstByteSeq.Get (); // Number of bytes to remove |
|
219 |
uint32_t pktSize; |
|
220 |
NS_LOG_LOGIC ("Offset=" << offset); |
|
221 |
BufIterator i = m_data.begin (); |
|
222 |
while (i != m_data.end ()) |
|
223 |
{ |
|
224 |
if (offset > (*i)->GetSize ()) |
|
225 |
{ // This packet is behind the seqnum. Remove this packet from the buffer |
|
226 |
pktSize = (*i)->GetSize (); |
|
227 |
m_size -= pktSize; |
|
228 |
offset -= pktSize; |
|
229 |
m_firstByteSeq += pktSize; |
|
230 |
i = m_data.erase (i); |
|
231 |
NS_LOG_LOGIC ("Removed one packet of size " << pktSize << ", offset=" << offset); |
|
232 |
} |
|
233 |
else if (offset > 0) |
|
234 |
{ // Part of the packet is behind the seqnum. Fragment |
|
235 |
pktSize = (*i)->GetSize () - offset; |
|
236 |
*i = (*i)->CreateFragment (offset, pktSize); |
|
237 |
m_size -= offset; |
|
238 |
m_firstByteSeq += offset; |
|
239 |
NS_LOG_LOGIC ("Fragmented one packet by size " << offset << ", new size=" << pktSize); |
|
240 |
break; |
|
241 |
} |
|
242 |
} |
|
243 |
// Catching the case of ACKing a FIN |
|
244 |
if (m_size == 0) |
|
245 |
{ |
|
246 |
m_firstByteSeq = seq; |
|
247 |
} |
|
248 |
NS_LOG_LOGIC ("size=" << m_size << " headSeq=" << m_firstByteSeq << " maxBuffer=" << m_maxBuffer |
|
7176
9f2663992e99
internet coding style changes
Josh Pelkey <jpelkey@gatech.edu>
parents:
6834
diff
changeset
|
249 |
<<" numPkts="<< m_data.size ()); |
6694 | 250 |
NS_ASSERT (m_firstByteSeq == seq); |
251 |
} |
|
252 |
||
253 |
} // namepsace ns3 |