INET Framework for OMNeT++/OMNEST
TCPSACKRexmitQueue.cc
Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2009-2010 Thomas Reschka
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 
00019 #include "TCPSACKRexmitQueue.h"
00020 
00021 
00022 TCPSACKRexmitQueue::TCPSACKRexmitQueue()
00023 {
00024     conn = NULL;
00025     begin = end = 0;
00026 }
00027 
00028 TCPSACKRexmitQueue::~TCPSACKRexmitQueue()
00029 {
00030     while (!rexmitQueue.empty())
00031         rexmitQueue.pop_front();
00032 }
00033 
00034 void TCPSACKRexmitQueue::init(uint32 seqNum)
00035 {
00036     begin = seqNum;
00037     end = seqNum;
00038 }
00039 
00040 std::string TCPSACKRexmitQueue::str() const
00041 {
00042     std::stringstream out;
00043     out << "[" << begin << ".." << end << ")";
00044     return out.str();
00045 }
00046 
00047 void TCPSACKRexmitQueue::info()
00048 {
00049     str();
00050     RexmitQueue::iterator i = rexmitQueue.begin();
00051     uint j = 1;
00052     while (i!=rexmitQueue.end())
00053     {
00054         tcpEV << j << ". region: [" << i->beginSeqNum << ".." << i->endSeqNum << ") \t sacked=" << i->sacked << "\t rexmitted=" << i->rexmitted << "\n";
00055         i++;
00056         j++;
00057     }
00058 }
00059 
00060 uint32 TCPSACKRexmitQueue::getBufferStartSeq()
00061 {
00062     return begin;
00063 }
00064 
00065 uint32 TCPSACKRexmitQueue::getBufferEndSeq()
00066 {
00067     return end;
00068 }
00069 
00070 void TCPSACKRexmitQueue::discardUpTo(uint32 seqNum)
00071 {
00072     if (rexmitQueue.empty())
00073         return;
00074 
00075     ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end));
00076     begin = seqNum;
00077 
00078     RexmitQueue::iterator i = rexmitQueue.begin();
00079     while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked
00080     {
00081         if (seqLess(i->beginSeqNum,begin))
00082             i = rexmitQueue.erase(i);
00083         else
00084             i++;
00085     }
00086 
00087     // update begin and end of rexmit queue
00088     if (rexmitQueue.empty())
00089         begin = end = 0;
00090     else
00091     {
00092         i = rexmitQueue.begin();
00093         begin = i->beginSeqNum;
00094         i = rexmitQueue.end();
00095         end = i->endSeqNum;
00096     }
00097 }
00098 
00099 void TCPSACKRexmitQueue::enqueueSentData(uint32 fromSeqNum, uint32 toSeqNum)
00100 {
00101     bool found = false;
00102 
00103     tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
00104 
00105     Region region;
00106     region.beginSeqNum = fromSeqNum;
00107     region.endSeqNum = toSeqNum;
00108     region.sacked = false;
00109     region.rexmitted = false;
00110 
00111     if (getQueueLength()==0)
00112     {
00113         begin = fromSeqNum;
00114         end = toSeqNum;
00115         rexmitQueue.push_back(region);
00116 //        tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
00117         return;
00118     }
00119 
00120     if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
00121     {
00122         // Search for region in queue!
00123         RexmitQueue::iterator i = rexmitQueue.begin();
00124         while (i!=rexmitQueue.end())
00125         {
00126             if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum)
00127             {
00128                 i->rexmitted = true; // set rexmitted bit
00129                 found = true;
00130             }
00131             i++;
00132         }
00133     }
00134 
00135     if (!found)
00136     {
00137         end = toSeqNum;
00138         rexmitQueue.push_back(region);
00139     }
00140 //    tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
00141 }
00142 
00143 void TCPSACKRexmitQueue::setSackedBit(uint32 fromSeqNum, uint32 toSeqNum)
00144 {
00145     bool found = false;
00146 
00147     if (seqLE(toSeqNum,end))
00148     {
00149         RexmitQueue::iterator i = rexmitQueue.begin();
00150         while (i!=rexmitQueue.end())
00151         {
00152             if (i->beginSeqNum == fromSeqNum && seqGE(toSeqNum, i->endSeqNum)) // Search for LE of region in queue!
00153             {
00154                 i->sacked = true; // set sacked bit
00155                 found = true;
00156                 i++;
00157                 while (seqGE(toSeqNum, i->endSeqNum) && i!=rexmitQueue.end()) // Search for RE of region in queue!
00158                 {
00159                     i->sacked = true; // set sacked bit
00160                     i++;
00161                 }
00162             }
00163             else
00164                 i++;
00165         }
00166     }
00167 
00168     if (!found)
00169         tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
00170 }
00171 
00172 bool TCPSACKRexmitQueue::getSackedBit(uint32 seqNum)
00173 {
00174     bool found = false;
00175 
00176     if (seqLE(begin,seqNum))
00177     {
00178         RexmitQueue::iterator i = rexmitQueue.begin();
00179         while (i!=rexmitQueue.end())
00180         {
00181             if (i->beginSeqNum == seqNum) // Search for region in queue!
00182             {
00183                 found = i->sacked;
00184                 break;
00185             }
00186             i++;
00187         }
00188     }
00189     return found;
00190 }
00191 
00192 uint32 TCPSACKRexmitQueue::getQueueLength()
00193 {
00194     return rexmitQueue.size();
00195 }
00196 
00197 uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum()
00198 {
00199     uint32 tmp_highest_sacked = 0;
00200 
00201     RexmitQueue::iterator i = rexmitQueue.begin();
00202     while (i!=rexmitQueue.end())
00203     {
00204         if (i->sacked)
00205             tmp_highest_sacked = i->endSeqNum;
00206         i++;
00207     }
00208     return tmp_highest_sacked;
00209 }
00210 
00211 uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum()
00212 {
00213     uint32 tmp_highest_rexmitted = 0;
00214 
00215     RexmitQueue::iterator i = rexmitQueue.begin();
00216     while (i!=rexmitQueue.end())
00217     {
00218         if (i->rexmitted)
00219             tmp_highest_rexmitted = i->endSeqNum;
00220         i++;
00221     }
00222     return tmp_highest_rexmitted;
00223 }
00224 
00225 uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments(uint32 fromSeqNum)
00226 {
00227     uint32 counter = 0;
00228 
00229     if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end)))
00230         return counter;
00231 
00232     RexmitQueue::iterator i = rexmitQueue.begin();
00233     while (i!=rexmitQueue.end())
00234     {
00235         // search for fromSeqNum (snd_nxt)
00236         if (i->beginSeqNum == fromSeqNum)
00237             break;
00238         else
00239             i++;
00240     }
00241 
00242     // search for adjacent sacked/rexmitted regions
00243     while (i!=rexmitQueue.end())
00244     {
00245         if (i->sacked || i->rexmitted)
00246         {
00247             counter = counter + (i->endSeqNum - i->beginSeqNum);
00248 
00249             // adjacent regions?
00250             uint32 tmp = i->endSeqNum;
00251             i++;
00252             if (i->beginSeqNum != tmp)
00253                 break;
00254         }
00255         else
00256             break;
00257     }
00258     return counter;
00259 }
00260 
00261 void TCPSACKRexmitQueue::resetSackedBit()
00262 {
00263     RexmitQueue::iterator i = rexmitQueue.begin();
00264     while (i!=rexmitQueue.end())
00265     {
00266         i->sacked = false; // reset sacked bit
00267         i++;
00268     }
00269 }
00270 
00271 void TCPSACKRexmitQueue::resetRexmittedBit()
00272 {
00273     RexmitQueue::iterator i = rexmitQueue.begin();
00274     while (i!=rexmitQueue.end())
00275     {
00276         i->rexmitted = false; // reset rexmitted bit
00277         i++;
00278     }
00279 }
00280 
00281 uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes()
00282 {
00283     uint32 bytes = 0;
00284     uint32 counter = 0;
00285 
00286     RexmitQueue::iterator i = rexmitQueue.begin();
00287     while (i!=rexmitQueue.end())
00288     {
00289         if (i->sacked)
00290         {
00291             counter++;
00292             bytes = bytes + (i->endSeqNum - i->beginSeqNum);
00293         }
00294         i++;
00295     }
00296     return bytes;
00297 }
00298 
00299 uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes(uint32 seqNum)
00300 {
00301     uint32 bytes = 0;
00302     uint32 counter = 0;
00303 
00304     if (rexmitQueue.empty() || seqGE(seqNum,end))
00305         return counter;
00306 
00307     RexmitQueue::iterator i = rexmitQueue.begin();
00308     while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
00309     {
00310         i++;
00311         if (i->beginSeqNum == seqNum)
00312             break;
00313     }
00314 
00315     ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
00316 
00317     while (i!=rexmitQueue.end())
00318     {
00319         if (i->sacked)
00320         {
00321             counter++;
00322             bytes = bytes + (i->endSeqNum - i->beginSeqNum);
00323         }
00324         i++;
00325     }
00326     return bytes;
00327 }
00328 
00329 
00330 uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks(uint32 seqNum)
00331 {
00332     uint32 counter = 0;
00333 
00334     if (rexmitQueue.empty() || seqGE(seqNum,end))
00335         return counter;
00336 
00337     RexmitQueue::iterator i = rexmitQueue.begin();
00338     while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
00339     {
00340         i++;
00341         if (i->beginSeqNum == seqNum)
00342             break;
00343     }
00344 
00345     ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
00346 
00347     // search for discontiguous sacked regions
00348     while (i!=rexmitQueue.end())
00349     {
00350         if (i->sacked)
00351         {
00352             counter++;
00353             uint32 tmp = i->endSeqNum;
00354             i++;
00355             while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions?
00356             {
00357                 tmp = i->endSeqNum;
00358                 i++;
00359             }
00360         }
00361         else
00362             i++;
00363     }
00364     return counter;
00365 }