A Discrete-Event Network Simulator
API
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 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("TcpTxBuffer");
34 
35 NS_OBJECT_ENSURE_REGISTERED (TcpTxBuffer);
36 
37 TypeId
39 {
40  static TypeId tid = TypeId ("ns3::TcpTxBuffer")
41  .SetParent<Object> ()
42  .SetGroupName ("Internet")
43  .AddConstructor<TcpTxBuffer> ()
44  .AddTraceSource ("UnackSequence",
45  "First unacknowledged sequence number (SND.UNA)",
47  "ns3::SequenceNumber32TracedValueCallback")
48  ;
49  return tid;
50 }
51 
52 /* A user is supposed to create a TcpSocket through a factory. In TcpSocket,
53  * there are attributes SndBufSize and RcvBufSize to control the default Tx and
54  * Rx window sizes respectively, with default of 128 KiByte. The attribute
55  * SndBufSize is passed to TcpTxBuffer by TcpSocketBase::SetSndBufSize() and in
56  * turn, TcpTxBuffer:SetMaxBufferSize(). Therefore, the m_maxBuffer value
57  * initialized below is insignificant.
58  */
60  : m_firstByteSeq (n), m_size (0), m_maxBuffer (32768), m_data (0)
61 {
62 }
63 
65 {
66 }
67 
70 {
71  return m_firstByteSeq;
72 }
73 
76 {
78 }
79 
80 uint32_t
81 TcpTxBuffer::Size (void) const
82 {
83  return m_size;
84 }
85 
86 uint32_t
88 {
89  return m_maxBuffer;
90 }
91 
92 void
94 {
95  m_maxBuffer = n;
96 }
97 
98 uint32_t
100 {
101  return m_maxBuffer - m_size;
102 }
103 
104 bool
106 {
107  NS_LOG_FUNCTION (this << p);
108  NS_LOG_LOGIC ("Packet of size " << p->GetSize () << " appending to window starting at "
109  << m_firstByteSeq << ", availSize="<< Available ());
110  if (p->GetSize () <= Available ())
111  {
112  if (p->GetSize () > 0)
113  {
114  m_data.push_back (p);
115  m_size += p->GetSize ();
116  NS_LOG_LOGIC ("Updated size=" << m_size << ", lastSeq=" << m_firstByteSeq + SequenceNumber32 (m_size));
117  }
118  return true;
119  }
120  NS_LOG_LOGIC ("Rejected. Not enough room to buffer packet.");
121  return false;
122 }
123 
124 uint32_t
126 {
127  NS_LOG_FUNCTION (this << seq);
128  // Sequence of last byte in buffer
130  // Non-negative size
131  NS_LOG_LOGIC ("HeadSeq=" << m_firstByteSeq << ", lastSeq=" << lastSeq << ", size=" << m_size <<
132  ", returns " << lastSeq - seq);
133  return lastSeq - seq;
134 }
135 
137 TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq)
138 {
139  NS_LOG_FUNCTION (this << numBytes << seq);
140  uint32_t s = std::min (numBytes, SizeFromSequence (seq)); // Real size to extract. Insure not beyond end of data
141  if (s == 0)
142  {
143  return Create<Packet> (); // Empty packet returned
144  }
145  if (m_data.size () == 0)
146  { // No actual data, just return dummy-data packet of correct size
147  return Create<Packet> (s);
148  }
149 
150  // Extract data from the buffer and return
151  uint32_t offset = seq - m_firstByteSeq.Get ();
152  uint32_t count = 0; // Offset of the first byte of a packet in the buffer
153  uint32_t pktSize = 0;
154  bool beginFound = false;
155  int pktCount = 0;
156  Ptr<Packet> outPacket;
157  NS_LOG_LOGIC ("There are " << m_data.size () << " number of packets in buffer");
158  for (BufIterator i = m_data.begin (); i != m_data.end (); ++i)
159  {
160  pktCount++;
161  pktSize = (*i)->GetSize ();
162  if (!beginFound)
163  { // Look for first fragment
164  if (count + pktSize > offset)
165  {
166  NS_LOG_LOGIC ("First byte found in packet #" << pktCount << " at buffer offset " << count
167  << ", packet len=" << pktSize);
168  beginFound = true;
169  uint32_t packetOffset = offset - count;
170  uint32_t fragmentLength = count + pktSize - offset;
171  if (fragmentLength >= s)
172  { // Data to be copied falls entirely in this packet
173  return (*i)->CreateFragment (packetOffset, s);
174  }
175  else
176  { // This packet only fulfills part of the request
177  outPacket = (*i)->CreateFragment (packetOffset, fragmentLength);
178  }
179  NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ());
180  }
181  }
182  else if (count + pktSize >= offset + s)
183  { // Last packet fragment found
184  NS_LOG_LOGIC ("Last byte found in packet #" << pktCount << " at buffer offset " << count
185  << ", packet len=" << pktSize);
186  uint32_t fragmentLength = offset + s - count;
187  Ptr<Packet> endFragment = (*i)->CreateFragment (0, fragmentLength);
188  outPacket->AddAtEnd (endFragment);
189  NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ());
190  break;
191  }
192  else
193  {
194  NS_LOG_LOGIC ("Appending to output the packet #" << pktCount << " of offset " << count << " len=" << pktSize);
195  outPacket->AddAtEnd (*i);
196  NS_LOG_LOGIC ("Output packet is now of size " << outPacket->GetSize ());
197  }
198  count += pktSize;
199  }
200  NS_ASSERT (outPacket->GetSize () == s);
201  return outPacket;
202 }
203 
204 void
206 {
207  NS_LOG_FUNCTION (this << seq);
208  m_firstByteSeq = seq;
209 }
210 
211 void
213 {
214  NS_LOG_FUNCTION (this << seq);
215  NS_LOG_LOGIC ("current data size=" << m_size << ", headSeq=" << m_firstByteSeq << ", maxBuffer=" << m_maxBuffer
216  << ", numPkts=" << m_data.size ());
217  // Cases do not need to scan the buffer
218  if (m_firstByteSeq >= seq) return;
219 
220  // Scan the buffer and discard packets
221  uint32_t offset = seq - m_firstByteSeq.Get (); // Number of bytes to remove
222  uint32_t pktSize;
223  NS_LOG_LOGIC ("Offset=" << offset);
224  BufIterator i = m_data.begin ();
225  while (i != m_data.end ())
226  {
227  if (offset > (*i)->GetSize ())
228  { // This packet is behind the seqnum. Remove this packet from the buffer
229  pktSize = (*i)->GetSize ();
230  m_size -= pktSize;
231  offset -= pktSize;
232  m_firstByteSeq += pktSize;
233  i = m_data.erase (i);
234  NS_LOG_LOGIC ("Removed one packet of size " << pktSize << ", offset=" << offset);
235  }
236  else if (offset > 0)
237  { // Part of the packet is behind the seqnum. Fragment
238  pktSize = (*i)->GetSize () - offset;
239  *i = (*i)->CreateFragment (offset, pktSize);
240  m_size -= offset;
241  m_firstByteSeq += offset;
242  NS_LOG_LOGIC ("Fragmented one packet by size " << offset << ", new size=" << pktSize);
243  break;
244  }
245  }
246  // Catching the case of ACKing a FIN
247  if (m_size == 0)
248  {
249  m_firstByteSeq = seq;
250  }
251  NS_LOG_LOGIC ("size=" << m_size << " headSeq=" << m_firstByteSeq << " maxBuffer=" << m_maxBuffer
252  <<" numPkts="<< m_data.size ());
253  NS_ASSERT (m_firstByteSeq == seq);
254 }
255 
256 } // namepsace ns3
uint32_t Size(void) const
Returns total number of bytes in this Tx buffer.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void DiscardUpTo(const SequenceNumber32 &seq)
Discard data up to but not including this sequence number.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
#define min(a, b)
Definition: 80211b.c:44
uint32_t SizeFromSequence(const SequenceNumber32 &seq) const
Returns the number of bytes from the buffer in the range [seq, tailSequence)
SequenceNumber32 HeadSequence(void) const
Returns the first byte's sequence number.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
uint32_t MaxBufferSize(void) const
Returns the Tx window size.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
T Get(void) const
Get the underlying value.
Definition: traced-value.h:218
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:228
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:313
TracedValue< SequenceNumber32 > m_firstByteSeq
Sequence number of the first byte in data (SND.UNA)
uint32_t m_size
Number of data bytes.
class for keeping the data sent by the application to the TCP socket, i.e.
Definition: tcp-tx-buffer.h:40
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
void SetMaxBufferSize(uint32_t n)
Set the Tx window size.
uint32_t Available(void) const
Returns the available capacity in this Tx window.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool Add(Ptr< Packet > p)
Append a data packet to the end of the buffer.
static TypeId GetTypeId(void)
Get the type ID.
uint32_t m_maxBuffer
Max number of data bytes in buffer (SND.WND)
A base class which provides memory management and object aggregation.
Definition: object.h:87
TcpTxBuffer(uint32_t n=0)
Constructor.
virtual ~TcpTxBuffer(void)
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
std::list< Ptr< Packet > >::iterator BufIterator
container for data stored in the buffer
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
SequenceNumber32 TailSequence(void) const
Returns the last byte's sequence number + 1.
std::list< Ptr< Packet > > m_data
Corresponding data (may be null)
void SetHeadSequence(const SequenceNumber32 &seq)
Set the m_firstByteSeq to seq.
Ptr< Packet > CopyFromSequence(uint32_t numBytes, const SequenceNumber32 &seq)
Copy data of size numBytes into a packet, data from the range [seq, seq+numBytes) ...