25 #include "ns3/packet.h" 
   27 #include "ns3/abort.h" 
   28 #include "ns3/tcp-option-ts.h" 
   81     .SetGroupName (
"Internet")
 
   83     .AddTraceSource (
"UnackSequence",
 
   84                      "First unacknowledged sequence number (SND.UNA)",
 
   86                      "ns3::SequenceNumber32TracedValueCallback")
 
   99   : m_maxBuffer (32768), m_size (0), m_sentSize (0), m_firstByteSeq (n)
 
  105   PacketList::iterator it;
 
  194   NS_LOG_LOGIC (
"Rejected. Not enough room to buffer packet.");
 
  207       return static_cast<uint32_t
> (lastSeq - seq);
 
  210   NS_LOG_ERROR (
"Requested a sequence beyond our space (" << seq << 
" > " << lastSeq <<
 
  211                 "). Returning 0 for convenience.");
 
  221                    "Requested a sequence number which is not in the buffer anymore");
 
  229       return Create<Packet> ();
 
  241       NS_LOG_DEBUG (
"Returning already sent item " << *outItem << 
" from " << *
this);
 
  246                            "Requesting a piece of new data with an hole");
 
  253       NS_LOG_DEBUG (
"Returning new item " << *outItem << 
" from " << *
this);
 
  272                  "Returning an item " << *outItem << 
" with SND.UNA as " <<
 
  285   NS_LOG_INFO (
"AppList start at " << startOfAppList << 
", sentSize = " <<
 
  289                                        numBytes, startOfAppList);
 
  312   bool listEdited = 
false;
 
  313   uint32_t s = numBytes;
 
  319       if ((*it)->m_startSeq == seq)
 
  326               if (! (*next)->m_sacked)
 
  328                   s = 
std::min(s, (*it)->m_packet->GetSize () + (*next)->m_packet->GetSize ());
 
  333                   s = 
std::min(s, (*it)->m_packet->GetSize ());
 
  338               s = 
std::min(s, (*it)->m_packet->GetSize ());
 
  355 std::pair <TcpTxBuffer::PacketList::const_iterator, SequenceNumber32>
 
  369           ret = std::make_pair (it, beginOfCurrentPacket);
 
  381   NS_ASSERT (t1 != 
nullptr && t2 != 
nullptr);
 
  395   NS_LOG_INFO (
"Split of size " << size << 
" result: t1 " << *t1 << 
" t2 " << *t2);
 
  401                                 bool *listEdited)
 const 
  435   PacketList::iterator it = list.begin ();
 
  438   while (it != list.end ())
 
  441       currentPacket = currentItem->
m_packet;
 
  449       if (seq < beginOfCurrentPacket + currentPacket->
GetSize ())
 
  452           if (seq == beginOfCurrentPacket)
 
  455               outItem = currentItem;
 
  456               NS_LOG_INFO (
"Current packet starts at seq " << seq <<
 
  457                            " ends at " << seq + currentPacket->
GetSize ());
 
  459           else if (seq > beginOfCurrentPacket)
 
  464               NS_LOG_INFO (
"we are at " << beginOfCurrentPacket <<
 
  465                            " searching for " << seq <<
 
  466                            " and now we recurse because packet ends at " 
  467                                         << beginOfCurrentPacket + currentPacket->
GetSize ());
 
  469               SplitItems (firstPart, currentItem, seq - beginOfCurrentPacket);
 
  472               list.insert (it, firstPart);
 
  482               NS_FATAL_ERROR (
"seq < beginOfCurrentPacket: our data is before");
 
  488           beginOfCurrentPacket += currentPacket->
GetSize ();
 
  499       if (seq + numBytes <= beginOfCurrentPacket + currentPacket->
GetSize ())
 
  502           if (numBytes == currentPacket->
GetSize ())
 
  530           else if (numBytes < currentPacket->
GetSize ())
 
  535               SplitItems (firstPart, currentItem, numBytes);
 
  538               list.insert (it, firstPart);
 
  551           if (++it == list.end ())
 
  555               NS_LOG_WARN (
"Cannot reach the end, but this case is covered " 
  556                            "with conditional statements inside CopyFromSequence." 
  557                            "Something has gone wrong, report a bug");
 
  585   return first ? second : !second;
 
  591   NS_ASSERT (t1 != 
nullptr && t2 != 
nullptr);
 
  593   NS_LOG_INFO (
"Merging " << *t2 << 
" into " << *t1);
 
  596                  "Merging one sacked and another not sacked. Impossible");
 
  598                  "Merging one lost and another not lost. Impossible");
 
  627   NS_LOG_INFO (
"Situation after the merge: " << *t1);
 
  669   while (
m_size > 0 && offset > 0)
 
  687       if (offset >= pktSize)
 
  699                        ". Remaining data " << 
m_size);
 
  715           NS_LOG_INFO (
"Fragmented one packet by size " << offset <<
 
  716                        ", new size=" << pktSize << 
" resulting item is " <<
 
  717                        *item << 
" status: " << *
this);
 
  738           NS_LOG_INFO (
"Moving the SACK flag from the HEAD to another segment");
 
  744                      "While removing up to " << seq << 
" we get SND.UNA to " <<
 
  755   NS_LOG_LOGIC (
"Buffer status after discarding data " << *
this);
 
  765   NS_LOG_INFO (
"Updating scoreboard, got " << list.size () << 
" blocks to analyze");
 
  767   bool modified = 
false;
 
  769   for (
auto option_it = list.begin (); option_it != list.end (); ++option_it)
 
  771       PacketList::iterator item_it = 
m_sentList.begin ();
 
  776           NS_LOG_INFO (
"Not updating scoreboard, the option block is outside the sent list");
 
  782           uint32_t pktSize = (*item_it)->m_packet->GetSize ();
 
  789           if (beginOfCurrentPacket >= (*option_it).first
 
  790               && beginOfCurrentPacket + pktSize <= (*option_it).second)
 
  792               if ((*item_it)->m_sacked)
 
  796                                ", checking sentList for block " << *(*item_it) <<
 
  797                                ", found in the sackboard already sacked");
 
  801                   if ((*item_it)->m_lost)
 
  803                       (*item_it)->m_lost = 
false;
 
  804                       m_lostOut -= (*item_it)->m_packet->GetSize ();
 
  807                   (*item_it)->m_sacked = 
true;
 
  813                       m_highestSack = std::make_pair (item_it, beginOfCurrentPacket);
 
  817                                ", checking sentList for block " << *(*item_it) <<
 
  818                                ", found in the sackboard, sacking, current highSack: " <<
 
  823           else if (beginOfCurrentPacket + pktSize > (*option_it).second)
 
  827                            ", checking sentList for block " << *(*item_it) <<
 
  828                            "], not found, breaking loop");
 
  832           beginOfCurrentPacket += pktSize;
 
  859       NS_LOG_INFO (
"Status before the update: " << *
this <<
 
  860                    ", will start from the latest sent item");
 
  864       NS_LOG_INFO (
"Status before the update: " << *
this <<
 
  896   NS_LOG_INFO (
"Status after the update: " << *
this);
 
  906   PacketList::const_iterator it;
 
  918       if (beginOfCurrentPacket >= seq)
 
  920           if ((*it)->m_lost == 
true)
 
  922               NS_LOG_INFO (
"seq=" << seq << 
" is lost because of lost flag");
 
  926           if ((*it)->m_sacked == 
true)
 
  928               NS_LOG_INFO (
"seq=" << seq << 
" is not lost because of sacked flag");
 
  933       beginOfCurrentPacket += (*it)->m_packet->GetSize ();
 
  957   PacketList::const_iterator it;
 
  960   bool isSeqPerRule3Valid = 
false;
 
  972               NS_LOG_INFO(
"IsLost, returning" << beginOfCurrentPkt);
 
  973               *seq = beginOfCurrentPkt;
 
  976           else if (seqPerRule3.
GetValue () == 0 && isRecovery)
 
  978               NS_LOG_INFO (
"Saving for rule 3 the seq " << beginOfCurrentPkt);
 
  979               isSeqPerRule3Valid = 
true;
 
  980               seqPerRule3 = beginOfCurrentPkt;
 
 1011   if (isSeqPerRule3Valid)
 
 1039                  " is out of sync with sent list size " << 
m_sentSize <<
 
 1045                " retrans: " << retrans);
 
 1046   uint32_t in_flight = 
m_sentSize - leftOut + retrans;
 
 1059   PacketList::const_iterator it;
 
 1063   uint32_t sackedOut = 0;
 
 1064   uint32_t lostOut = 0;
 
 1065   uint32_t retrans = 0;
 
 1066   uint32_t totalSize = 0;
 
 1077           bool isLost = 
IsLostRFC (beginOfCurrentPkt, it);
 
 1115                 "Sent size counted: " << totalSize << 
" " << 
m_sentSize << *
this);
 
 1126   PacketList::const_iterator it;
 
 1131   if ((*segment)->m_sacked == 
true)
 
 1141   for (it = segment; it != 
m_sentList.end (); ++it)
 
 1149                        " found to be SACKed while checking for " << seq);
 
 1154               NS_LOG_INFO (
"seq=" << seq << 
" is lost because of 3 sacked blocks ahead");
 
 1164           NS_LOG_INFO (
"seq=" << seq << 
" is not lost because there are no sacked segment ahead");
 
 1168       beginOfCurrentPacket += current->
GetSize ();
 
 1185       (*it)->m_sacked = 
false;
 
 1253           (*it)->m_sacked = 
false;
 
 1254           (*it)->m_lost = 
true;
 
 1261               m_lostOut += (*it)->m_packet->GetSize ();
 
 1263           else if (!(*it)->m_sacked)
 
 1266               (*it)->m_lost = 
true;
 
 1267               m_lostOut += (*it)->m_packet->GetSize ();
 
 1271       (*it)->m_retrans = 
false;
 
 1274   NS_LOG_INFO (
"Set sent list lost, status: " << *
this);
 
 1351   while (it != 
m_sentList.end () && (*it)->m_sacked)
 
 1359       (*it)->m_sacked = 
true;
 
 1362       NS_LOG_INFO (
"Added a Reno SACK, status: " << *
this);
 
 1366       NS_LOG_INFO (
"Can't add a Reno SACK because we miss segments. This dupack" 
 1367                    " should be arrived from spurious retransmissions");
 
 1376   static const bool enable = 
false;
 
 1383   uint32_t sacked = 0;
 
 1385   uint32_t retrans = 0;
 
 1389       if ((*it)->m_sacked)
 
 1391           sacked += (*it)->m_packet->GetSize ();
 
 1395           lost += (*it)->m_packet->GetSize ();
 
 1397       if ((*it)->m_retrans)
 
 1399           retrans += (*it)->m_packet->GetSize ();
 
 1421   TcpTxBuffer::PacketList::const_iterator it;
 
 1422   std::stringstream ss;
 
 1424   uint32_t sentSize = 0, appSize = 0;
 
 1429       p = (*it)->m_packet;
 
 1434       beginOfCurrentPacket += p->
GetSize ();
 
 1439       appSize += (*it)->m_packet->GetSize ();
 
 1442   os << 
"Sent list: " << ss.str () << 
", size = " << tcpTxBuf.
m_sentList.size () <<
 
 1443     " Total size: " << tcpTxBuf.
m_size <<
 
 1446     " m_retransOut = " << tcpTxBuf.
m_retrans <<
 
 1447     " m_lostOut = " << tcpTxBuf.
m_lostOut <<
 
void AddRenoSack()
Emulate SACKs for SACKless connection: account for a new dupack. 
 
bool m_retrans
Indicates if the segment is retransmitted. 
 
uint32_t Size(void) const 
Returns total number of bytes in this buffer. 
 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
 
uint32_t m_retrans
Number of retransmitted bytes. 
 
TcpTxItem * GetTransmittedSegment(uint32_t numBytes, const SequenceNumber32 &seq)
Get a block of data previously transmitted. 
 
NUMERIC_TYPE GetValue() const 
Extracts the numeric value of the sequence number. 
 
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. 
 
bool NextSeg(SequenceNumber32 *seq, bool isRecovery) const 
Get the next sequence number to transmit, according to RFC 6675. 
 
uint32_t SizeFromSequence(const SequenceNumber32 &seq) const 
Returns the number of bytes from the buffer in the range [seq, tailSequence) 
 
void ResetLastSegmentSent()
Take the last segment sent and put it back into the un-sent list (at the beginning) ...
 
SequenceNumber32 HeadSequence(void) const 
Get the sequence number of the buffer head. 
 
void ConsistencyCheck() const 
Check if the values of sacked, lost, retrans, are in sync with the sent list. 
 
PacketList m_appList
Buffer for application data. 
 
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 m_lostOut
Number of lost bytes. 
 
std::list< SackBlock > SackList
SACK list definition. 
 
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
 
uint32_t MaxBufferSize(void) const 
Get the maximum buffer size. 
 
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name. 
 
uint32_t GetSize(void) const 
Returns the the size in bytes of the packet (including the zero-filled initial payload). 
 
#define NS_UNUSED(x)
Mark a local variable as unused. 
 
void SplitItems(TcpTxItem *t1, TcpTxItem *t2, uint32_t size) const 
Split one TcpTxItem. 
 
void DeleteRetransmittedFlagFromHead()
DeleteRetransmittedFlagFromHead. 
 
void RemoveFromCounts(TcpTxItem *item, uint32_t size)
Remove the size specified from the lostOut, retrans, sacked count. 
 
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO. 
 
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate. 
 
void MergeItems(TcpTxItem *t1, TcpTxItem *t2) const 
Merge two TcpTxItem. 
 
T Get(void) const 
Get the underlying value. 
 
void Print(std::ostream &os) const 
Print the packet contents. 
 
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. 
 
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source. 
 
void UpdateLostCount()
Update the lost count. 
 
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const 
Create a new packet which contains a fragment of the original packet. 
 
double GetSeconds(void) const 
Get an approximation of the time stored in this instance in the indicated unit. 
 
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet. 
 
uint32_t GetSeqSize(void) const 
Get the size in the sequence number space. 
 
Item that encloses the application packet and some flags for it. 
 
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
 
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet. 
 
TracedValue< SequenceNumber32 > m_firstByteSeq
Sequence number of the first byte in data (SND.UNA) 
 
Time m_lastSent
Timestamp of the time at which the segment has been sent last time. 
 
SequenceNumber32 m_startSeq
Sequence number of the item (if transmitted) 
 
uint32_t m_sentSize
Size of sent (and not discarded) segments. 
 
bool IsLost(const SequenceNumber32 &seq) const 
Check if a segment is lost. 
 
bool IsLostRFC(const SequenceNumber32 &seq, const PacketList::const_iterator &segment) const 
Decide if a segment is lost based on RFC 6675 algorithm. 
 
std::list< TcpTxItem * > PacketList
container for data stored in the buffer 
 
static bool AreEquals(const bool &first, const bool &second)
 
uint32_t m_size
Size of all data in this buffer. 
 
void SetMaxBufferSize(uint32_t n)
Set the maximum buffer size. 
 
void SetSentListLost(bool resetSack=false)
Set the entire sent list as lost (typically after an RTO) 
 
std::pair< PacketList::const_iterator, SequenceNumber32 > m_highestSack
Highest SACK byte. 
 
uint32_t Available(void) const 
Returns the available capacity of this buffer. 
 
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output 
 
void ResetSentList()
Reset the sent list. 
 
Ptr< Packet > Copy(void) const 
performs a COW copy of the packet. 
 
Ptr< Packet > m_packet
Application packet (can be null) 
 
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. 
 
uint32_t m_sackedOut
Number of sacked bytes. 
 
static TypeId GetTypeId(void)
Get the type ID. 
 
void ResetRenoSack()
Reset the SACKs. 
 
static Time Now(void)
Return the current simulation virtual time. 
 
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
 
void MarkHeadAsLost()
Mark the head of the sent list as lost. 
 
bool Update(const TcpOptionSack::SackList &list)
Update the scoreboard. 
 
bool IsHeadRetransmitted() const 
Check if the head is retransmitted. 
 
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message. 
 
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message. 
 
uint32_t m_dupAckThresh
Duplicate Ack threshold from TcpSocketBase. 
 
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN. 
 
PacketList m_sentList
Buffer for sent (but not acked) data. 
 
uint32_t BytesInFlightRFC() const 
Calculate the number of bytes in flight per RFC 6675. 
 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG. 
 
uint32_t m_maxBuffer
Max number of data bytes in buffer (SND.WND) 
 
std::pair< TcpTxBuffer::PacketList::const_iterator, SequenceNumber32 > FindHighestSacked() const 
Find the highest SACK byte. 
 
TcpTxItem * GetNewSegment(uint32_t numBytes)
Get a block of data not transmitted yet and move it into SentList. 
 
uint32_t m_segmentSize
Segment size from TcpSocketBase. 
 
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR. 
 
A base class which provides memory management and object aggregation. 
 
uint32_t BytesInFlight() const 
Return total bytes in flight. 
 
TcpTxBuffer(uint32_t n=0)
Constructor. 
 
virtual ~TcpTxBuffer(void)
 
void Print(std::ostream &os) const 
Print the time. 
 
bool m_renoSack
Indicates if AddRenoSack was called. 
 
bool m_sacked
Indicates if the segment has been SACKed. 
 
a unique identifier for an interface. 
 
TypeId SetParent(TypeId tid)
Set the parent TypeId. 
 
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number. 
 
bool m_lost
Indicates if the segment has been lost (RTO) 
 
SequenceNumber32 TailSequence(void) const 
Get the sequence number of the buffer tail (plus one) 
 
void SetHeadSequence(const SequenceNumber32 &seq)
Set the head sequence of the buffer. 
 
Ptr< Packet > CopyFromSequence(uint32_t numBytes, const SequenceNumber32 &seq)
Copy data from the range [seq, seq+numBytes) into a packet.