A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
red-queue.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright © 2011 Marcos Talau
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation;
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 General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*
18
* Author: Marcos Talau (talau@users.sourceforge.net)
19
*
20
* Thanks to: Duy Nguyen<duy@soe.ucsc.edu> by RED efforts in NS3
21
*
22
*
23
* This file incorporates work covered by the following copyright and
24
* permission notice:
25
*
26
* Copyright (c) 1990-1997 Regents of the University of California.
27
* All rights reserved.
28
*
29
* Redistribution and use in source and binary forms, with or without
30
* modification, are permitted provided that the following conditions
31
* are met:
32
* 1. Redistributions of source code must retain the above copyright
33
* notice, this list of conditions and the following disclaimer.
34
* 2. Redistributions in binary form must reproduce the above copyright
35
* notice, this list of conditions and the following disclaimer in the
36
* documentation and/or other materials provided with the distribution.
37
* 3. Neither the name of the University nor of the Laboratory may be used
38
* to endorse or promote products derived from this software without
39
* specific prior written permission.
40
*
41
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
* SUCH DAMAGE.
52
*/
53
54
/*
55
* PORT NOTE: This code was ported from ns-2 (queue/red.cc). Almost all
56
* comments have also been ported from NS-2
57
*/
58
59
#include "ns3/log.h"
60
#include "ns3/enum.h"
61
#include "ns3/uinteger.h"
62
#include "ns3/double.h"
63
#include "ns3/simulator.h"
64
#include "ns3/abort.h"
65
#include "ns3/random-variable-stream.h"
66
#include "
red-queue.h
"
67
68
NS_LOG_COMPONENT_DEFINE
(
"RedQueue"
);
69
70
namespace
ns3 {
71
72
NS_OBJECT_ENSURE_REGISTERED
(RedQueue);
73
74
TypeId
RedQueue::GetTypeId
(
void
)
75
{
76
static
TypeId
tid =
TypeId
(
"ns3::RedQueue"
)
77
.
SetParent
<
Queue
> ()
78
.AddConstructor<RedQueue> ()
79
.AddAttribute (
"Mode"
,
80
"Determines unit for QueueLimit"
,
81
EnumValue
(
QUEUE_MODE_PACKETS
),
82
MakeEnumAccessor
(&
RedQueue::SetMode
),
83
MakeEnumChecker
(
QUEUE_MODE_BYTES
,
"QUEUE_MODE_BYTES"
,
84
QUEUE_MODE_PACKETS
,
"QUEUE_MODE_PACKETS"
))
85
.AddAttribute (
"MeanPktSize"
,
86
"Average of packet size"
,
87
UintegerValue
(500),
88
MakeUintegerAccessor (&
RedQueue::m_meanPktSize
),
89
MakeUintegerChecker<uint32_t> ())
90
.AddAttribute (
"IdlePktSize"
,
91
"Average packet size used during idle times. Used when m_cautions = 3"
,
92
UintegerValue
(0),
93
MakeUintegerAccessor (&
RedQueue::m_idlePktSize
),
94
MakeUintegerChecker<uint32_t> ())
95
.AddAttribute (
"Wait"
,
96
"True for waiting between dropped packets"
,
97
BooleanValue
(
true
),
98
MakeBooleanAccessor (&
RedQueue::m_isWait
),
99
MakeBooleanChecker ())
100
.AddAttribute (
"Gentle"
,
101
"True to increases dropping probability slowly when average queue exceeds maxthresh"
,
102
BooleanValue
(
true
),
103
MakeBooleanAccessor (&
RedQueue::m_isGentle
),
104
MakeBooleanChecker ())
105
.AddAttribute (
"MinTh"
,
106
"Minimum average length threshold in packets/bytes"
,
107
DoubleValue
(5),
108
MakeDoubleAccessor (&
RedQueue::m_minTh
),
109
MakeDoubleChecker<double> ())
110
.AddAttribute (
"MaxTh"
,
111
"Maximum average length threshold in packets/bytes"
,
112
DoubleValue
(15),
113
MakeDoubleAccessor (&
RedQueue::m_maxTh
),
114
MakeDoubleChecker<double> ())
115
.AddAttribute (
"QueueLimit"
,
116
"Queue limit in bytes/packets"
,
117
UintegerValue
(25),
118
MakeUintegerAccessor (&
RedQueue::m_queueLimit
),
119
MakeUintegerChecker<uint32_t> ())
120
.AddAttribute (
"QW"
,
121
"Queue weight related to the exponential weighted moving average (EWMA)"
,
122
DoubleValue
(0.002),
123
MakeDoubleAccessor (&
RedQueue::m_qW
),
124
MakeDoubleChecker <double> ())
125
.AddAttribute (
"LInterm"
,
126
"The maximum probability of dropping a packet"
,
127
DoubleValue
(50),
128
MakeDoubleAccessor (&
RedQueue::m_lInterm
),
129
MakeDoubleChecker <double> ())
130
.AddAttribute (
"Ns1Compat"
,
131
"NS-1 compatibility"
,
132
BooleanValue
(
false
),
133
MakeBooleanAccessor (&
RedQueue::m_isNs1Compat
),
134
MakeBooleanChecker ())
135
.AddAttribute (
"LinkBandwidth"
,
136
"The RED link bandwidth"
,
137
DataRateValue
(
DataRate
(
"1.5Mbps"
)),
138
MakeDataRateAccessor (&
RedQueue::m_linkBandwidth
),
139
MakeDataRateChecker ())
140
.AddAttribute (
"LinkDelay"
,
141
"The RED link delay"
,
142
TimeValue
(
MilliSeconds
(20)),
143
MakeTimeAccessor (&
RedQueue::m_linkDelay
),
144
MakeTimeChecker ())
145
;
146
147
return
tid;
148
}
149
150
RedQueue::RedQueue
() :
151
Queue
(),
152
m_packets (),
153
m_bytesInQueue (0),
154
m_hasRedStarted (false)
155
{
156
NS_LOG_FUNCTION
(
this
);
157
m_uv
= CreateObject<UniformRandomVariable> ();
158
}
159
160
RedQueue::~RedQueue
()
161
{
162
NS_LOG_FUNCTION
(
this
);
163
}
164
165
void
166
RedQueue::SetMode
(
RedQueue::QueueMode
mode)
167
{
168
NS_LOG_FUNCTION
(
this
<< mode);
169
m_mode
= mode;
170
}
171
172
RedQueue::QueueMode
173
RedQueue::GetMode
(
void
)
174
{
175
NS_LOG_FUNCTION
(
this
);
176
return
m_mode
;
177
}
178
179
void
180
RedQueue::SetQueueLimit
(uint32_t lim)
181
{
182
NS_LOG_FUNCTION
(
this
<<lim);
183
m_queueLimit
= lim;
184
}
185
186
void
187
RedQueue::SetTh
(
double
minTh,
double
maxTh)
188
{
189
NS_LOG_FUNCTION
(
this
<< minTh << maxTh);
190
NS_ASSERT
(minTh <= maxTh);
191
m_minTh
= minTh;
192
m_maxTh
= maxTh;
193
}
194
195
RedQueue::Stats
196
RedQueue::GetStats
()
197
{
198
NS_LOG_FUNCTION
(
this
);
199
return
m_stats
;
200
}
201
202
int64_t
203
RedQueue::AssignStreams
(int64_t stream)
204
{
205
NS_LOG_FUNCTION
(
this
<< stream);
206
m_uv
->
SetStream
(stream);
207
return
1;
208
}
209
210
bool
211
RedQueue::DoEnqueue
(
Ptr<Packet>
p)
212
{
213
NS_LOG_FUNCTION
(
this
<< p);
214
215
if
(!
m_hasRedStarted
)
216
{
217
NS_LOG_INFO
(
"Initializing RED params."
);
218
InitializeParams
();
219
m_hasRedStarted
=
true
;
220
}
221
222
uint32_t nQueued = 0;
223
224
if
(
GetMode
() ==
QUEUE_MODE_BYTES
)
225
{
226
NS_LOG_DEBUG
(
"Enqueue in bytes mode"
);
227
nQueued =
m_bytesInQueue
;
228
}
229
else
if
(
GetMode
() ==
QUEUE_MODE_PACKETS
)
230
{
231
NS_LOG_DEBUG
(
"Enqueue in packets mode"
);
232
nQueued =
m_packets
.size ();
233
}
234
235
// simulate number of packets arrival during idle period
236
uint32_t m = 0;
237
238
if
(
m_idle
== 1)
239
{
240
NS_LOG_DEBUG
(
"RED Queue is idle."
);
241
Time
now =
Simulator::Now
();
242
243
if
(
m_cautious
== 3)
244
{
245
double
ptc =
m_ptc
*
m_meanPktSize
/
m_idlePktSize
;
246
m = uint32_t (ptc * (now -
m_idleTime
).GetSeconds ());
247
}
248
else
249
{
250
m = uint32_t (
m_ptc
* (now -
m_idleTime
).GetSeconds ());
251
}
252
253
m_idle
= 0;
254
}
255
256
m_qAvg
=
Estimator
(nQueued, m + 1,
m_qAvg
,
m_qW
);
257
258
NS_LOG_DEBUG
(
"\t bytesInQueue "
<<
m_bytesInQueue
<<
"\tQavg "
<<
m_qAvg
);
259
NS_LOG_DEBUG
(
"\t packetsInQueue "
<<
m_packets
.size () <<
"\tQavg "
<<
m_qAvg
);
260
261
m_count
++;
262
m_countBytes
+= p->
GetSize
();
263
264
uint32_t dropType =
DTYPE_NONE
;
265
if
(
m_qAvg
>=
m_minTh
&& nQueued > 1)
266
{
267
if
((!
m_isGentle
&&
m_qAvg
>=
m_maxTh
) ||
268
(
m_isGentle
&&
m_qAvg
>= 2 *
m_maxTh
))
269
{
270
NS_LOG_DEBUG
(
"adding DROP FORCED MARK"
);
271
dropType =
DTYPE_FORCED
;
272
}
273
else
if
(
m_old
== 0)
274
{
275
/*
276
* The average queue size has just crossed the
277
* threshold from below to above "minthresh", or
278
* from above "minthresh" with an empty queue to
279
* above "minthresh" with a nonempty queue.
280
*/
281
m_count = 1;
282
m_countBytes
= p->
GetSize
();
283
m_old
= 1;
284
}
285
else
if
(
DropEarly
(p, nQueued))
286
{
287
NS_LOG_LOGIC
(
"DropEarly returns 1"
);
288
dropType =
DTYPE_UNFORCED
;
289
}
290
}
291
else
292
{
293
// No packets are being dropped
294
m_vProb
= 0.0;
295
m_old
= 0;
296
}
297
298
if
(nQueued >=
m_queueLimit
)
299
{
300
NS_LOG_DEBUG
(
"\t Dropping due to Queue Full "
<< nQueued);
301
dropType =
DTYPE_FORCED
;
302
m_stats
.
qLimDrop
++;
303
}
304
305
if
(dropType ==
DTYPE_UNFORCED
)
306
{
307
NS_LOG_DEBUG
(
"\t Dropping due to Prob Mark "
<<
m_qAvg
);
308
m_stats
.
unforcedDrop
++;
309
Drop
(p);
310
return
false
;
311
}
312
else
if
(dropType ==
DTYPE_FORCED
)
313
{
314
NS_LOG_DEBUG
(
"\t Dropping due to Hard Mark "
<<
m_qAvg
);
315
m_stats
.
forcedDrop
++;
316
Drop
(p);
317
if
(
m_isNs1Compat
)
318
{
319
m_count = 0;
320
m_countBytes
= 0;
321
}
322
return
false
;
323
}
324
325
m_bytesInQueue
+= p->
GetSize
();
326
m_packets
.push_back (p);
327
328
NS_LOG_LOGIC
(
"Number packets "
<<
m_packets
.size ());
329
NS_LOG_LOGIC
(
"Number bytes "
<<
m_bytesInQueue
);
330
331
return
true
;
332
}
333
334
/*
335
* Note: if the link bandwidth changes in the course of the
336
* simulation, the bandwidth-dependent RED parameters do not change.
337
* This should be fixed, but it would require some extra parameters,
338
* and didn't seem worth the trouble...
339
*/
340
void
341
RedQueue::InitializeParams
(
void
)
342
{
343
NS_LOG_FUNCTION
(
this
);
344
345
NS_ASSERT
(
m_minTh
<=
m_maxTh
);
346
m_stats
.
forcedDrop
= 0;
347
m_stats
.
unforcedDrop
= 0;
348
m_stats
.
qLimDrop
= 0;
349
350
m_cautious
= 0;
351
m_ptc
=
m_linkBandwidth
.
GetBitRate
() / (8.0 *
m_meanPktSize
);
352
353
m_qAvg
= 0.0;
354
m_count
= 0;
355
m_countBytes
= 0;
356
m_old
= 0;
357
m_idle
= 1;
358
359
double
th_diff = (
m_maxTh
-
m_minTh
);
360
if
(th_diff == 0)
361
{
362
th_diff = 1.0;
363
}
364
m_vA
= 1.0 / th_diff;
365
m_curMaxP
= 1.0 /
m_lInterm
;
366
m_vB
= -
m_minTh
/ th_diff;
367
368
if
(
m_isGentle
)
369
{
370
m_vC
= (1.0 -
m_curMaxP
) /
m_maxTh
;
371
m_vD
= 2.0 *
m_curMaxP
- 1.0;
372
}
373
m_idleTime
=
NanoSeconds
(0);
374
375
/*
376
* If m_qW=0, set it to a reasonable value of 1-exp(-1/C)
377
* This corresponds to choosing m_qW to be of that value for
378
* which the packet time constant -1/ln(1-m)qW) per default RTT
379
* of 100ms is an order of magnitude more than the link capacity, C.
380
*
381
* If m_qW=-1, then the queue weight is set to be a function of
382
* the bandwidth and the link propagation delay. In particular,
383
* the default RTT is assumed to be three times the link delay and
384
* transmission delay, if this gives a default RTT greater than 100 ms.
385
*
386
* If m_qW=-2, set it to a reasonable value of 1-exp(-10/C).
387
*/
388
if
(
m_qW
== 0.0)
389
{
390
m_qW
= 1.0 - std::exp (-1.0 /
m_ptc
);
391
}
392
else
if
(
m_qW
== -1.0)
393
{
394
double
rtt = 3.0 * (
m_linkDelay
.
GetSeconds
() + 1.0 /
m_ptc
);
395
396
if
(rtt < 0.1)
397
{
398
rtt = 0.1;
399
}
400
m_qW
= 1.0 - std::exp (-1.0 / (10 * rtt *
m_ptc
));
401
}
402
else
if
(
m_qW
== -2.0)
403
{
404
m_qW
= 1.0 - std::exp (-10.0 /
m_ptc
);
405
}
406
407
// TODO: implement adaptive RED
408
409
NS_LOG_DEBUG
(
"\tm_delay "
<<
m_linkDelay
.
GetSeconds
() <<
"; m_isWait "
410
<<
m_isWait
<<
"; m_qW "
<<
m_qW
<<
"; m_ptc "
<<
m_ptc
411
<<
"; m_minTh "
<<
m_minTh
<<
"; m_maxTh "
<<
m_maxTh
412
<<
"; m_isGentle "
<<
m_isGentle
<<
"; th_diff "
<< th_diff
413
<<
"; lInterm "
<<
m_lInterm
<<
"; va "
<<
m_vA
<<
"; cur_max_p "
414
<<
m_curMaxP
<<
"; v_b "
<<
m_vB
<<
"; m_vC "
415
<<
m_vC
<<
"; m_vD "
<<
m_vD
);
416
}
417
418
// Compute the average queue size
419
double
420
RedQueue::Estimator
(uint32_t nQueued, uint32_t m,
double
qAvg,
double
qW)
421
{
422
NS_LOG_FUNCTION
(
this
<< nQueued << m << qAvg << qW);
423
double
newAve;
424
425
newAve = qAvg;
426
while
(--m >= 1)
427
{
428
newAve *= 1.0 - qW;
429
}
430
newAve *= 1.0 - qW;
431
newAve += qW * nQueued;
432
433
// TODO: implement adaptive RED
434
435
return
newAve;
436
}
437
438
// Check if packet p needs to be dropped due to probability mark
439
uint32_t
440
RedQueue::DropEarly
(
Ptr<Packet>
p, uint32_t qSize)
441
{
442
NS_LOG_FUNCTION
(
this
<< p << qSize);
443
m_vProb1
=
CalculatePNew
(
m_qAvg
,
m_maxTh
,
m_isGentle
,
m_vA
,
m_vB
,
m_vC
,
m_vD
,
m_curMaxP
);
444
m_vProb
=
ModifyP
(
m_vProb1
,
m_count
,
m_countBytes
,
m_meanPktSize
,
m_isWait
, p->
GetSize
());
445
446
// Drop probability is computed, pick random number and act
447
if
(
m_cautious
== 1)
448
{
449
/*
450
* Don't drop/mark if the instantaneous queue is much below the average.
451
* For experimental purposes only.
452
* pkts: the number of packets arriving in 50 ms
453
*/
454
double
pkts =
m_ptc
* 0.05;
455
double
fraction = std::pow ((1 -
m_qW
), pkts);
456
457
if
((
double
) qSize < fraction *
m_qAvg
)
458
{
459
// Queue could have been empty for 0.05 seconds
460
return
0;
461
}
462
}
463
464
double
u =
m_uv
->
GetValue
();
465
466
if
(
m_cautious
== 2)
467
{
468
/*
469
* Decrease the drop probability if the instantaneous
470
* queue is much below the average.
471
* For experimental purposes only.
472
* pkts: the number of packets arriving in 50 ms
473
*/
474
double
pkts =
m_ptc
* 0.05;
475
double
fraction = std::pow ((1 -
m_qW
), pkts);
476
double
ratio = qSize / (fraction *
m_qAvg
);
477
478
if
(ratio < 1.0)
479
{
480
u *= 1.0 / ratio;
481
}
482
}
483
484
if
(u <=
m_vProb
)
485
{
486
NS_LOG_LOGIC
(
"u <= m_vProb; u "
<< u <<
"; m_vProb "
<<
m_vProb
);
487
488
// DROP or MARK
489
m_count
= 0;
490
m_countBytes
= 0;
491
// TODO: Implement set bit to mark
492
493
return
1;
// drop
494
}
495
496
return
0;
// no drop/mark
497
}
498
499
// Returns a probability using these function parameters for the DropEarly funtion
500
double
501
RedQueue::CalculatePNew
(
double
qAvg,
double
maxTh,
bool
isGentle,
double
vA,
502
double
vB,
double
vC,
double
vD,
double
maxP)
503
{
504
NS_LOG_FUNCTION
(
this
<< qAvg << maxTh << isGentle << vA << vB << vC << vD << maxP);
505
double
p;
506
507
if
(isGentle && qAvg >= maxTh)
508
{
509
// p ranges from maxP to 1 as the average queue
510
// Size ranges from maxTh to twice maxTh
511
p = vC * qAvg + vD;
512
}
513
else
if
(!isGentle && qAvg >= maxTh)
514
{
515
/*
516
* OLD: p continues to range linearly above max_p as
517
* the average queue size ranges above th_max.
518
* NEW: p is set to 1.0
519
*/
520
p = 1.0;
521
}
522
else
523
{
524
/*
525
* p ranges from 0 to max_p as the average queue size ranges from
526
* th_min to th_max
527
*/
528
p = vA * qAvg + vB;
529
p *= maxP;
530
}
531
532
if
(p > 1.0)
533
{
534
p = 1.0;
535
}
536
537
return
p;
538
}
539
540
// Returns a probability using these function parameters for the DropEarly funtion
541
double
542
RedQueue::ModifyP
(
double
p, uint32_t count, uint32_t countBytes,
543
uint32_t meanPktSize,
bool
isWait, uint32_t size)
544
{
545
NS_LOG_FUNCTION
(
this
<< p << count << countBytes << meanPktSize << isWait << size);
546
double
count1 = (double) count;
547
548
if
(
GetMode
() ==
QUEUE_MODE_BYTES
)
549
{
550
count1 = (double) (countBytes / meanPktSize);
551
}
552
553
if
(isWait)
554
{
555
if
(count1 * p < 1.0)
556
{
557
p = 0.0;
558
}
559
else
if
(count1 * p < 2.0)
560
{
561
p /= (2.0 - count1 * p);
562
}
563
else
564
{
565
p = 1.0;
566
}
567
}
568
else
569
{
570
if
(count1 * p < 1.0)
571
{
572
p /= (1.0 - count1 * p);
573
}
574
else
575
{
576
p = 1.0;
577
}
578
}
579
580
if
((
GetMode
() ==
QUEUE_MODE_BYTES
) && (p < 1.0))
581
{
582
p = (p * size) / meanPktSize;
583
}
584
585
if
(p > 1.0)
586
{
587
p = 1.0;
588
}
589
590
return
p;
591
}
592
593
uint32_t
594
RedQueue::GetQueueSize
(
void
)
595
{
596
NS_LOG_FUNCTION
(
this
);
597
if
(
GetMode
() ==
QUEUE_MODE_BYTES
)
598
{
599
return
m_bytesInQueue
;
600
}
601
else
if
(
GetMode
() ==
QUEUE_MODE_PACKETS
)
602
{
603
return
m_packets
.size ();
604
}
605
else
606
{
607
NS_ABORT_MSG
(
"Unknown RED mode."
);
608
}
609
}
610
611
Ptr<Packet>
612
RedQueue::DoDequeue
(
void
)
613
{
614
NS_LOG_FUNCTION
(
this
);
615
616
if
(
m_packets
.empty ())
617
{
618
NS_LOG_LOGIC
(
"Queue empty"
);
619
m_idle
= 1;
620
m_idleTime
=
Simulator::Now
();
621
622
return
0;
623
}
624
else
625
{
626
m_idle
= 0;
627
Ptr<Packet>
p =
m_packets
.front ();
628
m_packets
.pop_front ();
629
m_bytesInQueue
-= p->
GetSize
();
630
631
NS_LOG_LOGIC
(
"Popped "
<< p);
632
633
NS_LOG_LOGIC
(
"Number packets "
<<
m_packets
.size ());
634
NS_LOG_LOGIC
(
"Number bytes "
<<
m_bytesInQueue
);
635
636
return
p;
637
}
638
}
639
640
Ptr<const Packet>
641
RedQueue::DoPeek
(
void
)
const
642
{
643
NS_LOG_FUNCTION
(
this
);
644
if
(
m_packets
.empty ())
645
{
646
NS_LOG_LOGIC
(
"Queue empty"
);
647
return
0;
648
}
649
650
Ptr<Packet>
p =
m_packets
.front ();
651
652
NS_LOG_LOGIC
(
"Number packets "
<<
m_packets
.size ());
653
NS_LOG_LOGIC
(
"Number bytes "
<<
m_bytesInQueue
);
654
655
return
p;
656
}
657
658
}
// namespace ns3
src
network
utils
red-queue.cc
Generated on Tue May 14 2013 11:08:31 for ns-3 by
1.8.1.2