Bug 829 - TCP unbound memory problem (pending data)
authorJosh Pelkey <jpelkey@gatech.edu>
Sat, 27 Mar 2010 19:09:18 -0400
changeset 6163 cdabef59da08
parent 6162 c36d596775f3
child 6164 fbd5ec1d7a2f
Bug 829 - TCP unbound memory problem (pending data)
src/internet-stack/pending-data.cc
src/internet-stack/pending-data.h
src/internet-stack/tcp-socket-impl.cc
--- a/src/internet-stack/pending-data.cc	Sat Mar 27 14:07:36 2010 -0700
+++ b/src/internet-stack/pending-data.cc	Sat Mar 27 19:09:18 2010 -0400
@@ -220,4 +220,36 @@
   NS_LOG_FUNCTION (this << s << f << o);
   return CopyFromOffset (s, OffsetFromSeq(f,o));
 }
+
+uint32_t
+PendingData::RemoveToSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset)
+{
+  NS_LOG_FUNCTION (this << seqFront << seqOffset);
+  uint32_t count = OffsetFromSeq (seqFront, seqOffset);
+  NS_ASSERT_MSG (count <= size, "Trying to remove more data than in the buffer"); 
+  if (count == size)
+    {
+      Clear ();
+      return size;
+    }
+  // Remove whole packets, if possible, from the front of the data
+  // Do not perform buffer manipulations within packet; if a whole packet
+  // cannot be removed, leave it alone
+  std::vector<Ptr<Packet> >::iterator endI = data.begin ();
+  uint32_t current = 0;
+  // Any packet whose data has been completely acked can be removed
+  for (std::vector<Ptr<Packet> >::iterator dataI = data.begin (); dataI < data.end (); dataI++)
+    {
+      if (current + (*dataI)->GetSize () > count)
+        {
+          break;
+        }
+      current += (*dataI)->GetSize ();
+      ++endI;
+    }
+  data.erase (data.begin (), endI);
+  size -= current;
+  return current;
+}
+
 }//namepsace ns3
--- a/src/internet-stack/pending-data.h	Sat Mar 27 14:07:36 2010 -0700
+++ b/src/internet-stack/pending-data.h	Sat Mar 27 19:09:18 2010 -0400
@@ -92,6 +92,16 @@
   virtual Ptr<Packet> CopyFromOffset (uint32_t, uint32_t);  // Size, offset, ret packet
   // Copy data, size, offset specified by sequence difference
   virtual Ptr<Packet> CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
+  /**
+   * Permits object to clear any pending data between seqFront and 
+   * seqOffset - 1).  Callers should check the return value to determine
+   * whether any data was removed from the front.
+   *
+   * \param seqFront sequence number to start to try to remove from 
+   * \param seqOffset first sequence number in buffer that should be retained
+   * \return number of bytes from the front that were removed from the buffer
+   */
+  virtual uint32_t RemoveToSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset);
   PendingData*   Copy () const;          // Create a copy of this header
   PendingData*   CopyS (uint32_t);         // Copy with new size
   PendingData*   CopySD (uint32_t, uint8_t*); // Copy with new size, new data
--- a/src/internet-stack/tcp-socket-impl.cc	Sat Mar 27 14:07:36 2010 -0700
+++ b/src/internet-stack/tcp-socket-impl.cc	Sat Mar 27 19:09:18 2010 -0400
@@ -1511,6 +1511,11 @@
                         Simulator::GetDelayLeft (m_retxEvent)).GetSeconds());
           m_retxEvent.Cancel ();
         }
+      else if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) > 0)
+        {
+          // Remove from front, if possible
+          m_firstPendingSequence += m_pendingData->RemoveToSeq (m_firstPendingSequence, m_highestRxAck);
+        }
     }
   // Try to send more data
   SendPendingData (m_connected);