PageRenderTime 225ms CodeModel.GetById 30ms app.highlight 161ms RepoModel.GetById 21ms app.codeStats 0ms

/INET-OverSim-20101019/src/transport/tcp/TCPSACKRexmitQueue.cc

https://bitbucket.org/indigopony/omnetproject
C++ | 365 lines | 291 code | 50 blank | 24 comment | 70 complexity | 78f74b60cb7d7c81195287d2468c29d4 MD5 | raw file
  1//
  2// Copyright (C) 2009-2010 Thomas Reschka
  3//
  4// This program is free software; you can redistribute it and/or
  5// modify it under the terms of the GNU Lesser General Public License
  6// as published by the Free Software Foundation; either version 2
  7// of the License, or (at your option) any later version.
  8//
  9// This program is distributed in the hope that it will be useful,
 10// but WITHOUT ANY WARRANTY; without even the implied warranty of
 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12// GNU Lesser General Public License for more details.
 13//
 14// You should have received a copy of the GNU Lesser General Public License
 15// along with this program; if not, see <http://www.gnu.org/licenses/>.
 16//
 17
 18
 19#include "TCPSACKRexmitQueue.h"
 20
 21
 22TCPSACKRexmitQueue::TCPSACKRexmitQueue()
 23{
 24    conn = NULL;
 25    begin = end = 0;
 26}
 27
 28TCPSACKRexmitQueue::~TCPSACKRexmitQueue()
 29{
 30    while (!rexmitQueue.empty())
 31        rexmitQueue.pop_front();
 32}
 33
 34void TCPSACKRexmitQueue::init(uint32 seqNum)
 35{
 36    begin = seqNum;
 37    end = seqNum;
 38}
 39
 40std::string TCPSACKRexmitQueue::str() const
 41{
 42    std::stringstream out;
 43    out << "[" << begin << ".." << end << ")";
 44    return out.str();
 45}
 46
 47void TCPSACKRexmitQueue::info()
 48{
 49    str();
 50    RexmitQueue::iterator i = rexmitQueue.begin();
 51    uint j = 1;
 52    while (i!=rexmitQueue.end())
 53    {
 54        tcpEV << j << ". region: [" << i->beginSeqNum << ".." << i->endSeqNum << ") \t sacked=" << i->sacked << "\t rexmitted=" << i->rexmitted << "\n";
 55        i++;
 56        j++;
 57    }
 58}
 59
 60uint32 TCPSACKRexmitQueue::getBufferStartSeq()
 61{
 62    return begin;
 63}
 64
 65uint32 TCPSACKRexmitQueue::getBufferEndSeq()
 66{
 67    return end;
 68}
 69
 70void TCPSACKRexmitQueue::discardUpTo(uint32 seqNum)
 71{
 72    if (rexmitQueue.empty())
 73        return;
 74
 75    ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end));
 76    begin = seqNum;
 77
 78    RexmitQueue::iterator i = rexmitQueue.begin();
 79    while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked
 80    {
 81        if (seqLess(i->beginSeqNum,begin))
 82            i = rexmitQueue.erase(i);
 83        else
 84            i++;
 85    }
 86
 87    // update begin and end of rexmit queue
 88    if (rexmitQueue.empty())
 89        begin = end = 0;
 90    else
 91    {
 92        i = rexmitQueue.begin();
 93        begin = i->beginSeqNum;
 94        i = rexmitQueue.end();
 95        end = i->endSeqNum;
 96    }
 97}
 98
 99void TCPSACKRexmitQueue::enqueueSentData(uint32 fromSeqNum, uint32 toSeqNum)
100{
101    bool found = false;
102
103    tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
104
105    Region region;
106    region.beginSeqNum = fromSeqNum;
107    region.endSeqNum = toSeqNum;
108    region.sacked = false;
109    region.rexmitted = false;
110
111    if (getQueueLength()==0)
112    {
113        begin = fromSeqNum;
114        end = toSeqNum;
115        rexmitQueue.push_back(region);
116//        tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
117        return;
118    }
119
120    if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
121    {
122        // Search for region in queue!
123        RexmitQueue::iterator i = rexmitQueue.begin();
124        while (i!=rexmitQueue.end())
125        {
126            if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum)
127            {
128                i->rexmitted = true; // set rexmitted bit
129                found = true;
130            }
131            i++;
132        }
133    }
134
135    if (!found)
136    {
137        end = toSeqNum;
138        rexmitQueue.push_back(region);
139    }
140//    tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
141}
142
143void TCPSACKRexmitQueue::setSackedBit(uint32 fromSeqNum, uint32 toSeqNum)
144{
145    bool found = false;
146
147    if (seqLE(toSeqNum,end))
148    {
149        RexmitQueue::iterator i = rexmitQueue.begin();
150        while (i!=rexmitQueue.end())
151        {
152            if (i->beginSeqNum == fromSeqNum && seqGE(toSeqNum, i->endSeqNum)) // Search for LE of region in queue!
153            {
154                i->sacked = true; // set sacked bit
155                found = true;
156                i++;
157                while (seqGE(toSeqNum, i->endSeqNum) && i!=rexmitQueue.end()) // Search for RE of region in queue!
158                {
159                    i->sacked = true; // set sacked bit
160                    i++;
161                }
162            }
163            else
164                i++;
165        }
166    }
167
168    if (!found)
169        tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
170}
171
172bool TCPSACKRexmitQueue::getSackedBit(uint32 seqNum)
173{
174    bool found = false;
175
176    if (seqLE(begin,seqNum))
177    {
178        RexmitQueue::iterator i = rexmitQueue.begin();
179        while (i!=rexmitQueue.end())
180        {
181            if (i->beginSeqNum == seqNum) // Search for region in queue!
182            {
183                found = i->sacked;
184                break;
185            }
186            i++;
187        }
188    }
189    return found;
190}
191
192uint32 TCPSACKRexmitQueue::getQueueLength()
193{
194    return rexmitQueue.size();
195}
196
197uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum()
198{
199    uint32 tmp_highest_sacked = 0;
200
201    RexmitQueue::iterator i = rexmitQueue.begin();
202    while (i!=rexmitQueue.end())
203    {
204        if (i->sacked)
205            tmp_highest_sacked = i->endSeqNum;
206        i++;
207    }
208    return tmp_highest_sacked;
209}
210
211uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum()
212{
213    uint32 tmp_highest_rexmitted = 0;
214
215    RexmitQueue::iterator i = rexmitQueue.begin();
216    while (i!=rexmitQueue.end())
217    {
218        if (i->rexmitted)
219            tmp_highest_rexmitted = i->endSeqNum;
220        i++;
221    }
222    return tmp_highest_rexmitted;
223}
224
225uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments(uint32 fromSeqNum)
226{
227    uint32 counter = 0;
228
229    if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end)))
230        return counter;
231
232    RexmitQueue::iterator i = rexmitQueue.begin();
233    while (i!=rexmitQueue.end())
234    {
235        // search for fromSeqNum (snd_nxt)
236        if (i->beginSeqNum == fromSeqNum)
237            break;
238        else
239            i++;
240    }
241
242    // search for adjacent sacked/rexmitted regions
243    while (i!=rexmitQueue.end())
244    {
245        if (i->sacked || i->rexmitted)
246        {
247            counter = counter + (i->endSeqNum - i->beginSeqNum);
248
249            // adjacent regions?
250            uint32 tmp = i->endSeqNum;
251            i++;
252            if (i->beginSeqNum != tmp)
253                break;
254        }
255        else
256            break;
257    }
258    return counter;
259}
260
261void TCPSACKRexmitQueue::resetSackedBit()
262{
263    RexmitQueue::iterator i = rexmitQueue.begin();
264    while (i!=rexmitQueue.end())
265    {
266        i->sacked = false; // reset sacked bit
267        i++;
268    }
269}
270
271void TCPSACKRexmitQueue::resetRexmittedBit()
272{
273    RexmitQueue::iterator i = rexmitQueue.begin();
274    while (i!=rexmitQueue.end())
275    {
276        i->rexmitted = false; // reset rexmitted bit
277        i++;
278    }
279}
280
281uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes()
282{
283    uint32 bytes = 0;
284    uint32 counter = 0;
285
286    RexmitQueue::iterator i = rexmitQueue.begin();
287    while (i!=rexmitQueue.end())
288    {
289        if (i->sacked)
290        {
291            counter++;
292            bytes = bytes + (i->endSeqNum - i->beginSeqNum);
293        }
294        i++;
295    }
296    return bytes;
297}
298
299uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes(uint32 seqNum)
300{
301    uint32 bytes = 0;
302    uint32 counter = 0;
303
304    if (rexmitQueue.empty() || seqGE(seqNum,end))
305        return counter;
306
307    RexmitQueue::iterator i = rexmitQueue.begin();
308    while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
309    {
310        i++;
311        if (i->beginSeqNum == seqNum)
312            break;
313    }
314
315    ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
316
317    while (i!=rexmitQueue.end())
318    {
319        if (i->sacked)
320        {
321            counter++;
322            bytes = bytes + (i->endSeqNum - i->beginSeqNum);
323        }
324        i++;
325    }
326    return bytes;
327}
328
329
330uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks(uint32 seqNum)
331{
332    uint32 counter = 0;
333
334    if (rexmitQueue.empty() || seqGE(seqNum,end))
335        return counter;
336
337    RexmitQueue::iterator i = rexmitQueue.begin();
338    while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
339    {
340        i++;
341        if (i->beginSeqNum == seqNum)
342            break;
343    }
344
345    ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
346
347    // search for discontiguous sacked regions
348    while (i!=rexmitQueue.end())
349    {
350        if (i->sacked)
351        {
352            counter++;
353            uint32 tmp = i->endSeqNum;
354            i++;
355            while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions?
356            {
357                tmp = i->endSeqNum;
358                i++;
359            }
360        }
361        else
362            i++;
363    }
364    return counter;
365}