diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index f845f2c56..39abdf92a 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -2847,7 +2847,7 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with isRetransmission = true; } - Ptr p = m_txBuffer->CopyFromSequence (maxSize, seq); + Ptr p = m_txBuffer->CopyFromSequence (maxSize, seq)->GetPacketCopy (); uint32_t sz = p->GetSize (); // Size of packet uint8_t flags = withAck ? TcpHeader::ACK : 0; uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz)); @@ -3595,7 +3595,7 @@ TcpSocketBase::PersistTimeout () { NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ()); m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s - Ptr p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence); + Ptr p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy (); m_txBuffer->ResetLastSegmentSent (); TcpHeader tcpHeader; tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence); diff --git a/src/internet/model/tcp-tx-buffer.cc b/src/internet/model/tcp-tx-buffer.cc index bb1c17e24..735f298bb 100644 --- a/src/internet/model/tcp-tx-buffer.cc +++ b/src/internet/model/tcp-tx-buffer.cc @@ -32,45 +32,6 @@ namespace ns3 { NS_LOG_COMPONENT_DEFINE ("TcpTxBuffer"); - -void -TcpTxItem::Print (std::ostream &os) const -{ - bool comma = false; - os << "[" << m_startSeq << ";" << m_startSeq + GetSeqSize () << "|" - << GetSeqSize () << "]"; - - if (m_lost) - { - os << "[lost]"; - comma = true; - } - if (m_retrans) - { - if (comma) - { - os << ","; - } - - os << "[retrans]"; - comma = true; - } - if (m_sacked) - { - if (comma) - { - os << ","; - } - os << "[sacked]"; - comma = true; - } - if (comma) - { - os << ","; - } - os << "[" << m_lastSent.GetSeconds () << "]"; -} - NS_OBJECT_ENSURE_REGISTERED (TcpTxBuffer); TypeId @@ -155,6 +116,36 @@ TcpTxBuffer::Available (void) const return m_maxBuffer - m_size; } +void +TcpTxBuffer::SetDupAckThresh (uint32_t dupAckThresh) +{ + m_dupAckThresh = dupAckThresh; +} + +void +TcpTxBuffer::SetSegmentSize (uint32_t segmentSize) +{ + m_segmentSize = segmentSize; +} + +uint32_t +TcpTxBuffer::GetRetransmitsCount (void) const +{ + return m_retrans; +} + +uint32_t +TcpTxBuffer::GetLost (void) const +{ + return m_lostOut; +} + +uint32_t +TcpTxBuffer::GetSacked (void) const +{ + return m_sackedOut; +} + void TcpTxBuffer::SetHeadSequence (const SequenceNumber32& seq) { @@ -212,7 +203,7 @@ TcpTxBuffer::SizeFromSequence (const SequenceNumber32& seq) const return 0; } -Ptr +TcpTxItem * TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq) { NS_LOG_FUNCTION (this << numBytes << seq); @@ -226,7 +217,7 @@ TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq) if (s == 0) { - return Create (); + return nullptr; } TcpTxItem *outItem = nullptr; @@ -265,14 +256,11 @@ TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq) } outItem->m_lastSent = Simulator::Now (); - Ptr toRet = outItem->m_packet->Copy (); - - NS_ASSERT (toRet->GetSize () <= s); NS_ASSERT_MSG (outItem->m_startSeq >= m_firstByteSeq, "Returning an item " << *outItem << " with SND.UNA as " << m_firstByteSeq); ConsistencyCheck (); - return toRet; + return outItem; } TcpTxItem* @@ -671,7 +659,7 @@ TcpTxBuffer::DiscardUpTo (const SequenceNumber32& seq) if (i == m_sentList.end ()) { // Move data from app list to sent list, so we can delete the item - Ptr p = CopyFromSequence (offset, m_firstByteSeq); + Ptr p = CopyFromSequence (offset, m_firstByteSeq)->GetPacketCopy (); NS_ASSERT (p != nullptr); NS_UNUSED (p); i = m_sentList.begin (); @@ -1423,10 +1411,10 @@ operator<< (std::ostream & os, TcpTxBuffer const & tcpTxBuf) SequenceNumber32 beginOfCurrentPacket = tcpTxBuf.m_firstByteSeq; uint32_t sentSize = 0, appSize = 0; - Ptr p; + Ptr p; for (it = tcpTxBuf.m_sentList.begin (); it != tcpTxBuf.m_sentList.end (); ++it) { - p = (*it)->m_packet; + p = (*it)->GetPacket (); ss << "{"; (*it)->Print (ss); ss << "}"; @@ -1436,7 +1424,7 @@ operator<< (std::ostream & os, TcpTxBuffer const & tcpTxBuf) for (it = tcpTxBuf.m_appList.begin (); it != tcpTxBuf.m_appList.end (); ++it) { - appSize += (*it)->m_packet->GetSize (); + appSize += (*it)->GetPacket ()->GetSize (); } os << "Sent list: " << ss.str () << ", size = " << tcpTxBuf.m_sentList.size () << diff --git a/src/internet/model/tcp-tx-buffer.h b/src/internet/model/tcp-tx-buffer.h index ca8cdd945..c4cc87fa7 100644 --- a/src/internet/model/tcp-tx-buffer.h +++ b/src/internet/model/tcp-tx-buffer.h @@ -25,44 +25,12 @@ #include "ns3/object.h" #include "ns3/traced-value.h" #include "ns3/sequence-number.h" -#include "ns3/nstime.h" #include "ns3/tcp-option-sack.h" -#include "ns3/packet.h" +#include "ns3/tcp-tx-item.h" namespace ns3 { class Packet; -/** - * \ingroup tcp - * - * \brief Item that encloses the application packet and some flags for it - */ -class TcpTxItem -{ -public: - // Default constructor, copy-constructor, destructor - - /** - * \brief Print the time - * \param os ostream - */ - void Print (std::ostream &os) const; - - /** - * \brief Get the size in the sequence number space - * - * \return 1 if the packet size is 0 or there's no packet, otherwise the size of the packet - */ - uint32_t GetSeqSize (void) const { return m_packet && m_packet->GetSize () > 0 ? m_packet->GetSize () : 1; } - - SequenceNumber32 m_startSeq {0}; //!< Sequence number of the item (if transmitted) - Ptr m_packet {nullptr}; //!< Application packet (can be null) - bool m_lost {false}; //!< Indicates if the segment has been lost (RTO) - bool m_retrans {false}; //!< Indicates if the segment is retransmitted - Time m_lastSent {Time::Min()};//!< Timestamp of the time at which the segment has been sent last time - bool m_sacked {false}; //!< Indicates if the segment has been SACKed -}; - /** * \ingroup tcp * @@ -208,13 +176,13 @@ public: * \brief Set the DupAckThresh * \param dupAckThresh the threshold */ - void SetDupAckThresh (uint32_t dupAckThresh) { m_dupAckThresh = dupAckThresh; } + void SetDupAckThresh (uint32_t dupAckThresh); /** * \brief Set the segment size * \param segmentSize the segment size */ - void SetSegmentSize (uint32_t segmentSize) { m_segmentSize = segmentSize; } + void SetSegmentSize (uint32_t segmentSize); /** * \brief Return the number of segments in the sent list that @@ -225,7 +193,7 @@ public: * * \returns number of segments that have been transmitted more than once, without acknowledgment */ - uint32_t GetRetransmitsCount (void) const { return m_retrans; } + uint32_t GetRetransmitsCount (void) const; /** * \brief Get the number of segments that we believe are lost in the network @@ -233,13 +201,13 @@ public: * It is calculated in UpdateLostCount. * \return the number of lost segment */ - uint32_t GetLost (void) const { return m_lostOut; } + uint32_t GetLost (void) const; /** * \brief Get the number of segments that have been explicitly sacked by the receiver. * \return the number of sacked segment. */ - uint32_t GetSacked (void) const { return m_sackedOut; } + uint32_t GetSacked (void) const; /** * \brief Append a data packet to the end of the buffer @@ -274,9 +242,10 @@ public: * * \param numBytes number of bytes to copy * \param seq start sequence number to extract - * \returns a packet + * \returns a pointer to the TcpTxItem that corresponds to what requested. + * Please do not delete the pointer, nor modify Packet data or sequence numbers. */ - Ptr CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq); + TcpTxItem* CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq); /** * \brief Set the head sequence of the buffer diff --git a/src/internet/model/tcp-tx-item.cc b/src/internet/model/tcp-tx-item.cc new file mode 100644 index 000000000..2d38d057c --- /dev/null +++ b/src/internet/model/tcp-tx-item.cc @@ -0,0 +1,104 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2018 Natale Patriciello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "tcp-tx-item.h" + +namespace ns3 { + +void +TcpTxItem::Print (std::ostream &os) const +{ + bool comma = false; + os << "[" << m_startSeq << ";" << m_startSeq + GetSeqSize () << "|" + << GetSeqSize () << "]"; + + if (m_lost) + { + os << "[lost]"; + comma = true; + } + if (m_retrans) + { + if (comma) + { + os << ","; + } + + os << "[retrans]"; + comma = true; + } + if (m_sacked) + { + if (comma) + { + os << ","; + } + os << "[sacked]"; + comma = true; + } + if (comma) + { + os << ","; + } + os << "[" << m_lastSent.GetSeconds () << "]"; +} + +uint32_t +TcpTxItem::GetSeqSize (void) const +{ + return m_packet && m_packet->GetSize () > 0 ? m_packet->GetSize () : 1; +} + +bool +TcpTxItem::IsSacked (void) const +{ + return m_sacked; +} + +bool +TcpTxItem::IsRetrans (void) const +{ + return m_retrans; +} + +Ptr +TcpTxItem::GetPacketCopy (void) const +{ + return m_packet->Copy (); +} + +Ptr +TcpTxItem::GetPacket (void) const +{ + return m_packet; +} + +const Time & +TcpTxItem::GetLastSent (void) const +{ + return m_lastSent; +} + +TcpTxItem::RateInformation & +TcpTxItem::GetRateInformation (void) +{ + return m_rateInfo; +} + + +} // namespace ns3 diff --git a/src/internet/model/tcp-tx-item.h b/src/internet/model/tcp-tx-item.h new file mode 100644 index 000000000..01615d52e --- /dev/null +++ b/src/internet/model/tcp-tx-item.h @@ -0,0 +1,115 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2018 Natale Patriciello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#pragma once + +#include "ns3/packet.h" +#include "ns3/nstime.h" +#include "ns3/sequence-number.h" + +namespace ns3 { +/** + * \ingroup tcp + * + * \brief Item that encloses the application packet and some flags for it + */ +class TcpTxItem +{ +public: + // Default constructor, copy-constructor, destructor + + /** + * \brief Print the time + * \param os ostream + */ + void Print (std::ostream &os) const; + + /** + * \brief Get the size in the sequence number space + * + * \return 1 if the packet size is 0 or there's no packet, otherwise the size of the packet + */ + uint32_t GetSeqSize (void) const; + + /** + * \brief Is the item sacked? + * \return true if the item is sacked, false otherwise + */ + bool IsSacked (void) const; + + /** + * \brief Is the item retransmitted? + * \return true if the item have been retransmitted + */ + bool IsRetrans (void) const; + + /** + * \brief Get a copy of the Packet underlying this item + * \return a copy of the Packet + */ + Ptr GetPacketCopy (void) const; + + /** + * \brief Get the Packet underlying this item + * \return a pointer to a const Packet + */ + Ptr GetPacket (void) const; + + /** + * \brief Get a reference to the time the packet was sent for the last time + * \return a reference to the last sent time + */ + const Time & GetLastSent (void) const; + + /** + * \brief Various rate-related information, can be accessed by TcpRateOps. + * + * Note: This is not enforced through C++, but you developer must honour + * this description. + */ + struct RateInformation + { + uint64_t m_delivered {0}; //!< Connection's delivered data at the time the packet was sent + Time m_deliveredTime {Time::Max ()};//!< Connection's delivered time at the time the packet was sent + Time m_firstSent {Time::Max ()};//!< Connection's first sent time at the time the packet was sent + bool m_isAppLimited {false}; //!< Connection's app limited at the time the packet was sent + }; + + /** + * \brief Get (to modify) the Rate Information of this item + * + * \return A reference to the rate information. + */ + RateInformation & GetRateInformation (void); + +private: + // Only TcpTxBuffer is allower to touch this part of the TcpTxItem, to manage + // its internal lists and counters + friend class TcpTxBuffer; + + SequenceNumber32 m_startSeq {0}; //!< Sequence number of the item (if transmitted) + Ptr m_packet {nullptr}; //!< Application packet (can be null) + bool m_lost {false}; //!< Indicates if the segment has been lost (RTO) + bool m_retrans {false}; //!< Indicates if the segment is retransmitted + Time m_lastSent {Time::Max ()};//!< Timestamp of the time at which the segment has been sent last time + bool m_sacked {false}; //!< Indicates if the segment has been SACKed + + RateInformation m_rateInfo; //!< Rate information of the item +}; + +} //namespace ns3 diff --git a/src/internet/test/tcp-ecn-test.cc b/src/internet/test/tcp-ecn-test.cc index 8671fb59a..602517e96 100644 --- a/src/internet/test/tcp-ecn-test.cc +++ b/src/internet/test/tcp-ecn-test.cc @@ -161,7 +161,7 @@ TcpSocketCongestedRouter::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize isRetransmission = true; } - Ptr p = m_txBuffer->CopyFromSequence (maxSize, seq); + Ptr p = m_txBuffer->CopyFromSequence (maxSize, seq)->GetPacketCopy (); uint32_t sz = p->GetSize (); // Size of packet uint8_t flags = withAck ? TcpHeader::ACK : 0; uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz)); diff --git a/src/internet/test/tcp-tx-buffer-test.cc b/src/internet/test/tcp-tx-buffer-test.cc index 17aeb337b..d9dfde29d 100644 --- a/src/internet/test/tcp-tx-buffer-test.cc +++ b/src/internet/test/tcp-tx-buffer-test.cc @@ -284,7 +284,7 @@ TcpTxBufferTestCase::TestNewBlock () NS_TEST_ASSERT_MSG_EQ (txBuf.BytesInFlight (), 0, "TxBuf miscalculates size of in flight segments"); - Ptr ret = txBuf.CopyFromSequence (100, SequenceNumber32 (1)); + Ptr ret = txBuf.CopyFromSequence (100, SequenceNumber32 (1))->GetPacketCopy (); NS_TEST_ASSERT_MSG_EQ (ret->GetSize (), 100, "Returned packet has different size than requested"); NS_TEST_ASSERT_MSG_EQ (txBuf.SizeFromSequence (SequenceNumber32 (1)), 100, @@ -303,7 +303,7 @@ TcpTxBufferTestCase::TestNewBlock () Ptr p2 = Create (100); txBuf.Add (p2); - ret = txBuf.CopyFromSequence (50, SequenceNumber32 (101)); + ret = txBuf.CopyFromSequence (50, SequenceNumber32 (101))->GetPacketCopy (); NS_TEST_ASSERT_MSG_EQ (ret->GetSize (), 50, "Returned packet has different size than requested"); NS_TEST_ASSERT_MSG_EQ (txBuf.SizeFromSequence (SequenceNumber32 (151)), 50, @@ -315,7 +315,7 @@ TcpTxBufferTestCase::TestNewBlock () Ptr p3 = Create (100); txBuf.Add (p3); - ret = txBuf.CopyFromSequence (70, SequenceNumber32 (151)); + ret = txBuf.CopyFromSequence (70, SequenceNumber32 (151))->GetPacketCopy (); NS_TEST_ASSERT_MSG_EQ (ret->GetSize (), 70, "Returned packet has different size than requested"); NS_TEST_ASSERT_MSG_EQ (txBuf.SizeFromSequence (SequenceNumber32 (221)), 80, @@ -323,7 +323,7 @@ TcpTxBufferTestCase::TestNewBlock () NS_TEST_ASSERT_MSG_EQ (txBuf.BytesInFlight (), 120, "TxBuf miscalculates size of in flight segments"); - ret = txBuf.CopyFromSequence (3000, SequenceNumber32 (221)); + ret = txBuf.CopyFromSequence (3000, SequenceNumber32 (221))->GetPacketCopy (); NS_TEST_ASSERT_MSG_EQ (ret->GetSize (), 80, "Returned packet has different size than requested"); NS_TEST_ASSERT_MSG_EQ (txBuf.SizeFromSequence (SequenceNumber32 (301)), 0, diff --git a/src/internet/wscript b/src/internet/wscript index 63e6b344e..3245b6f49 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -162,6 +162,7 @@ def build(bld): 'model/tcp-lp.cc', 'model/tcp-rx-buffer.cc', 'model/tcp-tx-buffer.cc', + 'model/tcp-tx-item.cc', 'model/tcp-option.cc', 'model/tcp-option-rfc793.cc', 'model/tcp-option-winscale.cc', @@ -402,6 +403,7 @@ def build(bld): 'model/tcp-socket-base.h', 'model/tcp-socket-state.h', 'model/tcp-tx-buffer.h', + 'model/tcp-tx-item.h', 'model/tcp-rx-buffer.h', 'model/tcp-recovery-ops.h', 'model/tcp-prr-recovery.h',