LEFT | RIGHT |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2010 Adrian Sai-wah Tam | 3 * Copyright (c) 2010 Adrian Sai-wah Tam |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 2 as |
7 * published by the Free Software Foundation; | 7 * published by the Free Software Foundation; |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 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 | 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 | 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 * | 17 * |
18 * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com> | 18 * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com> |
19 */ | 19 */ |
20 | 20 |
21 #include "ns3/packet.h" | 21 #include "ns3/packet.h" |
22 #include "ns3/fatal-error.h" | 22 #include "ns3/fatal-error.h" |
23 #include "ns3/log.h" | 23 #include "ns3/log.h" |
24 #include "tcp-rx-buffer.h" | 24 #include "tcp-rx-buffer.h" |
25 | 25 |
26 NS_LOG_COMPONENT_DEFINE ("TcpRxBuffer"); | 26 NS_LOG_COMPONENT_DEFINE ("TcpRxBuffer"); |
27 | 27 |
28 namespace ns3 { | 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 } |
29 | 42 |
30 /* A user is supposed to create a TcpSocket through a factory. In TcpSocket, | 43 /* A user is supposed to create a TcpSocket through a factory. In TcpSocket, |
31 * there are attributes SndBufSize and RcvBufSize to control the default Tx and | 44 * there are attributes SndBufSize and RcvBufSize to control the default Tx and |
32 * Rx window sizes respectively, with default of 128 KiByte. The attribute | 45 * Rx window sizes respectively, with default of 128 KiByte. The attribute |
33 * RcvBufSize is passed to TcpRxBuffer by TcpSocketBase::SetRcvBufSize() and in | 46 * RcvBufSize is passed to TcpRxBuffer by TcpSocketBase::SetRcvBufSize() and in |
34 * turn, TcpRxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value | 47 * turn, TcpRxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value |
35 * initialized below is insignificant. | 48 * initialized below is insignificant. |
36 */ | 49 */ |
37 TcpRxBuffer::TcpRxBuffer (uint32_t n) | 50 TcpRxBuffer::TcpRxBuffer (uint32_t n) |
38 : m_nextRxSeq(n), m_gotFin(false), m_size(0), m_maxBuffer(32768), m_availBytes
(0) | 51 : m_nextRxSeq(n), m_gotFin(false), m_size(0), m_maxBuffer(32768), m_availBytes
(0) |
39 { | 52 { |
40 } | 53 } |
41 | 54 |
42 TcpRxBuffer::~TcpRxBuffer () | 55 TcpRxBuffer::~TcpRxBuffer () |
43 { | 56 { |
44 } | 57 } |
45 | 58 |
46 SequenceNumber | 59 SequenceNumber32 |
47 TcpRxBuffer::NextRxSequence (void) const | 60 TcpRxBuffer::NextRxSequence (void) const |
48 { | 61 { |
49 return m_nextRxSeq; | 62 return m_nextRxSeq; |
50 } | 63 } |
51 | 64 |
52 void | 65 void |
53 TcpRxBuffer::SetNextRxSequence (const SequenceNumber& s) | 66 TcpRxBuffer::SetNextRxSequence (const SequenceNumber32& s) |
54 { | 67 { |
55 m_nextRxSeq = s; | 68 m_nextRxSeq = s; |
56 } | 69 } |
57 | 70 |
58 uint32_t | 71 uint32_t |
59 TcpRxBuffer::MaxBufferSize (void) const | 72 TcpRxBuffer::MaxBufferSize (void) const |
60 { | 73 { |
61 return m_maxBuffer; | 74 return m_maxBuffer; |
62 } | 75 } |
63 | 76 |
(...skipping 19 matching lines...) Expand all Loading... |
83 TcpRxBuffer::IncNextRxSequence () | 96 TcpRxBuffer::IncNextRxSequence () |
84 { | 97 { |
85 NS_LOG_FUNCTION (this); | 98 NS_LOG_FUNCTION (this); |
86 // Increment nextRxSeq is valid only if we don't have any data buffered, | 99 // Increment nextRxSeq is valid only if we don't have any data buffered, |
87 // this is supposed to be called only during the three-way handshake | 100 // this is supposed to be called only during the three-way handshake |
88 NS_ASSERT (m_size == 0); | 101 NS_ASSERT (m_size == 0); |
89 m_nextRxSeq++; | 102 m_nextRxSeq++; |
90 } | 103 } |
91 | 104 |
92 // Return the highest sequence number that this TcpRxBuffer can accept | 105 // Return the highest sequence number that this TcpRxBuffer can accept |
93 SequenceNumber | 106 SequenceNumber32 |
94 TcpRxBuffer::MaxRxSequence (void) const | 107 TcpRxBuffer::MaxRxSequence (void) const |
95 { | 108 { |
96 if (m_gotFin) | 109 if (m_gotFin) |
97 { // No data allowed beyond FIN | 110 { // No data allowed beyond FIN |
98 return m_finSeq; | 111 return m_finSeq; |
99 } | 112 } |
100 else if (m_data.size ()) | 113 else if (m_data.size ()) |
101 { // No data allowed beyond Rx window allowed | 114 { // No data allowed beyond Rx window allowed |
102 return m_data.begin()->first + SequenceNumber (m_maxBuffer); | 115 return m_data.begin()->first + SequenceNumber32 (m_maxBuffer); |
103 } | 116 } |
104 return m_nextRxSeq + SequenceNumber (m_maxBuffer); | 117 return m_nextRxSeq + SequenceNumber32 (m_maxBuffer); |
105 } | 118 } |
106 | 119 |
107 void | 120 void |
108 TcpRxBuffer::SetFinSequence (const SequenceNumber& s) | 121 TcpRxBuffer::SetFinSequence (const SequenceNumber32& s) |
109 { | 122 { |
110 NS_LOG_FUNCTION (this); | 123 NS_LOG_FUNCTION (this); |
111 | 124 |
112 m_gotFin = true; | 125 m_gotFin = true; |
113 m_finSeq = s; | 126 m_finSeq = s; |
114 if (m_nextRxSeq == m_finSeq) ++m_nextRxSeq; | 127 if (m_nextRxSeq == m_finSeq) ++m_nextRxSeq; |
115 } | 128 } |
116 | 129 |
117 bool | 130 bool |
118 TcpRxBuffer::Finished (void) | 131 TcpRxBuffer::Finished (void) |
119 { | 132 { |
120 return (m_gotFin && m_finSeq < m_nextRxSeq); | 133 return (m_gotFin && m_finSeq < m_nextRxSeq); |
121 } | 134 } |
122 | 135 |
123 bool | 136 bool |
124 TcpRxBuffer::Add (Ptr<Packet> p, TcpHeader const& tcph) | 137 TcpRxBuffer::Add (Ptr<Packet> p, TcpHeader const& tcph) |
125 { | 138 { |
126 NS_LOG_FUNCTION (this << p << tcph); | 139 NS_LOG_FUNCTION (this << p << tcph); |
127 | 140 |
128 uint32_t pktSize = p->GetSize (); | 141 uint32_t pktSize = p->GetSize (); |
129 SequenceNumber headSeq = tcph.GetSequenceNumber (); | 142 SequenceNumber32 headSeq = tcph.GetSequenceNumber (); |
130 SequenceNumber tailSeq = headSeq + SequenceNumber (pktSize); | 143 SequenceNumber32 tailSeq = headSeq + SequenceNumber32 (pktSize); |
131 NS_LOG_LOGIC ("Add pkt " << p << " len=" << pktSize << " seq=" << headSeq | 144 NS_LOG_LOGIC ("Add pkt " << p << " len=" << pktSize << " seq=" << headSeq |
132 << ", when NextRxSeq=" << m_nextRxSeq << ", buffsize=" << m_size
); | 145 << ", when NextRxSeq=" << m_nextRxSeq << ", buffsize=" << m_size
); |
133 | 146 |
134 // Trim packet to fit Rx window specification | 147 // Trim packet to fit Rx window specification |
135 if (headSeq < m_nextRxSeq) headSeq = m_nextRxSeq; | 148 if (headSeq < m_nextRxSeq) headSeq = m_nextRxSeq; |
136 if (m_data.size ()) | 149 if (m_data.size ()) |
137 { | 150 { |
138 SequenceNumber maxSeq = m_data.begin ()->first + SequenceNumber (m_maxBuff
er); | 151 SequenceNumber32 maxSeq = m_data.begin ()->first + SequenceNumber32 (m_max
Buffer); |
139 if (maxSeq < tailSeq) tailSeq = maxSeq; | 152 if (maxSeq < tailSeq) tailSeq = maxSeq; |
140 if (tailSeq < headSeq) headSeq = tailSeq; | 153 if (tailSeq < headSeq) headSeq = tailSeq; |
141 } | 154 } |
142 // Remove overlapped bytes from packet | 155 // Remove overlapped bytes from packet |
143 BufIterator i = m_data.begin (); | 156 BufIterator i = m_data.begin (); |
144 while (i != m_data.end () && i->first <= tailSeq) | 157 while (i != m_data.end () && i->first <= tailSeq) |
145 { | 158 { |
146 SequenceNumber lastByteSeq = i->first + SequenceNumber (i->second->GetSize
()); | 159 SequenceNumber32 lastByteSeq = i->first + SequenceNumber32 (i->second->Get
Size ()); |
147 if (lastByteSeq > headSeq) | 160 if (lastByteSeq > headSeq) |
148 { | 161 { |
149 if (i->first > headSeq && lastByteSeq < tailSeq) | 162 if (i->first > headSeq && lastByteSeq < tailSeq) |
150 { // Rare case: Existing packet is embedded fully in the new packet | 163 { // Rare case: Existing packet is embedded fully in the new packet |
151 m_size -= i->second->GetSize(); | 164 m_size -= i->second->GetSize(); |
152 m_data.erase (i++); | 165 m_data.erase (i++); |
153 continue; | 166 continue; |
154 } | 167 } |
155 if (i->first <= headSeq) | 168 if (i->first <= headSeq) |
156 { // Incoming head is overlapped | 169 { // Incoming head is overlapped |
(...skipping 18 matching lines...) Expand all Loading... |
175 uint32_t length = tailSeq - headSeq; | 188 uint32_t length = tailSeq - headSeq; |
176 p = p->CreateFragment (start, length); | 189 p = p->CreateFragment (start, length); |
177 NS_ASSERT (length == p->GetSize ()); | 190 NS_ASSERT (length == p->GetSize ()); |
178 } | 191 } |
179 // Insert packet into buffer | 192 // Insert packet into buffer |
180 NS_ASSERT (m_data.find (headSeq) == m_data.end ()); // Shouldn't be there yet | 193 NS_ASSERT (m_data.find (headSeq) == m_data.end ()); // Shouldn't be there yet |
181 m_data [ headSeq ] = p; | 194 m_data [ headSeq ] = p; |
182 NS_LOG_LOGIC ("Buffered packet of seqno=" << headSeq << " len=" << p->GetSize
()); | 195 NS_LOG_LOGIC ("Buffered packet of seqno=" << headSeq << " len=" << p->GetSize
()); |
183 // Update variables | 196 // Update variables |
184 m_size += p->GetSize (); // Occupancy | 197 m_size += p->GetSize (); // Occupancy |
185 for (BufIterator i = m_data.begin (); i != m_data.end () && i->first == m_next
RxSeq; ++i) | 198 for (BufIterator i = m_data.begin (); i != m_data.end (); ++i) |
186 { | 199 { |
187 m_nextRxSeq = i->first + SequenceNumber (i->second->GetSize ()); | 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 ()); |
188 m_availBytes += i->second->GetSize (); | 209 m_availBytes += i->second->GetSize (); |
189 } | 210 } |
190 NS_LOG_LOGIC ("Updated buffer occupancy=" << m_size << " nextRxSeq=" << m_next
RxSeq); | 211 NS_LOG_LOGIC ("Updated buffer occupancy=" << m_size << " nextRxSeq=" << m_next
RxSeq); |
191 if (m_gotFin && m_nextRxSeq == m_finSeq) | 212 if (m_gotFin && m_nextRxSeq == m_finSeq) |
192 { // Account for the FIN packet | 213 { // Account for the FIN packet |
193 ++m_nextRxSeq; | 214 ++m_nextRxSeq; |
194 }; | 215 }; |
195 return true; | 216 return true; |
196 } | 217 } |
197 | 218 |
(...skipping 18 matching lines...) Expand all Loading... |
216 { // Whole packet is extracted | 237 { // Whole packet is extracted |
217 outPkt->AddAtEnd (i->second); | 238 outPkt->AddAtEnd (i->second); |
218 m_data.erase (i); | 239 m_data.erase (i); |
219 m_size -= pktSize; | 240 m_size -= pktSize; |
220 m_availBytes -= pktSize; | 241 m_availBytes -= pktSize; |
221 extractSize -= pktSize; | 242 extractSize -= pktSize; |
222 } | 243 } |
223 else | 244 else |
224 { // Partial is extracted and done | 245 { // Partial is extracted and done |
225 outPkt->AddAtEnd (i->second->CreateFragment (0, extractSize)); | 246 outPkt->AddAtEnd (i->second->CreateFragment (0, extractSize)); |
226 m_data[i->first + SequenceNumber (extractSize)] = i->second->CreateFra
gment (extractSize, pktSize - extractSize); | 247 m_data[i->first + SequenceNumber32 (extractSize)] = i->second->CreateF
ragment (extractSize, pktSize - extractSize); |
227 m_data.erase (i); | 248 m_data.erase (i); |
228 m_size -= extractSize; | 249 m_size -= extractSize; |
229 m_availBytes -= extractSize; | 250 m_availBytes -= extractSize; |
230 extractSize = 0; | 251 extractSize = 0; |
231 } | 252 } |
232 } | 253 } |
233 if (outPkt->GetSize () == 0) | 254 if (outPkt->GetSize () == 0) |
234 { | 255 { |
235 NS_LOG_LOGIC ("Nothing extracted."); | 256 NS_LOG_LOGIC ("Nothing extracted."); |
236 return 0; | 257 return 0; |
237 } | 258 } |
238 NS_LOG_LOGIC ("Extracted " << outPkt->GetSize( ) << " bytes, bufsize=" << m_si
ze | 259 NS_LOG_LOGIC ("Extracted " << outPkt->GetSize( ) << " bytes, bufsize=" << m_si
ze |
239 << ", num pkts in buffer=" << m_data.size ()); | 260 << ", num pkts in buffer=" << m_data.size ()); |
240 return outPkt; | 261 return outPkt; |
241 } | 262 } |
242 | 263 |
243 } //namepsace ns3 | 264 } //namepsace ns3 |
LEFT | RIGHT |