tcp: split TcpTxItem in its own header/implementation file

- CopyFromSequence returns a TcpTxItem
    Instead of returning a packet, TcpTxBuffer returns a pointer to
    an item in its list of sent packet. The caller can then use the
    packet stored inside, or have a look into the item properties
    (retrans, lost, sacked, etc).
This commit is contained in:
Natale Patriciello
2018-05-13 16:20:54 +02:00
committed by Tom Henderson
parent e82c68a1ae
commit e92c671f5e
8 changed files with 274 additions and 96 deletions

View File

@@ -2847,7 +2847,7 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
isRetransmission = true;
}
Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
Ptr<Packet> 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<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence);
Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy ();
m_txBuffer->ResetLastSegmentSent ();
TcpHeader tcpHeader;
tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence);

View File

@@ -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<Packet>
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<Packet> ();
return nullptr;
}
TcpTxItem *outItem = nullptr;
@@ -265,14 +256,11 @@ TcpTxBuffer::CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq)
}
outItem->m_lastSent = Simulator::Now ();
Ptr<Packet> 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<Packet> p = CopyFromSequence (offset, m_firstByteSeq);
Ptr<Packet> 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<Packet> p;
Ptr<const Packet> 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 () <<

View File

@@ -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<Packet> 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<Packet> CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq);
TcpTxItem* CopyFromSequence (uint32_t numBytes, const SequenceNumber32& seq);
/**
* \brief Set the head sequence of the buffer

View File

@@ -0,0 +1,104 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
*
* 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<Packet>
TcpTxItem::GetPacketCopy (void) const
{
return m_packet->Copy ();
}
Ptr<const Packet>
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

View File

@@ -0,0 +1,115 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
*
* 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<Packet> GetPacketCopy (void) const;
/**
* \brief Get the Packet underlying this item
* \return a pointer to a const Packet
*/
Ptr<const Packet> 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<Packet> 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

View File

@@ -161,7 +161,7 @@ TcpSocketCongestedRouter::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize
isRetransmission = true;
}
Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
Ptr<Packet> 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));

View File

@@ -284,7 +284,7 @@ TcpTxBufferTestCase::TestNewBlock ()
NS_TEST_ASSERT_MSG_EQ (txBuf.BytesInFlight (), 0,
"TxBuf miscalculates size of in flight segments");
Ptr<Packet> ret = txBuf.CopyFromSequence (100, SequenceNumber32 (1));
Ptr<Packet> 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<Packet> p2 = Create<Packet> (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<Packet> p3 = Create<Packet> (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,

View File

@@ -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',