OLD | NEW |
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 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 } | 45 } |
46 | 46 |
47 /* A user is supposed to create a TcpSocket through a factory. In TcpSocket, | 47 /* A user is supposed to create a TcpSocket through a factory. In TcpSocket, |
48 * there are attributes SndBufSize and RcvBufSize to control the default Tx and | 48 * there are attributes SndBufSize and RcvBufSize to control the default Tx and |
49 * Rx window sizes respectively, with default of 128 KiByte. The attribute | 49 * Rx window sizes respectively, with default of 128 KiByte. The attribute |
50 * RcvBufSize is passed to TcpRxBuffer by TcpSocketBase::SetRcvBufSize() and in | 50 * RcvBufSize is passed to TcpRxBuffer by TcpSocketBase::SetRcvBufSize() and in |
51 * turn, TcpRxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value | 51 * turn, TcpRxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value |
52 * initialized below is insignificant. | 52 * initialized below is insignificant. |
53 */ | 53 */ |
54 TcpRxBuffer::TcpRxBuffer (uint32_t n) | 54 TcpRxBuffer::TcpRxBuffer (uint32_t n) |
55 : m_nextRxSeq (n), m_gotFin (false), m_size (0), m_maxBuffer (32768), m_availB
ytes (0) | 55 : m_nextRxSeq (n), |
| 56 m_gotFin (false), |
| 57 m_size (0), |
| 58 m_maxBuffer (32768), |
| 59 m_availBytes (0) |
56 { | 60 { |
57 } | 61 } |
58 | 62 |
59 TcpRxBuffer::~TcpRxBuffer () | 63 TcpRxBuffer::~TcpRxBuffer () |
60 { | 64 { |
61 } | 65 } |
62 | 66 |
63 SequenceNumber32 | 67 SequenceNumber32 |
64 TcpRxBuffer::NextRxSequence (void) const | 68 TcpRxBuffer::NextRxSequence (void) const |
65 { | 69 { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 return m_nextRxSeq + SequenceNumber32 (m_maxBuffer); | 125 return m_nextRxSeq + SequenceNumber32 (m_maxBuffer); |
122 } | 126 } |
123 | 127 |
124 void | 128 void |
125 TcpRxBuffer::SetFinSequence (const SequenceNumber32& s) | 129 TcpRxBuffer::SetFinSequence (const SequenceNumber32& s) |
126 { | 130 { |
127 NS_LOG_FUNCTION (this); | 131 NS_LOG_FUNCTION (this); |
128 | 132 |
129 m_gotFin = true; | 133 m_gotFin = true; |
130 m_finSeq = s; | 134 m_finSeq = s; |
131 if (m_nextRxSeq == m_finSeq) ++m_nextRxSeq; | 135 if (m_nextRxSeq == m_finSeq) |
| 136 { |
| 137 ++m_nextRxSeq; |
| 138 } |
132 } | 139 } |
133 | 140 |
134 bool | 141 bool |
135 TcpRxBuffer::Finished (void) | 142 TcpRxBuffer::Finished (void) |
136 { | 143 { |
137 return (m_gotFin && m_finSeq < m_nextRxSeq); | 144 return (m_gotFin && m_finSeq < m_nextRxSeq); |
138 } | 145 } |
139 | 146 |
140 bool | 147 bool |
141 TcpRxBuffer::Add (Ptr<Packet> p, TcpHeader const& tcph) | 148 TcpRxBuffer::Add (Ptr<Packet> p, TcpHeader const& tcph) |
142 { | 149 { |
143 NS_LOG_FUNCTION (this << p << tcph); | 150 NS_LOG_FUNCTION (this << p << tcph); |
144 | 151 |
145 uint32_t pktSize = p->GetSize (); | 152 uint32_t pktSize = p->GetSize (); |
146 SequenceNumber32 headSeq = tcph.GetSequenceNumber (); | 153 SequenceNumber32 headSeq = tcph.GetSequenceNumber (); |
147 SequenceNumber32 tailSeq = headSeq + SequenceNumber32 (pktSize); | 154 SequenceNumber32 tailSeq = headSeq + SequenceNumber32 (pktSize); |
148 NS_LOG_LOGIC ("Add pkt " << p << " len=" << pktSize << " seq=" << headSeq | 155 NS_LOG_LOGIC ("Add pkt " << p << " len=" << pktSize << " seq=" << headSeq |
149 << ", when NextRxSeq=" << m_nextRxSeq << ", buffsize=
" << m_size); | 156 << ", when NextRxSeq=" << m_nextRxSeq << ", buffsize=
" << m_size); |
150 | 157 |
151 // Trim packet to fit Rx window specification | 158 // Trim packet to fit Rx window specification |
152 if (headSeq < m_nextRxSeq) headSeq = m_nextRxSeq; | 159 if (headSeq < m_nextRxSeq) |
| 160 { |
| 161 headSeq = m_nextRxSeq; |
| 162 } |
153 if (m_data.size ()) | 163 if (m_data.size ()) |
154 { | 164 { |
155 SequenceNumber32 maxSeq = m_data.begin ()->first + SequenceNumber32 (m_max
Buffer); | 165 SequenceNumber32 maxSeq = m_data.begin ()->first + SequenceNumber32 (m_max
Buffer); |
156 if (maxSeq < tailSeq) tailSeq = maxSeq; | 166 if (maxSeq < tailSeq) |
157 if (tailSeq < headSeq) headSeq = tailSeq; | 167 { |
| 168 tailSeq = maxSeq; |
| 169 } |
| 170 if (tailSeq < headSeq) |
| 171 { |
| 172 headSeq = tailSeq; |
| 173 } |
158 } | 174 } |
159 // Remove overlapped bytes from packet | 175 // Remove overlapped bytes from packet |
160 BufIterator i = m_data.begin (); | 176 BufIterator i = m_data.begin (); |
161 while (i != m_data.end () && i->first <= tailSeq) | 177 while (i != m_data.end () && i->first <= tailSeq) |
162 { | 178 { |
163 SequenceNumber32 lastByteSeq = i->first + SequenceNumber32 (i->second->Get
Size ()); | 179 SequenceNumber32 lastByteSeq = i->first + SequenceNumber32 (i->second->Get
Size ()); |
164 if (lastByteSeq > headSeq) | 180 if (lastByteSeq > headSeq) |
165 { | 181 { |
166 if (i->first > headSeq && lastByteSeq < tailSeq) | 182 if (i->first > headSeq && lastByteSeq < tailSeq) |
167 { // Rare case: Existing packet is embedded fully in the new packet | 183 { // Rare case: Existing packet is embedded fully in the new packet |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 m_size += p->GetSize (); // Occupancy | 217 m_size += p->GetSize (); // Occupancy |
202 for (BufIterator i = m_data.begin (); i != m_data.end (); ++i) | 218 for (BufIterator i = m_data.begin (); i != m_data.end (); ++i) |
203 { | 219 { |
204 if (i->first < m_nextRxSeq) | 220 if (i->first < m_nextRxSeq) |
205 { | 221 { |
206 continue; | 222 continue; |
207 } | 223 } |
208 else if (i->first > m_nextRxSeq) | 224 else if (i->first > m_nextRxSeq) |
209 { | 225 { |
210 break; | 226 break; |
211 }; | 227 } |
212 m_nextRxSeq = i->first + SequenceNumber32 (i->second->GetSize ()); | 228 m_nextRxSeq = i->first + SequenceNumber32 (i->second->GetSize ()); |
213 m_availBytes += i->second->GetSize (); | 229 m_availBytes += i->second->GetSize (); |
214 } | 230 } |
215 NS_LOG_LOGIC ("Updated buffer occupancy=" << m_size << " nextRxSeq=" << m_next
RxSeq); | 231 NS_LOG_LOGIC ("Updated buffer occupancy=" << m_size << " nextRxSeq=" << m_next
RxSeq); |
216 if (m_gotFin && m_nextRxSeq == m_finSeq) | 232 if (m_gotFin && m_nextRxSeq == m_finSeq) |
217 { // Account for the FIN packet | 233 { // Account for the FIN packet |
218 ++m_nextRxSeq; | 234 ++m_nextRxSeq; |
219 }; | 235 } |
220 return true; | 236 return true; |
221 } | 237 } |
222 | 238 |
| 239 void |
| 240 TcpRxBuffer::GetIsolatedDataChunks (List& list) |
| 241 { |
| 242 NS_LOG_FUNCTION (this); |
| 243 |
| 244 // Search the receiving buffer to enlist blocks of data with |
| 245 // sequence number greater than the next expected sequence number |
| 246 for (BufIterator i = m_data.begin (); i != m_data.end (); ++i) |
| 247 { |
| 248 if (i->first < m_nextRxSeq) |
| 249 { |
| 250 continue; |
| 251 } |
| 252 else if (i->first > m_nextRxSeq) |
| 253 { |
| 254 list.push_back (std::make_pair (i->first, i->first + SequenceNumber32
(i->second->GetSize ()))); |
| 255 } |
| 256 } |
| 257 |
| 258 // Merge consecutive data blocks if needed |
| 259 List::iterator outer; |
| 260 List::iterator inner; |
| 261 bool isOuterChanged; |
| 262 List mergedList; |
| 263 |
| 264 if (list.size () > 1) |
| 265 { |
| 266 for (outer = list.begin (); outer != list.end (); ) |
| 267 { |
| 268 inner = outer; |
| 269 isOuterChanged = false; |
| 270 for (++inner; inner != list.end (); ) |
| 271 { |
| 272 if (outer->second == inner->first) |
| 273 { |
| 274 outer->second = inner->second; |
| 275 ++inner; |
| 276 } |
| 277 else |
| 278 { |
| 279 isOuterChanged = true; |
| 280 break; |
| 281 } |
| 282 } |
| 283 mergedList.push_back (std::make_pair (outer->first, outer->second)); |
| 284 NS_LOG_LOGIC ("Enlist an isolated chunk into SACK list: " << outer->fi
rst << " " << outer->second); |
| 285 |
| 286 if (isOuterChanged) |
| 287 { |
| 288 outer = inner; |
| 289 } |
| 290 else |
| 291 { |
| 292 break; |
| 293 } |
| 294 } |
| 295 list = mergedList; |
| 296 } |
| 297 } |
| 298 |
223 Ptr<Packet> | 299 Ptr<Packet> |
224 TcpRxBuffer::Extract (uint32_t maxSize) | 300 TcpRxBuffer::Extract (uint32_t maxSize) |
225 { | 301 { |
226 NS_LOG_FUNCTION (this << maxSize); | 302 NS_LOG_FUNCTION (this << maxSize); |
227 | 303 |
228 uint32_t extractSize = std::min (maxSize, m_availBytes); | 304 uint32_t extractSize = std::min (maxSize, m_availBytes); |
229 NS_LOG_LOGIC ("Requested to extract " << extractSize << " bytes from TcpRxBuff
er of size=" << m_size); | 305 NS_LOG_LOGIC ("Requested to extract " << extractSize << " bytes from TcpRxBuff
er of size=" << m_size); |
230 if (extractSize == 0) return 0; // No contiguous block to return | 306 if (extractSize == 0) |
| 307 { |
| 308 return 0; // No contiguous block to return |
| 309 } |
231 NS_ASSERT (m_data.size ()); // At least we have something to extract | 310 NS_ASSERT (m_data.size ()); // At least we have something to extract |
232 Ptr<Packet> outPkt = Create<Packet> (); // The packet that contains all the da
ta to return | 311 Ptr<Packet> outPkt = Create<Packet> (); // The packet that contains all the da
ta to return |
233 BufIterator i; | 312 BufIterator i; |
234 while (extractSize) | 313 while (extractSize) |
235 { // Check the buffered data for delivery | 314 { // Check the buffered data for delivery |
236 i = m_data.begin (); | 315 i = m_data.begin (); |
237 NS_ASSERT (i->first <= m_nextRxSeq); // in-sequence data expected | 316 NS_ASSERT (i->first <= m_nextRxSeq); // in-sequence data expected |
238 // Check if we send the whole pkt or just a partial | 317 // Check if we send the whole pkt or just a partial |
239 uint32_t pktSize = i->second->GetSize (); | 318 uint32_t pktSize = i->second->GetSize (); |
240 if (pktSize <= extractSize) | 319 if (pktSize <= extractSize) |
(...skipping 18 matching lines...) Expand all Loading... |
259 { | 338 { |
260 NS_LOG_LOGIC ("Nothing extracted."); | 339 NS_LOG_LOGIC ("Nothing extracted."); |
261 return 0; | 340 return 0; |
262 } | 341 } |
263 NS_LOG_LOGIC ("Extracted " << outPkt->GetSize ( ) << " bytes, bufsize=" << m_s
ize | 342 NS_LOG_LOGIC ("Extracted " << outPkt->GetSize ( ) << " bytes, bufsize=" << m_s
ize |
264 << ", num pkts in buffer=" << m_data.size ()); | 343 << ", num pkts in buffer=" << m_data.size ()); |
265 return outPkt; | 344 return outPkt; |
266 } | 345 } |
267 | 346 |
268 } //namepsace ns3 | 347 } //namepsace ns3 |
OLD | NEW |