PageRenderTime 54ms CodeModel.GetById 17ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/src/transport/tcp/TCPSACKRexmitQueue.cc

https://github.com/Sorouri/inetmanet
C++ | 341 lines | 270 code | 49 blank | 22 comment | 69 complexity | 500664eb9a7a41d8ff9b08456fca04df MD5 | raw file
  1//
  2// Copyright (C) 2009 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(); // TODO rexmit warnings (delete operator) are still present
 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
 47uint32 TCPSACKRexmitQueue::getBufferEndSeq()
 48{
 49    return end;
 50}
 51
 52void TCPSACKRexmitQueue::discardUpTo(uint32 seqNum)
 53{
 54    if (rexmitQueue.empty())
 55        return;
 56
 57    ASSERT(seqLE(begin,seqNum) && seqLE(seqNum,end));
 58    begin = seqNum;
 59
 60    RexmitQueue::iterator i = rexmitQueue.begin();
 61    while (i!=rexmitQueue.end()) // discard/delete regions from rexmit queue, which have been acked
 62    {
 63        if (seqLess(i->beginSeqNum,begin))
 64            i = rexmitQueue.erase(i);
 65        else
 66            i++;
 67    }
 68
 69    // update begin and end of rexmit queue
 70    if (rexmitQueue.empty())
 71        begin = end = 0;
 72    else
 73    {
 74        i = rexmitQueue.begin();
 75        begin = i->beginSeqNum;
 76        i = rexmitQueue.end();
 77        end = i->endSeqNum;
 78    }
 79}
 80
 81void TCPSACKRexmitQueue::enqueueSentData(uint32 fromSeqNum, uint32 toSeqNum)
 82{
 83    bool found = false;
 84
 85    tcpEV << "rexmitQ: " << str() << " enqueueSentData [" << fromSeqNum << ".." << toSeqNum << ")\n";
 86
 87    Region region;
 88    region.beginSeqNum = fromSeqNum;
 89    region.endSeqNum = toSeqNum;
 90    region.sacked = false;
 91    region.rexmitted = false;
 92
 93    if (getQueueLength()==0)
 94    {
 95        begin = fromSeqNum;
 96        end = toSeqNum;
 97        rexmitQueue.push_back(region);
 98        tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
 99        return;
100    }
101
102    if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
103    {
104        // Search for region in queue!
105        RexmitQueue::iterator i = rexmitQueue.begin();
106        while (i!=rexmitQueue.end())
107        {
108            if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum)
109            {
110                i->rexmitted=true; // set rexmitted bit
111                found = true;
112            }
113            i++;
114        }
115    }
116
117    if (!found)
118    {
119        end = toSeqNum;
120        rexmitQueue.push_back(region);
121    }
122    tcpEV << "rexmitQ: rexmitQLength=" << getQueueLength() << "\n";
123}
124
125void TCPSACKRexmitQueue::setSackedBit(uint32 fromSeqNum, uint32 toSeqNum)
126{
127    bool found = false;
128
129    if (seqLE(begin,fromSeqNum) && seqLE(toSeqNum,end))
130    {
131        RexmitQueue::iterator i = rexmitQueue.begin();
132        while (i!=rexmitQueue.end())
133        {
134            if (i->beginSeqNum == fromSeqNum && i->endSeqNum == toSeqNum) // Search for region in queue!
135            {
136                i->sacked=true; // set sacked bit
137                found = true;
138            }
139            i++;
140        }
141    }
142
143    if (!found)
144        tcpEV << "FAILED to set sacked bit for region: [" << fromSeqNum << ".." << toSeqNum << "). Not found in retransmission queue.\n";
145}
146
147bool TCPSACKRexmitQueue::getSackedBit(uint32 seqNum)
148{
149    bool found = false;
150
151    if (seqLE(begin,seqNum))
152    {
153        RexmitQueue::iterator i = rexmitQueue.begin();
154        while (i!=rexmitQueue.end())
155        {
156            if (i->beginSeqNum == seqNum) // Search for region in queue!
157            {
158                found = i->sacked;
159                break;
160            }
161            i++;
162        }
163    }
164
165	return found;
166}
167
168uint32 TCPSACKRexmitQueue::getQueueLength()
169{
170    return rexmitQueue.size();
171}
172
173uint32 TCPSACKRexmitQueue::getHighestSackedSeqNum()
174{
175    uint32 tmp_highest_sacked = 0;
176
177    RexmitQueue::iterator i = rexmitQueue.begin();
178    while (i!=rexmitQueue.end())
179    {
180        if (i->sacked)
181            tmp_highest_sacked = i->endSeqNum;
182        i++;
183    }
184    return tmp_highest_sacked;
185}
186
187uint32 TCPSACKRexmitQueue::getHighestRexmittedSeqNum()
188{
189    uint32 tmp_highest_rexmitted = 0;
190
191    RexmitQueue::iterator i = rexmitQueue.begin();
192    while (i!=rexmitQueue.end())
193    {
194        if (i->rexmitted)
195            tmp_highest_rexmitted = i->endSeqNum;
196        i++;
197    }
198    return tmp_highest_rexmitted;
199}
200
201uint32 TCPSACKRexmitQueue::checkRexmitQueueForSackedOrRexmittedSegments(uint32 fromSeqNum)
202{
203    uint32 counter = 0;
204
205    if (fromSeqNum==0 || rexmitQueue.empty() || !(seqLE(begin,fromSeqNum) && seqLE(fromSeqNum,end)))
206        return counter;
207
208    RexmitQueue::iterator i = rexmitQueue.begin();
209    while (i!=rexmitQueue.end())
210    {
211        // search for fromSeqNum (snd_nxt)
212        if (i->beginSeqNum == fromSeqNum)
213            break;
214        else
215            i++;
216    }
217
218    // search for adjacent sacked/rexmitted regions
219    while (i!=rexmitQueue.end())
220    {
221        if (i->sacked || i->rexmitted)
222        {
223            counter = counter + (i->endSeqNum - i->beginSeqNum);
224
225            // adjacent regions?
226            uint32 tmp = i->endSeqNum;
227            i++;
228            if (i->beginSeqNum != tmp)
229                break;
230        }
231        else
232            break;
233    }
234    return counter;
235}
236
237void TCPSACKRexmitQueue::resetSackedBit()
238{
239    RexmitQueue::iterator i = rexmitQueue.begin();
240    while (i!=rexmitQueue.end())
241    {
242        i->sacked=false; // reset sacked bit
243        i++;
244    }
245}
246
247void TCPSACKRexmitQueue::resetRexmittedBit()
248{
249    RexmitQueue::iterator i = rexmitQueue.begin();
250    while (i!=rexmitQueue.end())
251    {
252        i->rexmitted=false; // reset rexmitted bit
253        i++;
254    }
255}
256
257uint32 TCPSACKRexmitQueue::getTotalAmountOfSackedBytes()
258{
259    uint32 bytes = 0;
260    uint32 counter = 0;
261
262    RexmitQueue::iterator i = rexmitQueue.begin();
263    while (i!=rexmitQueue.end())
264    {
265        if (i->sacked)
266        {
267        	counter++;
268            bytes = bytes + (i->endSeqNum - i->beginSeqNum);
269        }
270        i++;
271    }
272    return bytes;
273}
274
275uint32 TCPSACKRexmitQueue::getAmountOfSackedBytes(uint32 seqNum)
276{
277    uint32 bytes = 0;
278    uint32 counter = 0;
279
280    if (rexmitQueue.empty() || seqGE(seqNum,end))
281        return counter;
282
283    RexmitQueue::iterator i = rexmitQueue.begin();
284    while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
285    {
286    	i++;
287        if (i->beginSeqNum == seqNum)
288            break;
289    }
290
291	ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
292	
293    while (i!=rexmitQueue.end())
294    {
295        if (i->sacked)
296        {
297        	counter++;
298            bytes = bytes + (i->endSeqNum - i->beginSeqNum);
299        }
300        i++;
301    }
302    return bytes;
303}
304
305
306uint32 TCPSACKRexmitQueue::getNumOfDiscontiguousSacks(uint32 seqNum)
307{
308    uint32 counter = 0;
309
310    if (rexmitQueue.empty() || seqGE(seqNum,end))
311        return counter;
312
313    RexmitQueue::iterator i = rexmitQueue.begin();
314    while (i!=rexmitQueue.end() && seqLess(i->beginSeqNum, seqNum)) // search for seqNum
315    {
316    	i++;
317        if (i->beginSeqNum == seqNum)
318            break;
319    }
320
321	ASSERT(seqLE(seqNum,i->beginSeqNum) || seqGE(seqNum,--i->endSeqNum));
322	
323    // search for discontiguous sacked regions
324    while (i!=rexmitQueue.end())
325    {
326		if (i->sacked)
327		{
328			counter++;
329			uint32 tmp = i->endSeqNum;
330			i++;
331    		while (i->sacked && i->beginSeqNum == tmp && i!=rexmitQueue.end()) // adjacent sacked regions?
332    		{
333    			tmp = i->endSeqNum;
334    			i++;
335			}
336		}
337		else
338			i++;
339    }
340    return counter;
341}