25 #include "ns3/packet.h"
27 #include "ns3/abort.h"
28 #include "ns3/tcp-option-ts.h"
46 : m_packet (other.m_packet),
47 m_lost (other.m_lost),
48 m_retrans (other.m_retrans),
49 m_lastSent (other.m_lastSent),
50 m_sacked (other.m_sacked)
97 .SetGroupName (
"Internet")
99 .AddTraceSource (
"UnackSequence",
100 "First unacknowledged sequence number (SND.UNA)",
102 "ns3::SequenceNumber32TracedValueCallback")
115 : m_maxBuffer (32768), m_size (0), m_sentSize (0), m_firstByteSeq (n)
121 PacketList::iterator it;
205 NS_LOG_WARN (
"Rejected. Not enough room to buffer packet.");
218 return lastSeq - seq;
221 NS_LOG_ERROR (
"Requested a sequence beyond our space (" << seq <<
" > " << lastSeq <<
222 "). Returning 0 for convenience.");
233 NS_LOG_ERROR (
"Requested a sequence number which is not in the buffer anymore");
234 return Create<Packet> ();
242 return Create<Packet> ();
254 NS_LOG_DEBUG (
"Retransmitting [" << seq <<
";" << seq + s <<
"|" << s <<
260 "Requesting a piece of new data with an hole");
267 NS_LOG_DEBUG (
"New segment [" << seq <<
";" << seq + s <<
"|" << s <<
303 bool listEdited =
false;
305 numBytes, startOfAppList, &listEdited);
327 bool listEdited =
false;
339 std::pair <TcpTxBuffer::PacketList::const_iterator, SequenceNumber32>
344 PacketList::const_iterator it;
345 std::pair <TcpTxBuffer::PacketList::const_iterator, SequenceNumber32> ret;
355 ret = std::make_pair (it, beginOfCurrentPacket);
381 bool *listEdited)
const
415 PacketList::iterator it = list.begin ();
418 while (it != list.end ())
421 currentPacket = currentItem->
m_packet;
426 if (seq < beginOfCurrentPacket + currentPacket->GetSize ())
429 if (seq == beginOfCurrentPacket)
432 outItem = currentItem;
433 NS_LOG_INFO (
"Current packet starts at seq " << seq <<
434 " ends at " << seq + currentPacket->
GetSize ());
436 else if (seq > beginOfCurrentPacket)
441 NS_LOG_INFO (
"we are at " << beginOfCurrentPacket <<
442 " searching for " << seq <<
443 " and now we recurse because packet ends at "
444 << beginOfCurrentPacket + currentPacket->
GetSize ());
446 SplitItems (*firstPart, *currentItem, seq - beginOfCurrentPacket);
449 list.insert (it, firstPart);
456 NS_FATAL_ERROR (
"seq < beginOfCurrentPacket: our data is before");
462 beginOfCurrentPacket += currentPacket->
GetSize ();
473 if (seq + numBytes <= beginOfCurrentPacket + currentPacket->GetSize ())
476 if (numBytes == currentPacket->
GetSize ())
501 else if (numBytes < currentPacket->GetSize ())
506 SplitItems (*firstPart, *currentItem, numBytes);
509 list.insert (it, firstPart);
519 if (++it == list.end ())
523 NS_LOG_WARN (
"Cannot reach the end, but this case is covered "
524 "with conditional statements inside CopyFromSequence."
525 "Something has gone wrong, report a bug");
593 while (
m_size > 0 && offset > 0)
606 if (offset >= pktSize)
615 ".Removed one packet of size " << pktSize <<
617 ". Remaining data " <<
m_size);
627 NS_LOG_INFO (
"Fragmented one packet by size " << offset <<
628 ", new size=" << pktSize);
656 NS_LOG_LOGIC (
"Buffer status after discarding data " << *
this);
665 bool modified =
false;
666 TcpOptionSack::SackList::const_iterator option_it;
667 NS_LOG_INFO (
"Updating scoreboard, got " << list.size () <<
" blocks to analyze");
668 for (option_it = list.begin (); option_it != list.end (); ++option_it)
674 PacketList::iterator item_it =
m_sentList.begin ();
684 if (beginOfCurrentPacket >= b.first
685 && beginOfCurrentPacket + current->
GetSize () <= b.second)
689 NS_LOG_INFO (
"Received block [" << b.first <<
";" << b.second <<
690 ", checking sentList for block " << beginOfCurrentPacket <<
691 ";" << beginOfCurrentPacket + current->
GetSize () <<
692 "], found in the sackboard already sacked");
697 NS_LOG_INFO (
"Received block [" << b.first <<
";" << b.second <<
698 ", checking sentList for block " << beginOfCurrentPacket <<
699 ";" << beginOfCurrentPacket + current->
GetSize () <<
700 "], found in the sackboard, sacking");
703 PacketList::iterator new_it = item_it;
709 else if (beginOfCurrentPacket + current->
GetSize () > b.second)
713 NS_LOG_INFO (
"Received block [" << b.first <<
";" << b.second <<
714 ", checking sentList for block " << beginOfCurrentPacket <<
715 ";" << beginOfCurrentPacket + current->
GetSize () <<
716 "], not found, breaking loop");
720 beginOfCurrentPacket += current->
GetSize ();
732 uint32_t dupThresh, uint32_t segmentSize)
const
737 PacketList::const_iterator it;
742 NS_LOG_INFO (
"Checking if seq=" << seq <<
" is lost from the buffer ");
744 if ((*segment)->m_lost ==
true)
746 NS_LOG_INFO (
"seq=" << seq <<
" is lost because of lost flag");
750 if ((*segment)->m_sacked ==
true)
752 NS_LOG_INFO (
"seq=" << seq <<
" is not lost because of sacked flag");
765 NS_LOG_INFO (
"seq=" << seq <<
" is not lost because there are no sacked segment ahead");
774 NS_LOG_INFO (
"Segment [" << beginOfCurrentPacket <<
", " <<
776 "] found to be SACKed");
779 if ((count >= dupThresh) || (bytes > (dupThresh-1) * segmentSize))
781 NS_LOG_INFO (
"seq=" << seq <<
" is lost because of 3 sacked blocks ahead");
786 beginOfCurrentPacket += current->
GetSize ();
794 uint32_t segmentSize)
const
799 PacketList::const_iterator it;
811 if (beginOfCurrentPacket >= seq)
813 return IsLost (beginOfCurrentPacket, it, dupThresh, segmentSize);
816 beginOfCurrentPacket += (*it)->m_packet->GetSize ();
824 uint32_t segmentSize,
bool isRecovery)
const
842 PacketList::const_iterator it;
845 bool isSeqPerRule3Valid =
false;
855 if (
IsLost (beginOfCurrentPkt, it, dupThresh, segmentSize))
857 *seq = beginOfCurrentPkt;
860 else if (seqPerRule3.
GetValue () == 0 && isRecovery)
862 isSeqPerRule3Valid =
true;
863 seqPerRule3 = beginOfCurrentPkt;
889 if (isSeqPerRule3Valid)
914 PacketList::const_iterator it;
931 PacketList::const_iterator it;
945 if (!
IsLost (beginOfCurrentPkt, it, dupThresh, segmentSize))
968 PacketList::iterator it;
973 (*it)->m_sacked =
false;
974 beginOfCurrentPkt += (*it)->m_packet->GetSize ();
1030 PacketList::iterator it;
1034 (*it)->m_lost =
true;
1061 NS_LOG_INFO (
"Crafting a SACK block, available bytes: " << (uint32_t) available <<
1062 " from seq: " << seq <<
" buffer starts at seq " <<
m_firstByteSeq);
1064 PacketList::const_iterator it;
1086 NS_LOG_DEBUG (
"Analyzing segment: [" << beginOfCurrentPacket <<
1087 ";" << endOfCurrentPacket <<
"], not usable, sacked=" <<
1089 beginOfCurrentPacket += current->
GetSize ();
1091 else if (seq > beginOfCurrentPacket)
1093 NS_LOG_DEBUG (
"Analyzing segment: [" << beginOfCurrentPacket <<
1094 ";" << endOfCurrentPacket <<
"], not usable, sacked=" <<
1096 beginOfCurrentPacket += current->
GetSize ();
1103 sackBlock = CreateObject <TcpOptionSack> ();
1105 endOfCurrentPacket));
1106 NS_LOG_DEBUG (
"Analyzing segment: [" << beginOfCurrentPacket <<
1107 ";" << endOfCurrentPacket <<
"] and found to be usable");
1115 while (sackBlock->GetSerializedSize () + 8 < available)
1126 endOfCurrentPacket = beginOfCurrentPacket;
1127 beginOfCurrentPacket -= current->
GetSize ();
1129 endOfCurrentPacket));
1130 NS_LOG_DEBUG (
"Filling the option: Adding [" << beginOfCurrentPacket <<
1131 ";" << endOfCurrentPacket <<
"], available space now : " <<
1132 (uint32_t) (available - sackBlock->GetSerializedSize ()));
1148 TcpTxBuffer::PacketList::const_iterator it;
1149 std::stringstream ss;
1151 uint32_t sentSize = 0, appSize = 0;
1156 p = (*it)->m_packet;
1157 ss <<
"[" << beginOfCurrentPacket <<
";"
1158 << beginOfCurrentPacket + p->
GetSize () <<
"|" << p->
GetSize () <<
"|";
1162 beginOfCurrentPacket += p->
GetSize ();
1167 appSize += (*it)->m_packet->GetSize ();
1170 os <<
"Sent list: " << ss.str () <<
", size = " << tcpTxBuf.
m_sentList.size () <<
1171 " Total size: " << tcpTxBuf.
m_size <<
Simulation virtual time values and global simulation resolution.
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 "...
void ResetSentList(uint32_t keepItems=1)
Reset the sent list.
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.
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) ...
bool IsLost(const SequenceNumber32 &seq, uint32_t dupThresh, uint32_t segmentSize) const
Check if a segment is lost per RFC 6675.
SequenceNumber32 HeadSequence(void) const
Get the sequence number of the buffer head.
PacketList m_appList
Buffer for application data.
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_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.
T Get(void) const
Get the underlying value.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
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.
uint32_t GetRetransmitsCount(void) const
Return the number of segments in the sent list that have been transmitted more than once...
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.
uint32_t BytesInFlight(uint32_t dupThresh, uint32_t segmentSize) const
Return total bytes in flight.
uint32_t m_sentSize
Size of sent (and not discarded) segments.
void SetSentListLost()
Set the entire sent list as lost (typically after an RTO)
std::list< TcpTxItem * > PacketList
container for data stored in the buffer
uint32_t m_size
Size of all data in this buffer.
void SetMaxBufferSize(uint32_t n)
Set the maximum buffer size.
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
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Ptr< Packet > m_packet
Application packet.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool NextSeg(SequenceNumber32 *seq, uint32_t dupThresh, uint32_t segmentSize, bool isRecovery) const
Get the next sequence number to transmit, according to RFC 6675.
bool Add(Ptr< Packet > p)
Append a data packet to the end of the buffer.
static TypeId GetTypeId(void)
Get the type ID.
static Time Now(void)
Return the current simulation virtual time.
void SplitItems(TcpTxItem &t1, TcpTxItem &t2, uint32_t size) const
Split one TcpTxItem.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
std::pair< SequenceNumber32, SequenceNumber32 > SackBlock
SACK block definition.
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_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
PacketList m_sentList
Buffer for sent (but not acked) data.
#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)
void ResetScoreboard()
Reset the Scoreboard from all SACK informations.
TcpTxItem * GetNewSegment(uint32_t numBytes)
Get a block of data not transmitted yet and move it into SentList.
TcpTxItem * GetPacketFromList(PacketList &list, const SequenceNumber32 &startingSeq, uint32_t numBytes, const SequenceNumber32 &requestedSeq, bool *listEdited) const
Get a block (which is returned as Packet) from a list.
Ptr< const TcpOptionSack > CraftSackOption(const SequenceNumber32 &seq, uint8_t available) const
Craft a SACK block.
#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.
TcpTxBuffer(uint32_t n=0)
Constructor.
virtual ~TcpTxBuffer(void)
void MergeItems(TcpTxItem &t1, TcpTxItem &t2) const
Merge two TcpTxItem.
void Print(std::ostream &os) const
Print the time.
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)
std::pair< TcpTxBuffer::PacketList::const_iterator, SequenceNumber32 > GetHighestSacked() const
Find the highest SACK byte.
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.