25#include "ns3/packet.h" 
   26#include "ns3/simulator.h" 
   44                            .SetGroupName(
"Internet")
 
   46                            .AddTraceSource(
"UnackSequence",
 
   47                                            "First unacknowledged sequence number (SND.UNA)",
 
   49                                            "ns3::SequenceNumber32TracedValueCallback");
 
  184    NS_LOG_LOGIC(
"Try to append " << p->GetSize() << 
" bytes to window starting at " 
  188        if (p->GetSize() > 0)
 
  191            item->m_packet = p->Copy();
 
  200    NS_LOG_LOGIC(
"Rejected. Not enough room to buffer packet.");
 
  213        return static_cast<uint32_t>(lastSeq - seq);
 
  216    NS_LOG_ERROR(
"Requested a sequence beyond our space (" << seq << 
" > " << lastSeq
 
  217                                                           << 
"). Returning 0 for convenience.");
 
  227                    "Requested a sequence number which is not in the buffer anymore");
 
  247        NS_LOG_DEBUG(
"Returning already sent item " << *outItem << 
" from " << *
this);
 
  252                            "Requesting a piece of new data with an hole");
 
  259        NS_LOG_DEBUG(
"Returning new item " << *outItem << 
" from " << *
this);
 
  275                  "Returning an item " << *outItem << 
" with SND.UNA as " << 
m_firstByteSeq);
 
  313    bool listEdited = 
false;
 
  320        if ((*it)->m_startSeq == seq)
 
  328                if ((!(*next)->m_sacked) && ((*it)->m_lost == (*next)->m_lost))
 
  330                    s = std::min(s, (*it)->m_packet->GetSize() + (*next)->m_packet->GetSize());
 
  335                    s = std::min(s, (*it)->m_packet->GetSize());
 
  340                s = std::min(s, (*it)->m_packet->GetSize());
 
  357std::pair<TcpTxBuffer::PacketList::const_iterator, SequenceNumber32>
 
  371            ret = std::make_pair(it, beginOfCurrentPacket);
 
  382    NS_ASSERT(t1 != 
nullptr && t2 != 
nullptr);
 
  396    NS_LOG_INFO(
"Split of size " << size << 
" result: t1 " << *t1 << 
" t2 " << *t2);
 
  404                               bool* listEdited)
 const 
  438    auto it = 
list.begin();
 
  441    while (it != 
list.end())
 
  444        currentPacket = currentItem->
m_packet;
 
  447                                << 
" currentItem start: " << currentItem->
m_startSeq);
 
  452        if (seq < beginOfCurrentPacket + currentPacket->
GetSize())
 
  455            if (seq == beginOfCurrentPacket)
 
  458                outItem = currentItem;
 
  459                NS_LOG_INFO(
"Current packet starts at seq " << seq << 
" ends at " 
  460                                                            << seq + currentPacket->GetSize());
 
  462            else if (seq > beginOfCurrentPacket)
 
  467                NS_LOG_INFO(
"we are at " << beginOfCurrentPacket << 
" searching for " << seq
 
  468                                         << 
" and now we recurse because packet ends at " 
  469                                         << beginOfCurrentPacket + currentPacket->GetSize());
 
  471                SplitItems(firstPart, currentItem, seq - beginOfCurrentPacket);
 
  474                list.insert(it, firstPart);
 
  490            beginOfCurrentPacket += currentPacket->GetSize();
 
  501        if (seq + numBytes <= beginOfCurrentPacket + currentPacket->
GetSize())
 
  504            if (numBytes == currentPacket->GetSize())
 
  532            else if (numBytes < currentPacket->
GetSize())
 
  540                list.insert(it, firstPart);
 
  553            if (++it == 
list.end())
 
  557                NS_LOG_WARN(
"Cannot reach the end, but this case is covered " 
  558                            "with conditional statements inside CopyFromSequence." 
  559                            "Something has gone wrong, report a bug");
 
  589    NS_ASSERT(t1 != 
nullptr && t2 != 
nullptr);
 
  594                  "Merging one sacked and another not sacked. Impossible");
 
  644                      "Trying to remove " << size << 
" bytes from " << 
m_lostOut);
 
  683    while (
m_size > 0 && offset > 0)
 
  698                      "Item starts at " << item->
m_startSeq << 
" while SND.UNA is " 
  714            if (!beforeDelCb.
IsNull())
 
  736                                                         << 
" resulting item is " << *item
 
  737                                                         << 
" status: " << *
this);
 
  758            NS_LOG_INFO(
"Moving the SACK flag from the HEAD to another segment");
 
  764                      "While removing up to " << seq << 
" we get SND.UNA to " << 
m_firstByteSeq 
  765                                              << 
" this is the result: " << *
this);
 
  775    NS_LOG_LOGIC(
"Buffer status after discarding data " << *
this);
 
  785    NS_LOG_INFO(
"Updating scoreboard, got " << 
list.size() << 
" blocks to analyze");
 
  789    for (
auto option_it = 
list.begin(); option_it != 
list.end(); ++option_it)
 
  796            NS_LOG_INFO(
"Not updating scoreboard, the option block is outside the sent list");
 
  809            if (beginOfCurrentPacket >= (*option_it).first &&
 
  810                beginOfCurrentPacket + 
pktSize <= (*option_it).second)
 
  812                if ((*item_it)->m_sacked)
 
  815                    NS_LOG_INFO(
"Received block " << *option_it << 
", checking sentList for block " 
  817                                                  << 
", found in the sackboard already sacked");
 
  821                    if ((*item_it)->m_lost)
 
  823                        (*item_it)->m_lost = 
false;
 
  824                        m_lostOut -= (*item_it)->m_packet->GetSize();
 
  827                    (*item_it)->m_sacked = 
true;
 
  829                    bytesSacked += (*item_it)->m_packet->GetSize();
 
  834                        m_highestSack = std::make_pair(item_it, beginOfCurrentPacket);
 
  838                                << *option_it << 
", checking sentList for block " << *(*item_it)
 
  839                                << 
", found in the sackboard, sacking, current highSack: " 
  848            else if (beginOfCurrentPacket + 
pktSize > (*option_it).second)
 
  851                NS_LOG_INFO(
"Received block [" << *option_it << 
", checking sentList for block " 
  852                                               << *(*item_it) << 
"], not found, breaking loop");
 
  856            beginOfCurrentPacket += 
pktSize;
 
  884                                                 << 
", will start from the latest sent item");
 
  888        NS_LOG_INFO(
"Status before the update: " << *
this << 
", will start from item " 
  939        if ((*it)->m_startSeq <= seq && seq < (*it)->m_startSeq + (*it)->m_packet->GetSize())
 
  943                NS_LOG_INFO(
"seq=" << seq << 
" is lost because of lost flag");
 
  949                NS_LOG_INFO(
"seq=" << seq << 
" is not lost because of sacked flag");
 
  978    bool isSeqPerRule3Valid = 
false;
 
  990                NS_LOG_INFO(
"IsLost, returning" << beginOfCurrentPkt);
 
  991                *seq = beginOfCurrentPkt;
 
  995            else if (seqPerRule3.
GetValue() == 0 && isRecovery)
 
  997                NS_LOG_INFO(
"Saving for rule 3 the seq " << beginOfCurrentPkt);
 
  998                isSeqPerRule3Valid = 
true;
 
  999                seqPerRule3 = beginOfCurrentPkt;
 
 1024            NS_LOG_INFO(
"There is no available receiver window to send");
 
 1039    if (isSeqPerRule3Valid)
 
 1068                                     << 
" is out of sync with sent list size " << 
m_sentSize << 
" " 
 1104            bool isLost = 
IsLostRFC(beginOfCurrentPkt, it);
 
 1132                  "Lost counted: " << lostOut << 
" " << 
m_lostOut << 
"\n" 
 1135                  "Retrans Counted: " << retrans << 
" " << 
m_retrans << 
"\n" 
 1138                  "Sacked counted: " << sackedOut << 
" " << 
m_sackedOut << *
this);
 
 1140                  "Sent size counted: " << totalSize << 
" " << 
m_sentSize << *
this);
 
 1151    PacketList::const_iterator it;
 
 1156    if ((*segment)->m_sacked)
 
 1166    for (it = segment; it != 
m_sentList.end(); ++it)
 
 1173            NS_LOG_INFO(
"Segment " << *item << 
" found to be SACKed while checking for " << seq);
 
 1175            bytes += current->GetSize();
 
 1178                NS_LOG_INFO(
"seq=" << seq << 
" is lost because of 3 sacked blocks ahead");
 
 1190            NS_LOG_INFO(
"seq=" << seq << 
" is not lost because there are no sacked segment ahead");
 
 1194        beginOfCurrentPacket += current->GetSize();
 
 1198        NS_LOG_INFO(
"seq=" << seq << 
" is not lost because there are no sacked segment ahead " 
 1212        (*it)->m_sacked = 
false;
 
 1287            (*it)->m_sacked = 
false;
 
 1288            (*it)->m_lost = 
true;
 
 1295                m_lostOut += (*it)->m_packet->GetSize();
 
 1297            else if (!(*it)->m_sacked)
 
 1300                (*it)->m_lost = 
true;
 
 1301                m_lostOut += (*it)->m_packet->GetSize();
 
 1305        (*it)->m_retrans = 
false;
 
 1308    NS_LOG_INFO(
"Set sent list lost, status: " << *
this);
 
 1393    while (it != 
m_sentList.end() && (*it)->m_sacked)
 
 1401        (*it)->m_sacked = 
true;
 
 1404        NS_LOG_INFO(
"Added a Reno SACK, status: " << *
this);
 
 1408        NS_LOG_INFO(
"Can't add a Reno SACK because we miss segments. This dupack" 
 1409                    " should be arrived from spurious retransmissions");
 
 1418    static const bool enable = 
false;
 
 1431        if ((*it)->m_sacked)
 
 1433            sacked += (*it)->m_packet->GetSize();
 
 1437            lost += (*it)->m_packet->GetSize();
 
 1439        if ((*it)->m_retrans)
 
 1441            retrans += (*it)->m_packet->GetSize();
 
 1446                  "Counted SACK: " << sacked << 
" stored SACK: " << 
m_sackedOut);
 
 1449                  " Counted retrans: " << retrans << 
" stored retrans: " << 
m_retrans);
 
 1462    std::stringstream ss;
 
 1470        p = (*it)->GetPacket();
 
 1474        sentSize += p->GetSize();
 
 1475        beginOfCurrentPacket += p->GetSize();
 
 1480        appSize += (*it)->GetPacket()->GetSize();
 
 1483    os << 
"Sent list: " << ss.str() << 
", size = " << tcpTxBuf.
m_sentList.size()
 
bool IsNull() const
Check for null implementation.
 
A base class which provides memory management and object aggregation.
 
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
 
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
 
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
 
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
 
Smart pointer class similar to boost::intrusive_ptr.
 
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
 
static Time Now()
Return the current simulation virtual time.
 
std::list< SackBlock > SackList
SACK list definition.
 
uint32_t m_retrans
Number of retransmitted bytes.
 
void ResetRenoSack()
Reset the SACKs.
 
void ConsistencyCheck() const
Check if the values of sacked, lost, retrans, are in sync with the sent list.
 
bool m_sackEnabled
Indicates if SACK is enabled on this connection.
 
uint32_t m_lostOut
Number of lost bytes.
 
bool IsLostRFC(const SequenceNumber32 &seq, const PacketList::const_iterator &segment) const
Decide if a segment is lost based on RFC 6675 algorithm.
 
std::pair< TcpTxBuffer::PacketList::const_iterator, SequenceNumber32 > FindHighestSacked() const
Find the highest SACK byte.
 
SequenceNumber32 HeadSequence() const
Get the sequence number of the buffer head.
 
std::pair< PacketList::const_iterator, SequenceNumber32 > m_highestSack
Highest SACK byte.
 
bool IsHeadRetransmitted() const
Check if the head is retransmitted.
 
bool Add(Ptr< Packet > p)
Append a data packet to the end of the buffer.
 
void SetSegmentSize(uint32_t segmentSize)
Set the segment size.
 
uint32_t GetRetransmitsCount() const
Return the number of segments in the sent list that have been transmitted more than once,...
 
bool IsRetransmittedDataAcked(const SequenceNumber32 &ack) const
Checks whether the ack corresponds to retransmitted data.
 
static TypeId GetTypeId()
Get the type ID.
 
TcpTxItem * GetPacketFromList(PacketList &list, const SequenceNumber32 &startingSeq, uint32_t numBytes, const SequenceNumber32 &requestedSeq, bool *listEdited=nullptr) const
Get a block (which is returned as Packet) from a list.
 
uint32_t SizeFromSequence(const SequenceNumber32 &seq) const
Returns the number of bytes from the buffer in the range [seq, tailSequence)
 
TracedValue< SequenceNumber32 > m_firstByteSeq
Sequence number of the first byte in data (SND.UNA)
 
std::list< TcpTxItem * > PacketList
container for data stored in the buffer
 
uint32_t MaxBufferSize() const
Get the maximum buffer size.
 
TcpTxItem * GetTransmittedSegment(uint32_t numBytes, const SequenceNumber32 &seq)
Get a block of data previously transmitted.
 
uint32_t m_maxBuffer
Max number of data bytes in buffer (SND.WND)
 
bool m_renoSack
Indicates if AddRenoSack was called.
 
uint32_t m_dupAckThresh
Duplicate Ack threshold from TcpSocketBase.
 
uint32_t Size() const
Returns total number of bytes in this buffer.
 
void SetSackEnabled(bool enabled)
tell tx-buffer whether SACK is used on this TCP socket
 
static Callback< void, TcpTxItem * > m_nullCb
Null callback for an item.
 
uint32_t m_sackedOut
Number of sacked bytes.
 
void ResetLastSegmentSent()
Take the last segment sent and put it back into the un-sent list (at the beginning)
 
bool IsLost(const SequenceNumber32 &seq) const
Check if a segment is lost.
 
bool NextSeg(SequenceNumber32 *seq, SequenceNumber32 *seqHigh, bool isRecovery) const
Get the next sequence number to transmit, according to RFC 6675.
 
void SetDupAckThresh(uint32_t dupAckThresh)
Set the DupAckThresh.
 
TcpTxItem * CopyFromSequence(uint32_t numBytes, const SequenceNumber32 &seq)
Copy data from the range [seq, seq+numBytes) into a packet.
 
bool IsSackEnabled() const
check whether SACK is used on the corresponding TCP socket
 
TcpTxItem * GetNewSegment(uint32_t numBytes)
Get a block of data not transmitted yet and move it into SentList.
 
uint32_t Available() const
Returns the available capacity of this buffer.
 
uint32_t m_segmentSize
Segment size from TcpSocketBase.
 
uint32_t Update(const TcpOptionSack::SackList &list, const Callback< void, TcpTxItem * > &sackedCb=m_nullCb)
Update the scoreboard.
 
uint32_t GetLost() const
Get the number of segments that we believe are lost in the network.
 
void AddRenoSack()
Emulate SACKs for SACKless connection: account for a new dupack.
 
void MarkHeadAsLost()
Mark the head of the sent list as lost.
 
void UpdateLostCount()
Update the lost count.
 
SequenceNumber32 TailSequence() const
Get the sequence number of the buffer tail (plus one)
 
Callback< uint32_t > m_rWndCallback
Callback to obtain RCV.WND value.
 
void SetRWndCallback(Callback< uint32_t > rWndCallback)
Set callback to obtain receiver window value.
 
uint32_t BytesInFlight() const
Return total bytes in flight.
 
void SetSentListLost(bool resetSack=false)
Set the entire sent list as lost (typically after an RTO)
 
void SplitItems(TcpTxItem *t1, TcpTxItem *t2, uint32_t size) const
Split one TcpTxItem.
 
void DiscardUpTo(const SequenceNumber32 &seq, const Callback< void, TcpTxItem * > &beforeDelCb=m_nullCb)
Discard data up to but not including this sequence number.
 
uint32_t BytesInFlightRFC() const
Calculate the number of bytes in flight per RFC 6675.
 
PacketList m_appList
Buffer for application data.
 
uint32_t GetSacked() const
Get the number of segments that have been explicitly sacked by the receiver.
 
void MergeItems(TcpTxItem *t1, TcpTxItem *t2) const
Merge two TcpTxItem.
 
uint32_t m_size
Size of all data in this buffer.
 
void ResetSentList()
Reset the sent list.
 
void DeleteRetransmittedFlagFromHead()
DeleteRetransmittedFlagFromHead.
 
void SetMaxBufferSize(uint32_t n)
Set the maximum buffer size.
 
PacketList m_sentList
Buffer for sent (but not acked) data.
 
uint32_t m_sentSize
Size of sent (and not discarded) segments.
 
void RemoveFromCounts(TcpTxItem *item, uint32_t size)
Remove the size specified from the lostOut, retrans, sacked count.
 
void SetHeadSequence(const SequenceNumber32 &seq)
Set the head sequence of the buffer.
 
TcpTxBuffer(uint32_t n=0)
Constructor.
 
Item that encloses the application packet and some flags for it.
 
bool m_sacked
Indicates if the segment has been SACKed.
 
bool m_retrans
Indicates if the segment is retransmitted.
 
SequenceNumber32 m_startSeq
Sequence number of the item (if transmitted)
 
Time m_lastSent
Timestamp of the time at which the segment has been sent last time.
 
Ptr< Packet > GetPacketCopy() const
Get a copy of the Packet underlying this item.
 
bool m_lost
Indicates if the segment has been lost (RTO)
 
Ptr< Packet > m_packet
Application packet (can be null)
 
void Print(std::ostream &os, Time::Unit unit=Time::S) const
Print the time.
 
T Get() const
Get the underlying value.
 
a unique identifier for an interface.
 
TypeId SetParent(TypeId tid)
Set the parent TypeId.
 
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
 
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
 
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
 
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
 
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
 
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
 
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
 
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
 
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
 
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
 
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
 
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
 
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
 
Every class exported by the ns3 library is enclosed in the ns3 namespace.
 
std::ostream & operator<<(std::ostream &os, const Angles &a)
 
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added.
 
uint32_t pktSize
packet size used for the simulation (in bytes)