INET Framework for OMNeT++/OMNEST
|
#include <TCPSACKRexmitQueue.h>
Classes | |
struct | Region |
Public Types | |
typedef std::list< Region > | RexmitQueue |
Public Member Functions | |
TCPSACKRexmitQueue () | |
virtual | ~TCPSACKRexmitQueue () |
virtual void | setConnection (TCPConnection *_conn) |
virtual void | init (uint32 seqNum) |
virtual std::string | str () const |
virtual void | info () |
virtual uint32 | getBufferStartSeq () |
virtual uint32 | getBufferEndSeq () |
virtual void | discardUpTo (uint32 seqNum) |
virtual void | enqueueSentData (uint32 fromSeqNum, uint32 toSeqNum) |
virtual void | setSackedBit (uint32 fromSeqNum, uint32 toSeqNum) |
virtual bool | getSackedBit (uint32 seqNum) |
virtual uint32 | getQueueLength () |
virtual uint32 | getHighestSackedSeqNum () |
virtual uint32 | getHighestRexmittedSeqNum () |
virtual uint32 | checkRexmitQueueForSackedOrRexmittedSegments (uint32 fromSeq) |
virtual void | resetSackedBit () |
virtual void | resetRexmittedBit () |
virtual uint32 | getTotalAmountOfSackedBytes () |
virtual uint32 | getAmountOfSackedBytes (uint32 seqNum) |
virtual uint32 | getNumOfDiscontiguousSacks (uint32 seqNum) |
Public Attributes | |
TCPConnection * | conn |
RexmitQueue | rexmitQueue |
uint32 | begin |
uint32 | end |
Retransmission data for SACK.
typedef std::list<Region> TCPSACKRexmitQueue::RexmitQueue |
TCPSACKRexmitQueue::~TCPSACKRexmitQueue | ( | ) | [virtual] |
Virtual dtor.
{ while (!rexmitQueue.empty()) rexmitQueue.pop_front(); }
uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments | ( | uint32 | fromSeq | ) | [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.
Referenced by TCPConnection::sendSegment().
{ uint32 counter = 0; if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end))) return counter; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { // search for fromSeqNum (snd_nxt) if (i->beginSeqNum == fromSeqNum) break; else i++; } // search for adjacent sacked/rexmitted regions while (i!=rexmitQueue.end()) { if (i->sacked || i->rexmitted) { counter = counter + (i->endSeqNum - i->beginSeqNum); // adjacent regions? uint32 tmp = i->endSeqNum; i++; if (i->beginSeqNum != tmp) break; } else break; } return counter; }
void TCPSACKRexmitQueue::discardUpTo | ( | uint32 | 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.
Referenced by TCPConnection::processAckInEstabEtc(), TCPConnection::processRstInSynReceived(), and TCPConnection::processSegmentInSynSent().
{ if (rexmitQueue.empty()) return; ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end)); begin = seqNum; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked { if (seqLess(i->beginSeqNum,begin)) i = rexmitQueue.erase(i); else i++; } // update begin and end of rexmit queue if (rexmitQueue.empty()) begin = end = 0; else { i = rexmitQueue.begin(); begin = i->beginSeqNum; i = rexmitQueue.end(); end = i->endSeqNum; } }
void TCPSACKRexmitQueue::enqueueSentData | ( | uint32 | fromSeqNum, |
uint32 | toSeqNum | ||
) | [virtual] |
Inserts sent data to the rexmit queue.
Referenced by TCPConnection::sendSegment().
{ bool found = false; tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n"; Region region; region.beginSeqNum = fromSeqNum; region.endSeqNum = toSeqNum; region.sacked = false; region.rexmitted = false; if (getQueueLength()==0) { begin = fromSeqNum; end = toSeqNum; rexmitQueue.push_back(region); // tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n"; return; } if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end)) { // Search for region in queue! RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum) { i->rexmitted = true; // set rexmitted bit found = true; } i++; } } if (!found) { end = toSeqNum; rexmitQueue.push_back(region); } // tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n"; }
uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes | ( | uint32 | seqNum | ) | [virtual] |
Returns amount of sacked bytes above seqNum.
Referenced by TCPConnection::isLost().
{ uint32 bytes = 0; uint32 counter = 0; if (rexmitQueue.empty() || seqGE(seqNum,end)) return counter; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum { i++; if (i->beginSeqNum == seqNum) break; } ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum)); while (i!=rexmitQueue.end()) { if (i->sacked) { counter++; bytes = bytes + (i->endSeqNum - i->beginSeqNum); } i++; } return bytes; }
uint32 TCPSACKRexmitQueue::getBufferEndSeq | ( | ) | [virtual] |
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.)
Referenced by TCPConnection::processRstInSynReceived().
{ return end; }
uint32 TCPSACKRexmitQueue::getBufferStartSeq | ( | ) | [virtual] |
Returns the sequence number of the first byte stored in the buffer.
{ return begin; }
uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum | ( | ) | [virtual] |
Returns the highest sequence number rexmitted by data sender.
Referenced by TCPConnection::nextSeg(), TCPConnection::retransmitOneSegment(), TCPConnection::sendData(), TCPConnection::sendSegmentDuringLossRecoveryPhase(), and TCPConnection::setPipe().
{ uint32 tmp_highest_rexmitted = 0; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->rexmitted) tmp_highest_rexmitted = i->endSeqNum; i++; } return tmp_highest_rexmitted; }
uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum | ( | ) | [virtual] |
Returns the highest sequence number sacked by data receiver.
Referenced by TCPConnection::nextSeg().
{ uint32 tmp_highest_sacked = 0; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->sacked) tmp_highest_sacked = i->endSeqNum; i++; } return tmp_highest_sacked; }
uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks | ( | uint32 | seqNum | ) | [virtual] |
Returns the number of discontiguous sacked regions (SACKed sequences) above seqNum.
Referenced by TCPConnection::isLost().
{ uint32 counter = 0; if (rexmitQueue.empty() || seqGE(seqNum,end)) return counter; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum { i++; if (i->beginSeqNum == seqNum) break; } ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum)); // search for discontiguous sacked regions while (i!=rexmitQueue.end()) { if (i->sacked) { counter++; uint32 tmp = i->endSeqNum; i++; while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions? { tmp = i->endSeqNum; i++; } } else i++; } return counter; }
uint32 TCPSACKRexmitQueue::getQueueLength | ( | ) | [virtual] |
Returns the number of blocks currently buffered in queue.
Referenced by enqueueSentData().
{ return rexmitQueue.size(); }
bool TCPSACKRexmitQueue::getSackedBit | ( | uint32 | seqNum | ) | [virtual] |
Returns SackedBit value of seqNum.
Referenced by TCPConnection::nextSeg(), and TCPConnection::setPipe().
{ bool found = false; if (seqLE(begin,seqNum)) { RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->beginSeqNum == seqNum) // Search for region in queue! { found = i->sacked; break; } i++; } } return found; }
uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes | ( | ) | [virtual] |
Returns total amount of sacked bytes. Corresponds to update() function from RFC 3517.
Referenced by TCPConnection::processSACKOption().
{ uint32 bytes = 0; uint32 counter = 0; RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->sacked) { counter++; bytes = bytes + (i->endSeqNum - i->beginSeqNum); } i++; } return bytes; }
void TCPSACKRexmitQueue::info | ( | ) | [virtual] |
Prints the current rexmitQueue status for debug purposes.
{ str(); RexmitQueue::iterator i = rexmitQueue.begin(); uint j = 1; while (i!=rexmitQueue.end()) { tcpEV << j << ". region: [" << i->beginSeqNum << ".." << i->endSeqNum << ") \t sacked=" << i->sacked << "\t rexmitted=" << i->rexmitted << "\n"; i++; j++; } }
void TCPSACKRexmitQueue::init | ( | uint32 | 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.
Referenced by TCPConnection::selectInitialSeqNum().
void TCPSACKRexmitQueue::resetRexmittedBit | ( | ) | [virtual] |
Called when REXMIT timer expired. Resets rexmitted bit of all segments in rexmit queue.
Referenced by TCPBaseAlg::processRexmitTimer().
{ RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { i->rexmitted = false; // reset rexmitted bit i++; } }
void TCPSACKRexmitQueue::resetSackedBit | ( | ) | [virtual] |
Called when REXMIT timer expired. Resets sacked bit of all segments in rexmit queue.
Referenced by TCPBaseAlg::processRexmitTimer().
{ RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { i->sacked = false; // reset sacked bit i++; } }
virtual void TCPSACKRexmitQueue::setConnection | ( | TCPConnection * | _conn | ) | [inline, virtual] |
Set the connection that owns this queue.
Referenced by TCPConnection::cloneListeningConnection(), and TCPConnection::initConnection().
{conn = _conn;}
void TCPSACKRexmitQueue::setSackedBit | ( | uint32 | fromSeqNum, |
uint32 | 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.
Referenced by TCPConnection::processSACKOption().
{ bool found = false; if (seqLE(toSeqNum,end)) { RexmitQueue::iterator i = rexmitQueue.begin(); while (i!=rexmitQueue.end()) { if (i->beginSeqNum == fromSeqNum && seqGE(toSeqNum, i->endSeqNum)) // Search for LE of region in queue! { i->sacked = true; // set sacked bit found = true; i++; while (seqGE(toSeqNum, i->endSeqNum) && i!=rexmitQueue.end()) // Search for RE of region in queue! { i->sacked = true; // set sacked bit i++; } } else i++; } } if (!found) tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n"; }
std::string TCPSACKRexmitQueue::str | ( | ) | const [virtual] |
Returns a string for debug purposes.
Referenced by enqueueSentData(), and info().
uint32 TCPSACKRexmitQueue::begin |
Referenced by TCPSACKRexmitQueue().
uint32 TCPSACKRexmitQueue::end |
Referenced by checkRexmitQueueForSackedOrRexmittedSegments(), discardUpTo(), enqueueSentData(), getAmountOfSackedBytes(), getHighestRexmittedSeqNum(), getHighestSackedSeqNum(), getNumOfDiscontiguousSacks(), getQueueLength(), getSackedBit(), getTotalAmountOfSackedBytes(), info(), resetRexmittedBit(), resetSackedBit(), setSackedBit(), and ~TCPSACKRexmitQueue().