25 #include "ns3/packet.h" 27 #include "ns3/abort.h" 28 #include "ns3/tcp-option-ts.h" 43 .SetGroupName (
"Internet")
45 .AddTraceSource (
"UnackSequence",
46 "First unacknowledged sequence number (SND.UNA)",
48 "ns3::SequenceNumber32TracedValueCallback")
61 : m_maxBuffer (32768), m_size (0), m_sentSize (0), m_firstByteSeq (
n)
68 PacketList::iterator it;
187 NS_LOG_LOGIC (
"Rejected. Not enough room to buffer packet.");
200 return static_cast<uint32_t
> (lastSeq - seq);
203 NS_LOG_ERROR (
"Requested a sequence beyond our space (" << seq <<
" > " << lastSeq <<
204 "). Returning 0 for convenience.");
214 "Requested a sequence number which is not in the buffer anymore");
234 NS_LOG_DEBUG (
"Returning already sent item " << *outItem <<
" from " << *
this);
239 "Requesting a piece of new data with an hole");
246 NS_LOG_DEBUG (
"Returning new item " << *outItem <<
" from " << *
this);
262 "Returning an item " << *outItem <<
" with SND.UNA as " <<
275 NS_LOG_INFO (
"AppList start at " << startOfAppList <<
", sentSize = " <<
279 numBytes, startOfAppList);
302 bool listEdited =
false;
303 uint32_t s = numBytes;
309 if ((*it)->m_startSeq == seq)
316 if (! (*next)->m_sacked)
318 s =
std::min(s, (*it)->m_packet->GetSize () + (*next)->m_packet->GetSize ());
323 s =
std::min(s, (*it)->m_packet->GetSize ());
328 s =
std::min(s, (*it)->m_packet->GetSize ());
345 std::pair <TcpTxBuffer::PacketList::const_iterator, SequenceNumber32>
359 ret = std::make_pair (it, beginOfCurrentPacket);
371 NS_ASSERT (t1 !=
nullptr && t2 !=
nullptr);
385 NS_LOG_INFO (
"Split of size " << size <<
" result: t1 " << *t1 <<
" t2 " << *t2);
391 bool *listEdited)
const 425 PacketList::iterator it =
list.begin ();
428 while (it !=
list.end ())
431 currentPacket = currentItem->
m_packet;
439 if (seq < beginOfCurrentPacket + currentPacket->
GetSize ())
442 if (seq == beginOfCurrentPacket)
445 outItem = currentItem;
446 NS_LOG_INFO (
"Current packet starts at seq " << seq <<
447 " ends at " << seq + currentPacket->
GetSize ());
449 else if (seq > beginOfCurrentPacket)
454 NS_LOG_INFO (
"we are at " << beginOfCurrentPacket <<
455 " searching for " << seq <<
456 " and now we recurse because packet ends at " 457 << beginOfCurrentPacket + currentPacket->
GetSize ());
459 SplitItems (firstPart, currentItem, seq - beginOfCurrentPacket);
462 list.insert (it, firstPart);
472 NS_FATAL_ERROR (
"seq < beginOfCurrentPacket: our data is before");
478 beginOfCurrentPacket += currentPacket->
GetSize ();
489 if (seq + numBytes <= beginOfCurrentPacket + currentPacket->
GetSize ())
492 if (numBytes == currentPacket->
GetSize ())
520 else if (numBytes < currentPacket->
GetSize ())
525 SplitItems (firstPart, currentItem, numBytes);
528 list.insert (it, firstPart);
541 if (++it ==
list.end ())
545 NS_LOG_WARN (
"Cannot reach the end, but this case is covered " 546 "with conditional statements inside CopyFromSequence." 547 "Something has gone wrong, report a bug");
581 NS_ASSERT (t1 !=
nullptr && t2 !=
nullptr);
583 NS_LOG_INFO (
"Merging " << *t2 <<
" into " << *t1);
586 "Merging one sacked and another not sacked. Impossible");
588 "Merging one lost and another not lost. Impossible");
617 NS_LOG_INFO (
"Situation after the merge: " << *t1);
660 while (
m_size > 0 && offset > 0)
690 ". Remaining data " <<
m_size);
692 if (!beforeDelCb.
IsNull ())
713 NS_LOG_INFO (
"Fragmented one packet by size " << offset <<
714 ", new size=" <<
pktSize <<
" resulting item is " <<
715 *item <<
" status: " << *
this);
736 NS_LOG_INFO (
"Moving the SACK flag from the HEAD to another segment");
742 "While removing up to " << seq <<
" we get SND.UNA to " <<
753 NS_LOG_LOGIC (
"Buffer status after discarding data " << *
this);
764 NS_LOG_INFO (
"Updating scoreboard, got " <<
list.size () <<
" blocks to analyze");
766 uint32_t bytesSacked = 0;
768 for (
auto option_it =
list.begin (); option_it !=
list.end (); ++option_it)
770 PacketList::iterator item_it =
m_sentList.begin ();
775 NS_LOG_INFO (
"Not updating scoreboard, the option block is outside the sent list");
781 uint32_t
pktSize = (*item_it)->m_packet->GetSize ();
788 if (beginOfCurrentPacket >= (*option_it).first
789 && beginOfCurrentPacket +
pktSize <= (*option_it).second)
791 if ((*item_it)->m_sacked)
795 ", checking sentList for block " << *(*item_it) <<
796 ", found in the sackboard already sacked");
800 if ((*item_it)->m_lost)
802 (*item_it)->m_lost =
false;
803 m_lostOut -= (*item_it)->m_packet->GetSize ();
806 (*item_it)->m_sacked =
true;
808 bytesSacked += (*item_it)->m_packet->GetSize ();
813 m_highestSack = std::make_pair (item_it, beginOfCurrentPacket);
817 ", checking sentList for block " << *(*item_it) <<
818 ", found in the sackboard, sacking, current highSack: " <<
827 else if (beginOfCurrentPacket +
pktSize > (*option_it).second)
831 ", checking sentList for block " << *(*item_it) <<
832 "], not found, breaking loop");
836 beginOfCurrentPacket +=
pktSize;
863 NS_LOG_INFO (
"Status before the update: " << *
this <<
864 ", will start from the latest sent item");
868 NS_LOG_INFO (
"Status before the update: " << *
this <<
900 NS_LOG_INFO (
"Status after the update: " << *
this);
910 PacketList::const_iterator it;
922 if (beginOfCurrentPacket >= seq)
924 if ((*it)->m_lost ==
true)
926 NS_LOG_INFO (
"seq=" << seq <<
" is lost because of lost flag");
930 if ((*it)->m_sacked ==
true)
932 NS_LOG_INFO (
"seq=" << seq <<
" is not lost because of sacked flag");
937 beginOfCurrentPacket += (*it)->m_packet->GetSize ();
961 PacketList::const_iterator it;
964 bool isSeqPerRule3Valid =
false;
976 NS_LOG_INFO(
"IsLost, returning" << beginOfCurrentPkt);
977 *seq = beginOfCurrentPkt;
981 else if (seqPerRule3.
GetValue () == 0 && isRecovery)
983 NS_LOG_INFO (
"Saving for rule 3 the seq " << beginOfCurrentPkt);
984 isSeqPerRule3Valid =
true;
985 seqPerRule3 = beginOfCurrentPkt;
1010 NS_LOG_INFO (
"There is no available receiver window to send");
1025 if (isSeqPerRule3Valid)
1054 " is out of sync with sent list size " <<
m_sentSize <<
1060 " retrans: " << retrans);
1061 uint32_t in_flight =
m_sentSize - leftOut + retrans;
1074 PacketList::const_iterator it;
1078 uint32_t sackedOut = 0;
1079 uint32_t lostOut = 0;
1080 uint32_t retrans = 0;
1081 uint32_t totalSize = 0;
1092 bool isLost =
IsLostRFC (beginOfCurrentPkt, it);
1130 "Sent size counted: " << totalSize <<
" " <<
m_sentSize << *
this);
1141 PacketList::const_iterator it;
1146 if ((*segment)->m_sacked ==
true)
1156 for (it = segment; it !=
m_sentList.end (); ++it)
1164 " found to be SACKed while checking for " << seq);
1169 NS_LOG_INFO (
"seq=" << seq <<
" is lost because of 3 sacked blocks ahead");
1179 NS_LOG_INFO (
"seq=" << seq <<
" is not lost because there are no sacked segment ahead");
1183 beginOfCurrentPacket += current->
GetSize ();
1200 (*it)->m_sacked =
false;
1275 (*it)->m_sacked =
false;
1276 (*it)->m_lost =
true;
1283 m_lostOut += (*it)->m_packet->GetSize ();
1285 else if (!(*it)->m_sacked)
1288 (*it)->m_lost =
true;
1289 m_lostOut += (*it)->m_packet->GetSize ();
1293 (*it)->m_retrans =
false;
1296 NS_LOG_INFO (
"Set sent list lost, status: " << *
this);
1373 while (it !=
m_sentList.end () && (*it)->m_sacked)
1381 (*it)->m_sacked =
true;
1384 NS_LOG_INFO (
"Added a Reno SACK, status: " << *
this);
1388 NS_LOG_INFO (
"Can't add a Reno SACK because we miss segments. This dupack" 1389 " should be arrived from spurious retransmissions");
1398 static const bool enable =
false;
1405 uint32_t sacked = 0;
1407 uint32_t retrans = 0;
1411 if ((*it)->m_sacked)
1413 sacked += (*it)->m_packet->GetSize ();
1417 lost += (*it)->m_packet->GetSize ();
1419 if ((*it)->m_retrans)
1421 retrans += (*it)->m_packet->GetSize ();
1443 TcpTxBuffer::PacketList::const_iterator it;
1444 std::stringstream ss;
1446 uint32_t sentSize = 0, appSize = 0;
1451 p = (*it)->GetPacket ();
1456 beginOfCurrentPacket += p->
GetSize ();
1461 appSize += (*it)->GetPacket ()->GetSize ();
1464 os <<
"Sent list: " << ss.str () <<
", size = " << tcpTxBuf.
m_sentList.size () <<
1465 " Total size: " << tcpTxBuf.
m_size <<
1468 " m_retransOut = " << tcpTxBuf.
m_retrans <<
1469 " m_lostOut = " << tcpTxBuf.
m_lostOut <<
Callback< uint32_t > m_rWndCallback
Callback to obtain RCV.WND value.
void AddRenoSack()
Emulate SACKs for SACKless connection: account for a new dupack.
bool m_retrans
Indicates if the segment is retransmitted.
void Print(std::ostream &os) const
Print the packet contents.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
std::pair< TcpTxBuffer::PacketList::const_iterator, SequenceNumber32 > FindHighestSacked() const
Find the highest SACK byte.
void ResetLastSegmentSent()
Take the last segment sent and put it back into the un-sent list (at the beginning) ...
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.
uint32_t GetRetransmitsCount(void) const
Return the number of segments in the sent list that have been transmitted more than once...
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_UNUSED(x)
Mark a local variable as unused.
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.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
void UpdateLostCount()
Update the lost count.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Item that encloses the application packet and some flags for it.
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.
void DiscardUpTo(const SequenceNumber32 &seq, const Callback< void, TcpTxItem *> &beforeDelCb=m_nullCb)
Discard data up to but not including this sequence number.
std::list< TcpTxItem * > PacketList
container for data stored in the buffer
static bool AreEquals(const bool &first, const bool &second)
void MergeItems(TcpTxItem *t1, TcpTxItem *t2) const
Merge two TcpTxItem.
uint32_t m_size
Size of all data in this buffer.
TcpTxItem * CopyFromSequence(uint32_t numBytes, const SequenceNumber32 &seq)
Copy data from the range [seq, seq+numBytes) into a packet.
void SetRWndCallback(Callback< uint32_t > rWndCallback)
Set callback to obtain receiver window value.
void ConsistencyCheck() const
Check if the values of sacked, lost, retrans, are in sync with the sent list.
void SetMaxBufferSize(uint32_t n)
Set the maximum buffer size.
uint32_t SizeFromSequence(const SequenceNumber32 &seq) const
Returns the number of bytes from the buffer in the range [seq, tailSequence)
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.
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
void ResetSentList()
Reset the sent list.
uint32_t GetLost(void) const
Get the number of segments that we believe are lost in the network.
Ptr< Packet > m_packet
Application packet (can be null)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
SequenceNumber32 TailSequence(void) const
Get the sequence number of the buffer tail (plus one)
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
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 SetDupAckThresh(uint32_t dupAckThresh)
Set the DupAckThresh.
SequenceNumber32 HeadSequence(void) const
Get the sequence number of the buffer head.
void MarkHeadAsLost()
Mark the head of the sent list as lost.
bool IsLostRFC(const SequenceNumber32 &seq, const PacketList::const_iterator &segment) const
Decide if a segment is lost based on RFC 6675 algorithm.
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
void SetSegmentSize(uint32_t segmentSize)
Set the segment size.
#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.
void SplitItems(TcpTxItem *t1, TcpTxItem *t2, uint32_t size) const
Split one TcpTxItem.
uint32_t Size(void) const
Returns total number of bytes in this buffer.
uint32_t m_dupAckThresh
Duplicate Ack threshold from TcpSocketBase.
Ptr< Packet > GetPacketCopy(void) const
Get a copy of the Packet underlying this item.
bool IsLost(const SequenceNumber32 &seq) const
Check if a segment is lost.
#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.
uint32_t Update(const TcpOptionSack::SackList &list, const Callback< void, TcpTxItem *> &sackedCb=m_nullCb)
Update the scoreboard.
#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)
T Get(void) const
Get the underlying value.
uint32_t Available(void) const
Returns the available capacity of this buffer.
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.
bool NextSeg(SequenceNumber32 *seq, SequenceNumber32 *seqHigh, bool isRecovery) const
Get the next sequence number to transmit, according to RFC 6675.
#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.
bool IsHeadRetransmitted() const
Check if the head is retransmitted.
TcpTxBuffer(uint32_t n=0)
Constructor.
bool IsNull(void) const
Check for null implementation.
uint32_t pktSize
packet size used for the simulation (in bytes)
virtual ~TcpTxBuffer(void)
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
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.
uint32_t MaxBufferSize(void) const
Get the maximum buffer size.
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
uint32_t GetSacked(void) const
Get the number of segments that have been explicitly sacked by the receiver.
void Print(std::ostream &os) const
Print the time.
bool m_lost
Indicates if the segment has been lost (RTO)
uint32_t BytesInFlight() const
Return total bytes in flight.
static Callback< void, TcpTxItem * > m_nullCb
Null callback for an item.
void SetHeadSequence(const SequenceNumber32 &seq)
Set the head sequence of the buffer.