A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
fq-pie-queue-disc.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Universita' degli Studi di Napoli Federico II
3 * Copyright (c) 2018 NITK Surathkal (modified for FQ-PIE)
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 * Authors: Pasquale Imputato <p.imputato@gmail.com>
19 * Stefano Avallone <stefano.avallone@unina.it>
20 * Modified for FQ-PIE by: Sumukha PK <sumukhapk46@gmail.com>
21 * Prajval M <26prajval98@gmail.com>
22 * Ishaan R D <ishaanrd6@gmail.com>
23 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
24 */
25
26#include "fq-pie-queue-disc.h"
27
28#include "pie-queue-disc.h"
29
30#include "ns3/log.h"
31#include "ns3/net-device-queue-interface.h"
32#include "ns3/queue.h"
33#include "ns3/string.h"
34
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("FqPieQueueDisc");
39
41
42TypeId
44{
45 static TypeId tid = TypeId("ns3::FqPieFlow")
47 .SetGroupName("TrafficControl")
48 .AddConstructor<FqPieFlow>();
49 return tid;
50}
51
53 : m_deficit(0),
54 m_status(INACTIVE),
55 m_index(0)
56{
57 NS_LOG_FUNCTION(this);
58}
59
61{
62 NS_LOG_FUNCTION(this);
63}
64
65void
67{
68 NS_LOG_FUNCTION(this << deficit);
69 m_deficit = deficit;
70}
71
74{
75 NS_LOG_FUNCTION(this);
76 return m_deficit;
77}
78
79void
81{
82 NS_LOG_FUNCTION(this << deficit);
83 m_deficit += deficit;
84}
85
86void
88{
89 NS_LOG_FUNCTION(this);
90 m_status = status;
91}
92
95{
96 NS_LOG_FUNCTION(this);
97 return m_status;
98}
99
100void
102{
103 NS_LOG_FUNCTION(this);
104 m_index = index;
105}
106
109{
110 return m_index;
111}
112
114
115TypeId
117{
118 static TypeId tid =
119 TypeId("ns3::FqPieQueueDisc")
121 .SetGroupName("TrafficControl")
122 .AddConstructor<FqPieQueueDisc>()
123 .AddAttribute("UseEcn",
124 "True to use ECN (packets are marked instead of being dropped)",
125 BooleanValue(true),
128 .AddAttribute("MarkEcnThreshold",
129 "ECN marking threshold (RFC 8033 suggests 0.1 (i.e., 10%) default)",
130 DoubleValue(0.1),
132 MakeDoubleChecker<double>(0, 1))
133 .AddAttribute("CeThreshold",
134 "The FqPie CE threshold for marking packets",
138 .AddAttribute("UseL4s",
139 "True to use L4S (only ECT1 packets are marked at CE threshold)",
140 BooleanValue(false),
143 .AddAttribute("MeanPktSize",
144 "Average of packet size",
145 UintegerValue(1000),
147 MakeUintegerChecker<uint32_t>())
148 .AddAttribute("A",
149 "Value of alpha",
150 DoubleValue(0.125),
152 MakeDoubleChecker<double>())
153 .AddAttribute("B",
154 "Value of beta",
155 DoubleValue(1.25),
157 MakeDoubleChecker<double>())
158 .AddAttribute("Tupdate",
159 "Time period to calculate drop probability",
160 TimeValue(Seconds(0.015)),
163 .AddAttribute("Supdate",
164 "Start time of the update timer",
165 TimeValue(Seconds(0)),
168 .AddAttribute("MaxSize",
169 "The maximum number of packets accepted by this queue disc",
170 QueueSizeValue(QueueSize("10240p")),
173 .AddAttribute("DequeueThreshold",
174 "Minimum queue size in bytes before dequeue rate is measured",
175 UintegerValue(16384),
177 MakeUintegerChecker<uint32_t>())
178 .AddAttribute("QueueDelayReference",
179 "Desired queue delay",
180 TimeValue(Seconds(0.015)),
183 .AddAttribute("MaxBurstAllowance",
184 "Current max burst allowance before random drop",
185 TimeValue(Seconds(0.15)),
188 .AddAttribute("UseDequeueRateEstimator",
189 "Enable/Disable usage of Dequeue Rate Estimator",
190 BooleanValue(false),
193 .AddAttribute("UseCapDropAdjustment",
194 "Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033",
195 BooleanValue(true),
198 .AddAttribute("UseDerandomization",
199 "Enable/Disable Derandomization feature mentioned in RFC 8033",
200 BooleanValue(false),
203 .AddAttribute("Flows",
204 "The number of queues into which the incoming packets are classified",
205 UintegerValue(1024),
207 MakeUintegerChecker<uint32_t>())
208 .AddAttribute("DropBatchSize",
209 "The maximum number of packets dropped from the fat flow",
210 UintegerValue(64),
212 MakeUintegerChecker<uint32_t>())
213 .AddAttribute("Perturbation",
214 "The salt used as an additional input to the hash function used to "
215 "classify packets",
216 UintegerValue(0),
218 MakeUintegerChecker<uint32_t>())
219 .AddAttribute("EnableSetAssociativeHash",
220 "Enable/Disable Set Associative Hash",
221 BooleanValue(false),
224 .AddAttribute("SetWays",
225 "The size of a set of queues (used by set associative hash)",
226 UintegerValue(8),
228 MakeUintegerChecker<uint32_t>());
229 return tid;
230}
231
234 m_quantum(0)
235{
236 NS_LOG_FUNCTION(this);
237}
238
240{
241 NS_LOG_FUNCTION(this);
242}
243
244void
246{
247 NS_LOG_FUNCTION(this << quantum);
248 m_quantum = quantum;
249}
250
253{
254 return m_quantum;
255}
256
259{
260 NS_LOG_FUNCTION(this << flowHash);
261
262 uint32_t h = (flowHash % m_flows);
263 uint32_t innerHash = h % m_setWays;
264 uint32_t outerHash = h - innerHash;
265
266 for (uint32_t i = outerHash; i < outerHash + m_setWays; i++)
267 {
268 auto it = m_flowsIndices.find(i);
269
270 if (it == m_flowsIndices.end() ||
271 (m_tags.find(i) != m_tags.end() && m_tags[i] == flowHash) ||
272 StaticCast<FqPieFlow>(GetQueueDiscClass(it->second))->GetStatus() ==
274 {
275 // this queue has not been created yet or is associated with this flow
276 // or is inactive, hence we can use it
277 m_tags[i] = flowHash;
278 return i;
279 }
280 }
281
282 // all the queues of the set are used. Use the first queue of the set
283 m_tags[outerHash] = flowHash;
284 return outerHash;
285}
286
287bool
289{
290 NS_LOG_FUNCTION(this << item);
291
292 uint32_t flowHash;
293 uint32_t h;
294
295 if (GetNPacketFilters() == 0)
296 {
297 flowHash = item->Hash(m_perturbation);
298 }
299 else
300 {
301 int32_t ret = Classify(item);
302
303 if (ret != PacketFilter::PF_NO_MATCH)
304 {
305 flowHash = static_cast<uint32_t>(ret);
306 }
307 else
308 {
309 NS_LOG_ERROR("No filter has been able to classify this packet, drop it.");
311 return false;
312 }
313 }
314
316 {
317 h = SetAssociativeHash(flowHash);
318 }
319 else
320 {
321 h = flowHash % m_flows;
322 }
323
324 Ptr<FqPieFlow> flow;
325 if (m_flowsIndices.find(h) == m_flowsIndices.end())
326 {
327 NS_LOG_DEBUG("Creating a new flow queue with index " << h);
330 // If Pie, Set values of PieQueueDisc to match this QueueDisc
331 Ptr<PieQueueDisc> pie = qd->GetObject<PieQueueDisc>();
332 if (pie)
333 {
334 pie->SetAttribute("UseEcn", BooleanValue(m_useEcn));
335 pie->SetAttribute("CeThreshold", TimeValue(m_ceThreshold));
336 pie->SetAttribute("UseL4s", BooleanValue(m_useL4s));
337 }
338 qd->Initialize();
339 flow->SetQueueDisc(qd);
340 flow->SetIndex(h);
341 AddQueueDiscClass(flow);
342
344 }
345 else
346 {
347 flow = StaticCast<FqPieFlow>(GetQueueDiscClass(m_flowsIndices[h]));
348 }
349
350 if (flow->GetStatus() == FqPieFlow::INACTIVE)
351 {
352 flow->SetStatus(FqPieFlow::NEW_FLOW);
353 flow->SetDeficit(m_quantum);
354 m_newFlows.push_back(flow);
355 }
356
357 flow->GetQueueDisc()->Enqueue(item);
358
359 NS_LOG_DEBUG("Packet enqueued into flow " << h << "; flow index " << m_flowsIndices[h]);
360
361 if (GetCurrentSize() > GetMaxSize())
362 {
363 NS_LOG_DEBUG("Overload; enter FqPieDrop ()");
364 FqPieDrop();
365 }
366
367 return true;
368}
369
372{
373 NS_LOG_FUNCTION(this);
374
375 Ptr<FqPieFlow> flow;
377
378 do
379 {
380 bool found = false;
381
382 while (!found && !m_newFlows.empty())
383 {
384 flow = m_newFlows.front();
385
386 if (flow->GetDeficit() <= 0)
387 {
388 NS_LOG_DEBUG("Increase deficit for new flow index " << flow->GetIndex());
389 flow->IncreaseDeficit(m_quantum);
390 flow->SetStatus(FqPieFlow::OLD_FLOW);
391 m_oldFlows.push_back(flow);
392 m_newFlows.pop_front();
393 }
394 else
395 {
396 NS_LOG_DEBUG("Found a new flow " << flow->GetIndex() << " with positive deficit");
397 found = true;
398 }
399 }
400
401 while (!found && !m_oldFlows.empty())
402 {
403 flow = m_oldFlows.front();
404
405 if (flow->GetDeficit() <= 0)
406 {
407 NS_LOG_DEBUG("Increase deficit for old flow index " << flow->GetIndex());
408 flow->IncreaseDeficit(m_quantum);
409 m_oldFlows.push_back(flow);
410 m_oldFlows.pop_front();
411 }
412 else
413 {
414 NS_LOG_DEBUG("Found an old flow " << flow->GetIndex() << " with positive deficit");
415 found = true;
416 }
417 }
418
419 if (!found)
420 {
421 NS_LOG_DEBUG("No flow found to dequeue a packet");
422 return nullptr;
423 }
424
425 item = flow->GetQueueDisc()->Dequeue();
426
427 if (!item)
428 {
429 NS_LOG_DEBUG("Could not get a packet from the selected flow queue");
430 if (!m_newFlows.empty())
431 {
432 flow->SetStatus(FqPieFlow::OLD_FLOW);
433 m_oldFlows.push_back(flow);
434 m_newFlows.pop_front();
435 }
436 else
437 {
438 flow->SetStatus(FqPieFlow::INACTIVE);
439 m_oldFlows.pop_front();
440 }
441 }
442 else
443 {
444 NS_LOG_DEBUG("Dequeued packet " << item->GetPacket());
445 }
446 } while (!item);
447
448 flow->IncreaseDeficit(item->GetSize() * -1);
449
450 return item;
451}
452
453bool
455{
456 NS_LOG_FUNCTION(this);
457 if (GetNQueueDiscClasses() > 0)
458 {
459 NS_LOG_ERROR("FqPieQueueDisc cannot have classes");
460 return false;
461 }
462
463 if (GetNInternalQueues() > 0)
464 {
465 NS_LOG_ERROR("FqPieQueueDisc cannot have internal queues");
466 return false;
467 }
468 // we are at initialization time. If the user has not set a quantum value,
469 // set the quantum to the MTU of the device (if any)
470 if (!m_quantum)
471 {
473 Ptr<NetDevice> dev;
474 // if the NetDeviceQueueInterface object is aggregated to a
475 // NetDevice, get the MTU of such NetDevice
476 if (ndqi && (dev = ndqi->GetObject<NetDevice>()))
477 {
478 m_quantum = dev->GetMtu();
479 NS_LOG_DEBUG("Setting the quantum to the MTU of the device: " << m_quantum);
480 }
481
482 if (!m_quantum)
483 {
484 NS_LOG_ERROR("The quantum parameter cannot be null");
485 return false;
486 }
487 }
488
490 {
491 NS_LOG_ERROR("The number of queues must be an integer multiple of the size "
492 "of the set of queues used by set associative hash");
493 return false;
494 }
495
496 // If UseL4S attribute is enabled then CE threshold must be set.
497 if (m_useL4s)
498 {
499 NS_ABORT_MSG_IF(m_ceThreshold == Time::Max(), "CE threshold not set");
500 if (!m_useEcn)
501 {
502 NS_LOG_WARN("Enabling ECN as L4S mode is enabled");
503 }
504 }
505 return true;
506}
507
508void
510{
511 NS_LOG_FUNCTION(this);
512
513 m_flowFactory.SetTypeId("ns3::FqPieFlow");
514
515 m_queueDiscFactory.SetTypeId("ns3::PieQueueDisc");
523 m_queueDiscFactory.Set("QueueDelayReference", TimeValue(m_qDelayRef));
524 m_queueDiscFactory.Set("MaxBurstAllowance", TimeValue(m_maxBurst));
525 m_queueDiscFactory.Set("UseDequeueRateEstimator", BooleanValue(m_useDqRateEstimator));
528}
529
532{
533 NS_LOG_FUNCTION(this);
534
535 uint32_t maxBacklog = 0;
536 uint32_t index = 0;
538
539 /* Queue is full! Find the fat flow and drop packet(s) from it */
540 for (uint32_t i = 0; i < GetNQueueDiscClasses(); i++)
541 {
542 qd = GetQueueDiscClass(i)->GetQueueDisc();
543 uint32_t bytes = qd->GetNBytes();
544 if (bytes > maxBacklog)
545 {
546 maxBacklog = bytes;
547 index = i;
548 }
549 }
550
551 /* Our goal is to drop half of this fat flow backlog */
552 uint32_t len = 0;
553 uint32_t count = 0;
554 uint32_t threshold = maxBacklog >> 1;
555 qd = GetQueueDiscClass(index)->GetQueueDisc();
557
558 do
559 {
560 NS_LOG_DEBUG("Drop packet (overflow); count: " << count << " len: " << len
561 << " threshold: " << threshold);
562 item = qd->GetInternalQueue(0)->Dequeue();
564 len += item->GetSize();
565 } while (++count < m_dropBatchSize && len < threshold);
566
567 return index;
568}
569
570} // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
A flow queue used by the FqPie queue disc.
void SetIndex(uint32_t index)
Set the index for this flow.
FlowStatus
Used to determine the status of this flow queue.
int32_t m_deficit
the deficit for this flow
void SetStatus(FlowStatus status)
Set the status for this flow.
static TypeId GetTypeId()
Get the type ID.
~FqPieFlow() override
FlowStatus GetStatus() const
Get the status of this flow.
FlowStatus m_status
the status of this flow
uint32_t m_index
the index for this flow
void SetDeficit(uint32_t deficit)
Set the deficit for this flow.
uint32_t GetIndex() const
Get the index of this flow.
FqPieFlow()
FqPieFlow constructor.
void IncreaseDeficit(int32_t deficit)
Increase the deficit for this flow.
int32_t GetDeficit() const
Get the deficit for this flow.
A FqPie packet queue disc.
Time m_qDelayRef
Desired queue delay.
std::map< uint32_t, uint32_t > m_tags
Tags used by set associative hash.
bool m_useEcn
True if ECN is used (packets are marked instead of being dropped)
bool m_enableSetAssociativeHash
whether to enable set associative hash
uint32_t m_meanPktSize
Average packet size in bytes.
static constexpr const char * UNCLASSIFIED_DROP
No packet filter able to classify packet.
uint32_t GetQuantum() const
Get the quantum value.
uint32_t m_perturbation
hash perturbation value
FqPieQueueDisc()
FqPieQueueDisc constructor.
ObjectFactory m_queueDiscFactory
Factory to create a new queue.
bool DoEnqueue(Ptr< QueueDiscItem > item) override
This function actually enqueues a packet into the queue disc.
double m_a
Parameter to pie controller.
Time m_sUpdate
Start time of the update timer.
bool m_useDqRateEstimator
Enable/Disable usage of dequeue rate estimator for queue delay calculation.
Time m_ceThreshold
Threshold above which to CE mark.
uint32_t m_dqThreshold
Minimum queue size in bytes before dequeue rate is measured.
Ptr< QueueDiscItem > DoDequeue() override
This function actually extracts a packet from the queue disc.
bool CheckConfig() override
Check whether the current configuration is correct.
uint32_t m_dropBatchSize
Max number of packets dropped from the fat flow.
uint32_t m_quantum
Deficit assigned to flows at each round.
Time m_tUpdate
Time period after which CalculateP () is called.
uint32_t FqPieDrop()
Drop a packet from the head of the queue with the largest current byte count.
bool m_isCapDropAdjustment
Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033.
std::list< Ptr< FqPieFlow > > m_newFlows
The list of new flows.
Time m_maxBurst
Maximum burst allowed before random early dropping kicks in.
bool m_useDerandomization
Enable Derandomization feature mentioned in RFC 8033.
uint32_t m_setWays
size of a set of queues (used by set associative hash)
uint32_t m_flows
Number of flow queues.
static TypeId GetTypeId()
Get the type ID.
double m_markEcnTh
ECN marking threshold (default 10% as suggested in RFC 8033)
void InitializeParams() override
Initialize parameters (if any) before the first packet is enqueued.
std::map< uint32_t, uint32_t > m_flowsIndices
Map with the index of class for each flow.
uint32_t SetAssociativeHash(uint32_t flowHash)
Compute the index of the queue for the flow having the given flowHash, according to the set associati...
static constexpr const char * OVERLIMIT_DROP
Overlimit dropped packets.
bool m_useL4s
True if L4S is used (ECT1 packets are marked at CE threshold)
void SetQuantum(uint32_t quantum)
Set the quantum value.
double m_b
Parameter to pie controller.
ObjectFactory m_flowFactory
Factory to create a new flow.
std::list< Ptr< FqPieFlow > > m_oldFlows
The list of old flows.
Network layer to device interface.
Definition: net-device.h:98
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:211
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
static const int PF_NO_MATCH
Standard value used by packet filters to indicate that no match was possible.
Definition: packet-filter.h:49
Implements PIE Active Queue Management discipline.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
QueueDiscClass is the base class for classes that are included in a queue disc.
Definition: queue-disc.h:52
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:184
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:624
QueueSize GetCurrentSize() const
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets,...
Definition: queue-disc.cc:515
int32_t Classify(Ptr< QueueDiscItem > item)
Classify a packet by calling the packet filters, one at a time, until either a filter able to classif...
Definition: queue-disc.cc:667
Ptr< NetDeviceQueueInterface > GetNetDeviceQueueInterface() const
Definition: queue-disc.cc:538
void DropAfterDequeue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped after dequeue.
Definition: queue-disc.cc:759
std::size_t GetNQueueDiscClasses() const
Get the number of queue disc classes.
Definition: queue-disc.cc:661
QueueSize GetMaxSize() const
Get the maximum size of the queue disc.
Definition: queue-disc.cc:446
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:654
std::size_t GetNPacketFilters() const
Get the number of packet filters.
Definition: queue-disc.cc:618
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
Definition: queue-disc.cc:474
std::size_t GetNInternalQueues() const
Get the number of internal queues.
Definition: queue-disc.cc:598
void DropBeforeEnqueue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped before enqueue.
Definition: queue-disc.cc:720
Class for representing queue sizes.
Definition: queue-size.h:96
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:297
AttributeValue implementation for Time.
Definition: nstime.h:1413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeChecker > MakeQueueSizeChecker()
Definition: queue-size.cc:29
Ptr< const AttributeAccessor > MakeQueueSizeAccessor(T1 a1)
Definition: queue-size.h:221
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1434
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition: lr-wpan-mac.h:104
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:44
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:107
@ MULTIPLE_QUEUES
Used by queue discs with multiple internal queues/child queue discs.
Definition: queue-disc.h:110
Every class exported by the ns3 library is enclosed in the ns3 namespace.