INET Framework for OMNeT++/OMNEST
inet::tcp::TcpSackRexmitQueue Class Reference

Retransmission data for SACK. More...

#include <TcpSackRexmitQueue.h>

Classes

struct  Region
 

Public Types

typedef std::list< RegionRexmitQueue
 

Public Member Functions

 TcpSackRexmitQueue ()
 Ctor. More...
 
virtual ~TcpSackRexmitQueue ()
 Virtual dtor. More...
 
virtual void setConnection (TcpConnection *_conn)
 Set the connection that owns this queue. More...
 
virtual void init (uint32_t seqNum)
 Initialize the object. More...
 
virtual std::string str () const
 Returns a string for debug purposes. More...
 
virtual std::string detailedInfo () const
 Prints the current rexmitQueue status for debug purposes. More...
 
virtual uint32_t getBufferStartSeq () const
 Returns the sequence number of the first byte stored in the buffer. More...
 
virtual uint32_t getBufferEndSeq () const
 Returns the sequence number of the last byte stored in the buffer plus one. More...
 
virtual void discardUpTo (uint32_t seqNum)
 Tells the queue that bytes up to (but NOT including) seqNum have been transmitted and ACKed, so they can be removed from the queue. More...
 
virtual void enqueueSentData (uint32_t fromSeqNum, uint32_t toSeqNum)
 Inserts sent data to the rexmit queue. More...
 
virtual void setSackedBit (uint32_t fromSeqNum, uint32_t toSeqNum)
 Called when data sender received selective acknowledgments. More...
 
virtual bool getSackedBit (uint32_t seqNum) const
 Returns SackedBit value of seqNum. More...
 
virtual uint32_t getQueueLength () const
 Returns the number of blocks currently buffered in queue. More...
 
virtual uint32_t getHighestSackedSeqNum () const
 Returns the highest sequence number sacked by data receiver. More...
 
virtual uint32_t getHighestRexmittedSeqNum () const
 Returns the highest sequence number rexmitted by data sender. More...
 
virtual uint32_t checkRexmitQueueForSackedOrRexmittedSegments (uint32_t fromSeq) const
 Checks rexmit queue for sacked of rexmitted segments and returns a certain offset (contiguous sacked or rexmitted region) to forward snd->nxt. More...
 
virtual void resetSackedBit ()
 Called when REXMIT timer expired. More...
 
virtual void resetRexmittedBit ()
 Called when REXMIT timer expired. More...
 
virtual uint32_t getTotalAmountOfSackedBytes () const
 Returns total amount of sacked bytes. More...
 
virtual uint32_t getAmountOfSackedBytes (uint32_t seqNum) const
 Returns amount of sacked bytes above seqNum. More...
 
virtual uint32_t getNumOfDiscontiguousSacks (uint32_t seqNum) const
 Returns the number of discontiguous sacked regions (SACKed sequences) above seqNum. More...
 
virtual void checkSackBlock (uint32_t seqNum, uint32_t &length, bool &sacked, bool &rexmitted) const
 

Public Attributes

TcpConnectionconn
 
RexmitQueue rexmitQueue
 
uint32_t begin
 
uint32_t end
 

Protected Member Functions

bool checkQueue () const
 

Detailed Description

Retransmission data for SACK.

Member Typedef Documentation

◆ RexmitQueue

Constructor & Destructor Documentation

◆ TcpSackRexmitQueue()

inet::tcp::TcpSackRexmitQueue::TcpSackRexmitQueue ( )

Ctor.

15 {
16  conn = nullptr;
17  begin = end = 0;
18 }

◆ ~TcpSackRexmitQueue()

inet::tcp::TcpSackRexmitQueue::~TcpSackRexmitQueue ( )
virtual

Virtual dtor.

21 {
22  while (!rexmitQueue.empty())
23  rexmitQueue.pop_front();
24 }

Member Function Documentation

◆ checkQueue()

bool inet::tcp::TcpSackRexmitQueue::checkQueue ( ) const
protected
158 {
159  uint32_t b = begin;
160  bool f = true;
161 
162  for (const auto& elem : rexmitQueue) {
163  f = f && (b == elem.beginSeqNum);
164  f = f && seqLess(elem.beginSeqNum, elem.endSeqNum);
165  b = elem.endSeqNum;
166  }
167 
168  f = f && (b == end);
169 
170  if (!f) {
171  EV_DEBUG << "Invalid Queue\nThe Queue is:\n" << detailedInfo();
172  }
173 
174  return f;
175 }

Referenced by discardUpTo(), enqueueSentData(), and setSackedBit().

◆ checkRexmitQueueForSackedOrRexmittedSegments()

uint32_t inet::tcp::TcpSackRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments ( uint32_t  fromSeq) const
virtual

Checks rexmit queue for sacked of rexmitted segments and returns a certain offset (contiguous sacked or rexmitted region) to forward snd->nxt.

It is called before retransmitting data.

267 {
268  ASSERT(seqLE(begin, fromSeqNum) && seqLE(fromSeqNum, end));
269 
270  if (rexmitQueue.empty() || (end == fromSeqNum))
271  return 0;
272 
273  RexmitQueue::const_iterator i = rexmitQueue.begin();
274  uint32_t bytes = 0;
275 
276  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, fromSeqNum))
277  i++;
278 
279  while (i != rexmitQueue.end() && ((i->sacked || i->rexmitted))) {
280  ASSERT(seqLE(i->beginSeqNum, fromSeqNum) && seqLess(fromSeqNum, i->endSeqNum));
281 
282  bytes += (i->endSeqNum - fromSeqNum);
283  fromSeqNum = i->endSeqNum;
284  i++;
285  }
286 
287  return bytes;
288 }

Referenced by inet::tcp::TcpConnection::sendSegment().

◆ checkSackBlock()

void inet::tcp::TcpSackRexmitQueue::checkSackBlock ( uint32_t  seqNum,
uint32_t &  length,
bool &  sacked,
bool &  rexmitted 
) const
virtual
363 {
364  ASSERT(seqLE(begin, fromSeqNum) && seqLess(fromSeqNum, end));
365 
366  RexmitQueue::const_iterator i = rexmitQueue.begin();
367 
368  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, fromSeqNum)) // search for seqNum
369  i++;
370 
371  ASSERT(i != rexmitQueue.end());
372  ASSERT(seqLE(i->beginSeqNum, fromSeqNum) && seqLess(fromSeqNum, i->endSeqNum));
373 
374  length = (i->endSeqNum - fromSeqNum);
375  sacked = i->sacked;
376  rexmitted = i->rexmitted;
377 }

Referenced by inet::tcp::TcpConnection::nextSeg(), and inet::tcp::TcpConnection::setPipe().

◆ detailedInfo()

std::string inet::tcp::TcpSackRexmitQueue::detailedInfo ( ) const
virtual

Prints the current rexmitQueue status for debug purposes.

41 {
42  std::stringstream out;
43  out << str() << endl;
44 
45  uint j = 1;
46 
47  for (const auto& elem : rexmitQueue) {
48  out << j << ". region: [" << elem.beginSeqNum << ".." << elem.endSeqNum
49  << ") \t sacked=" << elem.sacked << "\t rexmitted=" << elem.rexmitted
50  << endl;
51  j++;
52  }
53  return out.str();
54 }

Referenced by checkQueue(), enqueueSentData(), and inet::tcp::TcpConnection::sendSegment().

◆ discardUpTo()

void inet::tcp::TcpSackRexmitQueue::discardUpTo ( uint32_t  seqNum)
virtual

Tells the queue that bytes up to (but NOT including) seqNum have been transmitted and ACKed, so they can be removed from the queue.

57 {
58  ASSERT(seqLE(begin, seqNum) && seqLE(seqNum, end));
59 
60  if (!rexmitQueue.empty()) {
61  auto i = rexmitQueue.begin();
62 
63  while ((i != rexmitQueue.end()) && seqLE(i->endSeqNum, seqNum)) // discard/delete regions from rexmit queue, which have been acked
64  i = rexmitQueue.erase(i);
65 
66  if (i != rexmitQueue.end()) {
67  ASSERT(seqLE(i->beginSeqNum, seqNum) && seqLess(seqNum, i->endSeqNum));
68  i->beginSeqNum = seqNum;
69  }
70  }
71 
72  begin = seqNum;
73 
74  // TESTING queue:
75  ASSERT(checkQueue());
76 }

Referenced by inet::tcp::TcpConnection::processAckInEstabEtc(), inet::tcp::TcpConnection::processRstInSynReceived(), and inet::tcp::TcpConnection::processSegmentInSynSent().

◆ enqueueSentData()

void inet::tcp::TcpSackRexmitQueue::enqueueSentData ( uint32_t  fromSeqNum,
uint32_t  toSeqNum 
)
virtual

Inserts sent data to the rexmit queue.

79 {
80  ASSERT(seqLE(begin, fromSeqNum) && seqLE(fromSeqNum, end));
81 
82  bool found = false;
83  Region region;
84 
85  EV_INFO << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
86 
87  ASSERT(seqLess(fromSeqNum, toSeqNum));
88 
89  if (rexmitQueue.empty() || (end == fromSeqNum)) {
90  region.beginSeqNum = fromSeqNum;
91  region.endSeqNum = toSeqNum;
92  region.sacked = false;
93  region.rexmitted = false;
94  rexmitQueue.push_back(region);
95  found = true;
96  fromSeqNum = toSeqNum;
97  }
98  else {
99  auto i = rexmitQueue.begin();
100 
101  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, fromSeqNum))
102  i++;
103 
104  ASSERT(i != rexmitQueue.end());
105  ASSERT(seqLE(i->beginSeqNum, fromSeqNum) && seqLess(fromSeqNum, i->endSeqNum));
106 
107  if (i->beginSeqNum != fromSeqNum) {
108  // chunk item
109  region = *i;
110  region.endSeqNum = fromSeqNum;
111  rexmitQueue.insert(i, region);
112  i->beginSeqNum = fromSeqNum;
113  }
114 
115  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, toSeqNum)) {
116  i->rexmitted = true;
117  fromSeqNum = i->endSeqNum;
118  found = true;
119  i++;
120  }
121 
122  if (fromSeqNum != toSeqNum) {
123  bool beforeEnd = (i != rexmitQueue.end());
124 
125  ASSERT(i == rexmitQueue.end() || seqLess(i->beginSeqNum, toSeqNum));
126 
127  region.beginSeqNum = fromSeqNum;
128  region.endSeqNum = toSeqNum;
129  region.sacked = beforeEnd ? i->sacked : false;
130  region.rexmitted = beforeEnd;
131  rexmitQueue.insert(i, region);
132  found = true;
133  fromSeqNum = toSeqNum;
134 
135  if (beforeEnd)
136  i->beginSeqNum = toSeqNum;
137  }
138  }
139 
140  ASSERT(fromSeqNum == toSeqNum);
141 
142  if (!found) {
143  EV_DEBUG << "Not found enqueueSentData(" << fromSeqNum << ", " << toSeqNum << ")\nThe Queue is:\n" << detailedInfo();
144  }
145 
146  ASSERT(found);
147 
148  begin = rexmitQueue.front().beginSeqNum;
149  end = rexmitQueue.back().endSeqNum;
150 
151  // TESTING queue:
152  ASSERT(checkQueue());
153 
154 // tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
155 }

Referenced by inet::tcp::TcpConnection::sendSegment().

◆ getAmountOfSackedBytes()

uint32_t inet::tcp::TcpSackRexmitQueue::getAmountOfSackedBytes ( uint32_t  seqNum) const
virtual

Returns amount of sacked bytes above seqNum.

315 {
316  ASSERT(seqLE(begin, fromSeqNum) && seqLE(fromSeqNum, end));
317 
318  uint32_t bytes = 0;
319  RexmitQueue::const_reverse_iterator i = rexmitQueue.rbegin();
320 
321  for (; i != rexmitQueue.rend() && seqLE(fromSeqNum, i->beginSeqNum); i++) {
322  if (i->sacked)
323  bytes += (i->endSeqNum - i->beginSeqNum);
324  }
325 
326  if (i != rexmitQueue.rend()
327  && seqLess(i->beginSeqNum, fromSeqNum) && seqLess(fromSeqNum, i->endSeqNum) && i->sacked)
328  {
329  bytes += (i->endSeqNum - fromSeqNum);
330  }
331 
332  return bytes;
333 }

Referenced by inet::tcp::TcpConnection::isLost().

◆ getBufferEndSeq()

virtual uint32_t inet::tcp::TcpSackRexmitQueue::getBufferEndSeq ( ) const
inlinevirtual

Returns the sequence number of the last byte stored in the buffer plus one.

(The first byte of the next send operation would get this sequence number.)

82 { return end; }

Referenced by inet::tcp::TcpConnection::processRstInSynReceived().

◆ getBufferStartSeq()

virtual uint32_t inet::tcp::TcpSackRexmitQueue::getBufferStartSeq ( ) const
inlinevirtual

Returns the sequence number of the first byte stored in the buffer.

76 { return begin; }

◆ getHighestRexmittedSeqNum()

uint32_t inet::tcp::TcpSackRexmitQueue::getHighestRexmittedSeqNum ( ) const
virtual

Returns the highest sequence number rexmitted by data sender.

257 {
258  for (RexmitQueue::const_reverse_iterator i = rexmitQueue.rbegin(); i != rexmitQueue.rend(); i++) {
259  if (i->rexmitted)
260  return i->endSeqNum;
261  }
262 
263  return begin;
264 }

Referenced by inet::tcp::TcpConnection::nextSeg(), inet::tcp::TcpConnection::retransmitOneSegment(), inet::tcp::TcpConnection::sendData(), inet::tcp::TcpConnection::sendSegmentDuringLossRecoveryPhase(), and inet::tcp::TcpConnection::setPipe().

◆ getHighestSackedSeqNum()

uint32_t inet::tcp::TcpSackRexmitQueue::getHighestSackedSeqNum ( ) const
virtual

Returns the highest sequence number sacked by data receiver.

247 {
248  for (RexmitQueue::const_reverse_iterator i = rexmitQueue.rbegin(); i != rexmitQueue.rend(); i++) {
249  if (i->sacked)
250  return i->endSeqNum;
251  }
252 
253  return begin;
254 }

Referenced by inet::tcp::TcpConnection::nextSeg().

◆ getNumOfDiscontiguousSacks()

uint32_t inet::tcp::TcpSackRexmitQueue::getNumOfDiscontiguousSacks ( uint32_t  seqNum) const
virtual

Returns the number of discontiguous sacked regions (SACKed sequences) above seqNum.

336 {
337  ASSERT(seqLE(begin, fromSeqNum) && seqLE(fromSeqNum, end));
338 
339  if (rexmitQueue.empty() || (fromSeqNum == end))
340  return 0;
341 
342  RexmitQueue::const_iterator i = rexmitQueue.begin();
343  uint32_t counter = 0;
344 
345  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, fromSeqNum)) // search for seqNum
346  i++;
347 
348  // search for discontiguous sacked regions
349  bool prevSacked = false;
350 
351  while (i != rexmitQueue.end()) {
352  if (i->sacked && !prevSacked)
353  counter++;
354 
355  prevSacked = i->sacked;
356  i++;
357  }
358 
359  return counter;
360 }

Referenced by inet::tcp::TcpConnection::isLost().

◆ getQueueLength()

virtual uint32_t inet::tcp::TcpSackRexmitQueue::getQueueLength ( ) const
inlinevirtual

Returns the number of blocks currently buffered in queue.

111 { return rexmitQueue.size(); }

◆ getSackedBit()

bool inet::tcp::TcpSackRexmitQueue::getSackedBit ( uint32_t  seqNum) const
virtual

Returns SackedBit value of seqNum.

230 {
231  ASSERT(seqLE(begin, seqNum) && seqLE(seqNum, end));
232 
233  RexmitQueue::const_iterator i = rexmitQueue.begin();
234 
235  if (end == seqNum)
236  return false;
237 
238  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, seqNum))
239  i++;
240 
241  ASSERT((i != rexmitQueue.end()) && seqLE(i->beginSeqNum, seqNum) && seqLess(seqNum, i->endSeqNum));
242 
243  return i->sacked;
244 }

◆ getTotalAmountOfSackedBytes()

uint32_t inet::tcp::TcpSackRexmitQueue::getTotalAmountOfSackedBytes ( ) const
virtual

Returns total amount of sacked bytes.

Corresponds to update() function from RFC 3517.

303 {
304  uint32_t bytes = 0;
305 
306  for (const auto& elem : rexmitQueue) {
307  if (elem.sacked)
308  bytes += (elem.endSeqNum - elem.beginSeqNum);
309  }
310 
311  return bytes;
312 }

Referenced by inet::tcp::TcpConnection::processSACKOption().

◆ init()

void inet::tcp::TcpSackRexmitQueue::init ( uint32_t  seqNum)
virtual

Initialize the object.

The startSeq parameter tells what sequence number the first byte of app data should get. This is usually ISS + 1 because SYN consumes one byte in the sequence number space.

init() may be called more than once; every call flushes the existing contents of the queue.

27 {
28  begin = seqNum;
29  end = seqNum;
30 }

Referenced by inet::tcp::TcpConnection::selectInitialSeqNum().

◆ resetRexmittedBit()

void inet::tcp::TcpSackRexmitQueue::resetRexmittedBit ( )
virtual

Called when REXMIT timer expired.

Resets rexmitted bit of all segments in rexmit queue.

297 {
298  for (auto& elem : rexmitQueue)
299  elem.rexmitted = false; // reset rexmitted bit
300 }

Referenced by inet::tcp::TcpBaseAlg::processRexmitTimer().

◆ resetSackedBit()

void inet::tcp::TcpSackRexmitQueue::resetSackedBit ( )
virtual

Called when REXMIT timer expired.

Resets sacked bit of all segments in rexmit queue.

291 {
292  for (auto& elem : rexmitQueue)
293  elem.sacked = false; // reset sacked bit
294 }

Referenced by inet::tcp::TcpBaseAlg::processRexmitTimer().

◆ setConnection()

virtual void inet::tcp::TcpSackRexmitQueue::setConnection ( TcpConnection _conn)
inlinevirtual

Set the connection that owns this queue.

51 { conn = _conn; }

Referenced by inet::tcp::TcpConnection::initClonedConnection(), and inet::tcp::TcpConnection::initConnection().

◆ setSackedBit()

void inet::tcp::TcpSackRexmitQueue::setSackedBit ( uint32_t  fromSeqNum,
uint32_t  toSeqNum 
)
virtual

Called when data sender received selective acknowledgments.

Tells the queue which bytes have been transmitted and SACKed, so they can be skipped if retransmitting segments as long as REXMIT timer did not expired.

178 {
179  if (seqLess(fromSeqNum, begin))
180  fromSeqNum = begin;
181 
182  ASSERT(seqLess(fromSeqNum, end));
183  ASSERT(seqLess(begin, toSeqNum) && seqLE(toSeqNum, end));
184  ASSERT(seqLess(fromSeqNum, toSeqNum));
185 
186  bool found = false;
187 
188  if (!rexmitQueue.empty()) {
189  auto i = rexmitQueue.begin();
190 
191  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, fromSeqNum))
192  i++;
193 
194  ASSERT(i != rexmitQueue.end() && seqLE(i->beginSeqNum, fromSeqNum) && seqLess(fromSeqNum, i->endSeqNum));
195 
196  if (i->beginSeqNum != fromSeqNum) {
197  Region region = *i;
198 
199  region.endSeqNum = fromSeqNum;
200  rexmitQueue.insert(i, region);
201  i->beginSeqNum = fromSeqNum;
202  }
203 
204  while (i != rexmitQueue.end() && seqLE(i->endSeqNum, toSeqNum)) {
205  if (seqGE(i->beginSeqNum, fromSeqNum)) { // Search region in queue!
206  found = true;
207  i->sacked = true; // set sacked bit
208  }
209 
210  i++;
211  }
212 
213  if (i != rexmitQueue.end() && seqLess(i->beginSeqNum, toSeqNum) && seqLess(toSeqNum, i->endSeqNum)) {
214  Region region = *i;
215 
216  region.endSeqNum = toSeqNum;
217  region.sacked = true;
218  rexmitQueue.insert(i, region);
219  i->beginSeqNum = toSeqNum;
220  }
221  }
222 
223  if (!found)
224  EV_DETAIL << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
225 
226  ASSERT(checkQueue());
227 }

Referenced by inet::tcp::TcpConnection::processSACKOption().

◆ str()

std::string inet::tcp::TcpSackRexmitQueue::str ( ) const
virtual

Returns a string for debug purposes.

33 {
34  std::stringstream out;
35 
36  out << "[" << begin << ".." << end << ")";
37  return out.str();
38 }

Referenced by detailedInfo(), and enqueueSentData().

Member Data Documentation

◆ begin

◆ conn

TcpConnection* inet::tcp::TcpSackRexmitQueue::conn

Referenced by TcpSackRexmitQueue().

◆ end

◆ rexmitQueue


The documentation for this class was generated from the following files:
inet::tcp::TcpSackRexmitQueue::str
virtual std::string str() const
Returns a string for debug purposes.
Definition: TcpSackRexmitQueue.cc:32
inet::tcp::TcpSackRexmitQueue::detailedInfo
virtual std::string detailedInfo() const
Prints the current rexmitQueue status for debug purposes.
Definition: TcpSackRexmitQueue.cc:40
inet::tcp::TcpSackRexmitQueue::rexmitQueue
RexmitQueue rexmitQueue
Definition: TcpSackRexmitQueue.h:32
inet::tcp::seqLess
bool seqLess(uint32_t a, uint32_t b)
Definition: TcpHeader.h:21
inet::tcp::seqLE
bool seqLE(uint32_t a, uint32_t b)
Definition: TcpHeader.h:22
inet::tcp::TcpSackRexmitQueue::checkQueue
bool checkQueue() const
Definition: TcpSackRexmitQueue.cc:157
inet::tcp::TcpSackRexmitQueue::end
uint32_t end
Definition: TcpSackRexmitQueue.h:35
inet::tcp::seqGE
bool seqGE(uint32_t a, uint32_t b)
Definition: TcpHeader.h:24
inet::units::values::b
value< int64_t, units::b > b
Definition: Units.h:1241
inet::tcp::TcpSackRexmitQueue::conn
TcpConnection * conn
Definition: TcpSackRexmitQueue.h:22
inet::uint
unsigned int uint
Definition: INETDefs.h:55
inet::tcp::TcpSackRexmitQueue::begin
uint32_t begin
Definition: TcpSackRexmitQueue.h:34