A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lorawan-mac-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Davide Magrin <magrinda@dei.unipd.it>
7 */
8
10
11#include "ns3/end-device-lora-phy.h"
12#include "ns3/gateway-lora-phy.h"
13#include "ns3/log.h"
14#include "ns3/lora-net-device.h"
15#include "ns3/random-variable-stream.h"
16
17namespace ns3
18{
19namespace lorawan
20{
21
22NS_LOG_COMPONENT_DEFINE("LorawanMacHelper");
23
28
29void
30LorawanMacHelper::Set(std::string name, const AttributeValue& v)
31{
32 m_mac.Set(name, v);
33}
34
35void
37{
38 NS_LOG_FUNCTION(this << dt);
39 switch (dt)
40 {
41 case GW:
42 m_mac.SetTypeId("ns3::GatewayLorawanMac");
43 break;
44 case ED_A:
45 m_mac.SetTypeId("ns3::ClassAEndDeviceLorawanMac");
46 break;
47 }
48 m_deviceType = dt;
49}
50
51void
58
59void
64
67{
69 mac->SetDevice(device);
70
71 // If we are operating on an end device, add an address to it
72 if (m_deviceType == ED_A && m_addrGen)
73 {
74 DynamicCast<ClassAEndDeviceLorawanMac>(mac)->SetDeviceAddress(m_addrGen->NextAddress());
75 }
76
77 // Add a basic list of channels based on the region where the device is
78 // operating
79 if (m_deviceType == ED_A)
80 {
82 switch (m_region)
83 {
86 break;
87 }
90 break;
91 }
94 break;
95 }
96 default: {
97 NS_LOG_ERROR("This region isn't supported yet!");
98 break;
99 }
100 }
101 }
102 else
103 {
105 switch (m_region)
106 {
109 break;
110 }
113 break;
114 }
117 break;
118 }
119 default: {
120 NS_LOG_ERROR("This region isn't supported yet!");
121 break;
122 }
123 }
124 }
125 return mac;
126}
127
128void
130{
132
134
135 /////////////////////////////////////////////////////
136 // TxPower -> Transmission power in dBm conversion //
137 /////////////////////////////////////////////////////
138 edMac->SetTxDbmForTxPower(std::vector<double>{16, 14, 12, 10, 8, 6, 4, 2});
139
140 ////////////////////////////////////////////////////////////
141 // Matrix to know which data rate the gateway will respond with //
142 ////////////////////////////////////////////////////////////
143 LorawanMac::ReplyDataRateMatrix matrix = {{{{0, 0, 0, 0, 0, 0}},
144 {{1, 0, 0, 0, 0, 0}},
145 {{2, 1, 0, 0, 0, 0}},
146 {{3, 2, 1, 0, 0, 0}},
147 {{4, 3, 2, 1, 0, 0}},
148 {{5, 4, 3, 2, 1, 0}},
149 {{6, 5, 4, 3, 2, 1}},
150 {{7, 6, 5, 4, 3, 2}}}};
151 edMac->SetReplyDataRateMatrix(matrix);
152
153 /////////////////////
154 // Preamble length //
155 /////////////////////
156 edMac->SetNPreambleSymbols(8);
157
158 //////////////////////////////////////
159 // Second receive window parameters //
160 //////////////////////////////////////
161 edMac->SetSecondReceiveWindowDataRate(0);
162 edMac->SetSecondReceiveWindowFrequency(869.525);
163}
164
165void
167{
169
170 ///////////////////////////////
171 // ReceivePath configuration //
172 ///////////////////////////////
173 Ptr<GatewayLoraPhy> gwPhy =
174 DynamicCast<GatewayLoraPhy>(DynamicCast<LoraNetDevice>(gwMac->GetDevice())->GetPhy());
175
177
178 if (gwPhy) // If cast is successful, there's a GatewayLoraPhy
179 {
180 NS_LOG_DEBUG("Resetting reception paths");
181 gwPhy->ResetReceptionPaths();
182
183 int receptionPaths = 0;
184 int maxReceptionPaths = 1;
185 while (receptionPaths < maxReceptionPaths)
186 {
187 DynamicCast<GatewayLoraPhy>(gwPhy)->AddReceptionPath();
188 receptionPaths++;
189 }
190 gwPhy->AddFrequency(868.1);
191 }
192}
193
194void
196{
198
199 //////////////
200 // SubBands //
201 //////////////
202
204 channelHelper->AddSubBand(868, 868.6, 1, 14);
205
206 //////////////////////
207 // Default channels //
208 //////////////////////
210 channelHelper->AddChannel(lc1);
211
212 lorawanMac->SetLogicalLoraChannelHelper(channelHelper);
213
214 ///////////////////////////////////////////////////////////
215 // Data rate -> Spreading factor, Data rate -> Bandwidth //
216 // and Data rate -> MaxAppPayload conversions //
217 ///////////////////////////////////////////////////////////
218 lorawanMac->SetSfForDataRate(std::vector<uint8_t>{12, 11, 10, 9, 8, 7, 7});
219 lorawanMac->SetBandwidthForDataRate(
220 std::vector<double>{125000, 125000, 125000, 125000, 125000, 125000, 250000});
221 lorawanMac->SetMaxAppPayloadForDataRate(
222 std::vector<uint32_t>{59, 59, 59, 123, 230, 230, 230, 230});
223}
224
225void
227{
229
231
232 /////////////////////////////////////////////////////
233 // TxPower -> Transmission power in dBm conversion //
234 /////////////////////////////////////////////////////
235 edMac->SetTxDbmForTxPower(std::vector<double>{16, 14, 12, 10, 8, 6, 4, 2});
236
237 ////////////////////////////////////////////////////////////
238 // Matrix to know which data rate the gateway will respond with //
239 ////////////////////////////////////////////////////////////
240 LorawanMac::ReplyDataRateMatrix matrix = {{{{0, 0, 0, 0, 0, 0}},
241 {{1, 0, 0, 0, 0, 0}},
242 {{2, 1, 0, 0, 0, 0}},
243 {{3, 2, 1, 0, 0, 0}},
244 {{4, 3, 2, 1, 0, 0}},
245 {{5, 4, 3, 2, 1, 0}},
246 {{6, 5, 4, 3, 2, 1}},
247 {{7, 6, 5, 4, 3, 2}}}};
248 edMac->SetReplyDataRateMatrix(matrix);
249
250 /////////////////////
251 // Preamble length //
252 /////////////////////
253 edMac->SetNPreambleSymbols(8);
254
255 //////////////////////////////////////
256 // Second receive window parameters //
257 //////////////////////////////////////
258 edMac->SetSecondReceiveWindowDataRate(0);
259 edMac->SetSecondReceiveWindowFrequency(869.525);
260}
261
262void
264{
266
267 ///////////////////////////////
268 // ReceivePath configuration //
269 ///////////////////////////////
270 Ptr<GatewayLoraPhy> gwPhy =
271 DynamicCast<GatewayLoraPhy>(DynamicCast<LoraNetDevice>(gwMac->GetDevice())->GetPhy());
272
274
275 if (gwPhy) // If cast is successful, there's a GatewayLoraPhy
276 {
277 NS_LOG_DEBUG("Resetting reception paths");
278 gwPhy->ResetReceptionPaths();
279
280 std::vector<double> frequencies;
281 frequencies.push_back(868.1);
282 frequencies.push_back(868.3);
283 frequencies.push_back(868.5);
284
285 for (auto& f : frequencies)
286 {
287 gwPhy->AddFrequency(f);
288 }
289
290 int receptionPaths = 0;
291 int maxReceptionPaths = 8;
292 while (receptionPaths < maxReceptionPaths)
293 {
294 DynamicCast<GatewayLoraPhy>(gwPhy)->AddReceptionPath();
295 receptionPaths++;
296 }
297 }
298}
299
300void
302{
304
305 //////////////
306 // SubBands //
307 //////////////
308
310 channelHelper->AddSubBand(868, 868.6, 0.01, 14);
311 channelHelper->AddSubBand(868.7, 869.2, 0.001, 14);
312 channelHelper->AddSubBand(869.4, 869.65, 0.1, 27);
313
314 //////////////////////
315 // Default channels //
316 //////////////////////
320 channelHelper->AddChannel(lc1);
321 channelHelper->AddChannel(lc2);
322 channelHelper->AddChannel(lc3);
323
324 lorawanMac->SetLogicalLoraChannelHelper(channelHelper);
325
326 ///////////////////////////////////////////////////////////
327 // Data rate -> Spreading factor, Data rate -> Bandwidth //
328 // and Data rate -> MaxAppPayload conversions //
329 ///////////////////////////////////////////////////////////
330 lorawanMac->SetSfForDataRate(std::vector<uint8_t>{12, 11, 10, 9, 8, 7, 7});
331 lorawanMac->SetBandwidthForDataRate(
332 std::vector<double>{125000, 125000, 125000, 125000, 125000, 125000, 250000});
333 lorawanMac->SetMaxAppPayloadForDataRate(
334 std::vector<uint32_t>{59, 59, 59, 123, 230, 230, 230, 230});
335}
336
337///////////////////////////////
338
339void
341{
343
345
346 /////////////////////////////////////////////////////
347 // TxPower -> Transmission power in dBm conversion //
348 /////////////////////////////////////////////////////
349 edMac->SetTxDbmForTxPower(std::vector<double>{16, 14, 12, 10, 8, 6, 4, 2});
350
351 ////////////////////////////////////////////////////////////
352 // Matrix to know which DataRate the gateway will respond with //
353 ////////////////////////////////////////////////////////////
354 LorawanMac::ReplyDataRateMatrix matrix = {{{{0, 0, 0, 0, 0, 0}},
355 {{1, 0, 0, 0, 0, 0}},
356 {{2, 1, 0, 0, 0, 0}},
357 {{3, 2, 1, 0, 0, 0}},
358 {{4, 3, 2, 1, 0, 0}},
359 {{5, 4, 3, 2, 1, 0}},
360 {{6, 5, 4, 3, 2, 1}},
361 {{7, 6, 5, 4, 3, 2}}}};
362 edMac->SetReplyDataRateMatrix(matrix);
363
364 /////////////////////
365 // Preamble length //
366 /////////////////////
367 edMac->SetNPreambleSymbols(8);
368
369 //////////////////////////////////////
370 // Second receive window parameters //
371 //////////////////////////////////////
372 edMac->SetSecondReceiveWindowDataRate(0);
373 edMac->SetSecondReceiveWindowFrequency(869.525);
374}
375
376void
378{
380
381 ///////////////////////////////
382 // ReceivePath configuration //
383 ///////////////////////////////
384 Ptr<GatewayLoraPhy> gwPhy =
385 DynamicCast<GatewayLoraPhy>(DynamicCast<LoraNetDevice>(gwMac->GetDevice())->GetPhy());
386
388
389 if (gwPhy) // If cast is successful, there's a GatewayLoraPhy
390 {
391 NS_LOG_DEBUG("Resetting reception paths");
392 gwPhy->ResetReceptionPaths();
393
394 std::vector<double> frequencies;
395 frequencies.push_back(868.1);
396
397 for (auto& f : frequencies)
398 {
399 gwPhy->AddFrequency(f);
400 }
401
402 int receptionPaths = 0;
403 int maxReceptionPaths = 8;
404 while (receptionPaths < maxReceptionPaths)
405 {
406 gwPhy->AddReceptionPath();
407 receptionPaths++;
408 }
409 }
410}
411
412void
414{
416
417 //////////////
418 // SubBands //
419 //////////////
420
422 channelHelper->AddSubBand(868, 868.6, 0.01, 14);
423 channelHelper->AddSubBand(868.7, 869.2, 0.001, 14);
424 channelHelper->AddSubBand(869.4, 869.65, 0.1, 27);
425
426 //////////////////////
427 // Default channels //
428 //////////////////////
430 channelHelper->AddChannel(lc1);
431
432 lorawanMac->SetLogicalLoraChannelHelper(channelHelper);
433
434 ///////////////////////////////////////////////////////////
435 // Data rate -> Spreading factor, Data rate -> Bandwidth //
436 // and Data rate -> MaxAppPayload conversions //
437 ///////////////////////////////////////////////////////////
438 lorawanMac->SetSfForDataRate(std::vector<uint8_t>{12, 11, 10, 9, 8, 7, 7});
439 lorawanMac->SetBandwidthForDataRate(
440 std::vector<double>{125000, 125000, 125000, 125000, 125000, 125000, 250000});
441 lorawanMac->SetMaxAppPayloadForDataRate(
442 std::vector<uint32_t>{59, 59, 59, 123, 230, 230, 230, 230});
443}
444
445std::vector<int>
447 NodeContainer gateways,
448 Ptr<LoraChannel> channel)
449{
451
452 std::vector<int> sfQuantity(7, 0);
453 for (auto j = endDevices.Begin(); j != endDevices.End(); ++j)
454 {
455 Ptr<Node> object = *j;
456 Ptr<MobilityModel> position = object->GetObject<MobilityModel>();
457 NS_ASSERT(position);
458 Ptr<NetDevice> netDevice = object->GetDevice(0);
459 Ptr<LoraNetDevice> loraNetDevice = DynamicCast<LoraNetDevice>(netDevice);
460 NS_ASSERT(loraNetDevice);
462 DynamicCast<ClassAEndDeviceLorawanMac>(loraNetDevice->GetMac());
463 NS_ASSERT(mac);
464
465 // Try computing the distance from each gateway and find the best one
466 Ptr<Node> bestGateway = gateways.Get(0);
467 Ptr<MobilityModel> bestGatewayPosition = bestGateway->GetObject<MobilityModel>();
468
469 // Assume devices transmit at 14 dBm
470 double highestRxPower = channel->GetRxPower(14, position, bestGatewayPosition);
471
472 for (auto currentGw = gateways.Begin() + 1; currentGw != gateways.End(); ++currentGw)
473 {
474 // Compute the power received from the current gateway
475 Ptr<Node> curr = *currentGw;
476 Ptr<MobilityModel> currPosition = curr->GetObject<MobilityModel>();
477 double currentRxPower = channel->GetRxPower(14, position, currPosition); // dBm
478
479 if (currentRxPower > highestRxPower)
480 {
481 bestGateway = curr;
482 bestGatewayPosition = currPosition;
483 highestRxPower = currentRxPower;
484 }
485 }
486
487 // NS_LOG_DEBUG ("Rx Power: " << highestRxPower);
488 double rxPower = highestRxPower;
489
490 // Get the end device sensitivity
491 Ptr<EndDeviceLoraPhy> edPhy = DynamicCast<EndDeviceLoraPhy>(loraNetDevice->GetPhy());
492 const double* edSensitivity = EndDeviceLoraPhy::sensitivity;
493
494 if (rxPower > *edSensitivity)
495 {
496 mac->SetDataRate(5);
497 sfQuantity[0] = sfQuantity[0] + 1;
498 }
499 else if (rxPower > *(edSensitivity + 1))
500 {
501 mac->SetDataRate(4);
502 sfQuantity[1] = sfQuantity[1] + 1;
503 }
504 else if (rxPower > *(edSensitivity + 2))
505 {
506 mac->SetDataRate(3);
507 sfQuantity[2] = sfQuantity[2] + 1;
508 }
509 else if (rxPower > *(edSensitivity + 3))
510 {
511 mac->SetDataRate(2);
512 sfQuantity[3] = sfQuantity[3] + 1;
513 }
514 else if (rxPower > *(edSensitivity + 4))
515 {
516 mac->SetDataRate(1);
517 sfQuantity[4] = sfQuantity[4] + 1;
518 }
519 else if (rxPower > *(edSensitivity + 5))
520 {
521 mac->SetDataRate(0);
522 sfQuantity[5] = sfQuantity[5] + 1;
523 }
524 else // Device is out of range. Assign SF12.
525 {
526 // NS_LOG_DEBUG ("Device out of range");
527 mac->SetDataRate(0);
528 sfQuantity[6] = sfQuantity[6] + 1;
529 // NS_LOG_DEBUG ("sfQuantity[6] = " << sfQuantity[6]);
530 }
531
532 /*
533
534 // Get the Gw sensitivity
535 Ptr<NetDevice> gatewayNetDevice = bestGateway->GetDevice (0);
536 Ptr<LoraNetDevice> gatewayLoraNetDevice = DynamicCast<LoraNetDevice>(gatewayNetDevice);
537 Ptr<GatewayLoraPhy> gatewayPhy = DynamicCast<GatewayLoraPhy>
538 (gatewayLoraNetDevice->GetPhy ()); const double *gwSensitivity = gatewayPhy->sensitivity;
539
540 if(rxPower > *gwSensitivity)
541 {
542 mac->SetDataRate (5);
543 sfQuantity[0] = sfQuantity[0] + 1;
544
545 }
546 else if (rxPower > *(gwSensitivity+1))
547 {
548 mac->SetDataRate (4);
549 sfQuantity[1] = sfQuantity[1] + 1;
550
551 }
552 else if (rxPower > *(gwSensitivity+2))
553 {
554 mac->SetDataRate (3);
555 sfQuantity[2] = sfQuantity[2] + 1;
556
557 }
558 else if (rxPower > *(gwSensitivity+3))
559 {
560 mac->SetDataRate (2);
561 sfQuantity[3] = sfQuantity[3] + 1;
562 }
563 else if (rxPower > *(gwSensitivity+4))
564 {
565 mac->SetDataRate (1);
566 sfQuantity[4] = sfQuantity[4] + 1;
567 }
568 else if (rxPower > *(gwSensitivity+5))
569 {
570 mac->SetDataRate (0);
571 sfQuantity[5] = sfQuantity[5] + 1;
572
573 }
574 else // Device is out of range. Assign SF12.
575 {
576 mac->SetDataRate (0);
577 sfQuantity[6] = sfQuantity[6] + 1;
578
579 }
580 */
581
582 } // end loop on nodes
583
584 return sfQuantity;
585
586} // end function
587
588std::vector<int>
590 NodeContainer gateways,
591 std::vector<double> distribution)
592{
594 NS_ASSERT(distribution.size() == 6);
595
596 std::vector<int> sfQuantity(7, 0);
598 std::vector<double> cumdistr(6);
599 cumdistr[0] = distribution[0];
600 for (int i = 1; i < 6; ++i)
601 {
602 cumdistr[i] = distribution[i] + cumdistr[i - 1];
603 }
604
605 NS_LOG_DEBUG("Distribution: " << distribution[0] << " " << distribution[1] << " "
606 << distribution[2] << " " << distribution[3] << " "
607 << distribution[4] << " " << distribution[5]);
608 NS_LOG_DEBUG("Cumulative distribution: " << cumdistr[0] << " " << cumdistr[1] << " "
609 << cumdistr[2] << " " << cumdistr[3] << " "
610 << cumdistr[4] << " " << cumdistr[5]);
611
612 for (auto j = endDevices.Begin(); j != endDevices.End(); ++j)
613 {
614 Ptr<Node> object = *j;
615 Ptr<MobilityModel> position = object->GetObject<MobilityModel>();
616 NS_ASSERT(position);
617 Ptr<NetDevice> netDevice = object->GetDevice(0);
618 Ptr<LoraNetDevice> loraNetDevice = DynamicCast<LoraNetDevice>(netDevice);
619 NS_ASSERT(loraNetDevice);
621 DynamicCast<ClassAEndDeviceLorawanMac>(loraNetDevice->GetMac());
622 NS_ASSERT(mac);
623
624 double prob = uniformRV->GetValue(0, 1);
625
626 // NS_LOG_DEBUG ("Probability: " << prob);
627 if (prob < cumdistr[0])
628 {
629 mac->SetDataRate(5);
630 sfQuantity[0] = sfQuantity[0] + 1;
631 }
632 else if (prob > cumdistr[0] && prob < cumdistr[1])
633 {
634 mac->SetDataRate(4);
635 sfQuantity[1] = sfQuantity[1] + 1;
636 }
637 else if (prob > cumdistr[1] && prob < cumdistr[2])
638 {
639 mac->SetDataRate(3);
640 sfQuantity[2] = sfQuantity[2] + 1;
641 }
642 else if (prob > cumdistr[2] && prob < cumdistr[3])
643 {
644 mac->SetDataRate(2);
645 sfQuantity[3] = sfQuantity[3] + 1;
646 }
647 else if (prob > cumdistr[3] && prob < cumdistr[4])
648 {
649 mac->SetDataRate(1);
650 sfQuantity[4] = sfQuantity[4] + 1;
651 }
652 else
653 {
654 mac->SetDataRate(0);
655 sfQuantity[5] = sfQuantity[5] + 1;
656 }
657
658 } // end loop on nodes
659
660 return sfQuantity;
661
662} // end function
663
664} // namespace lorawan
665} // namespace ns3
Hold a value for an Attribute.
Definition attribute.h:59
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
Iterator End() const
Get an iterator which indicates past-the-last Node in the container.
Iterator Begin() const
Get an iterator which refers to the first Node in the container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
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.
Smart pointer class similar to boost::intrusive_ptr.
static const double sensitivity[6]
The sensitivity vector of this device to different SFs.
Helper class for configuring and installing the LorawanMac class on devices and gateways.
void ConfigureForAlohaRegion(Ptr< ClassAEndDeviceLorawanMac > edMac) const
Perform region-specific configurations for the ALOHA band.
LorawanMacHelper()
Default constructor.
void SetDeviceType(enum DeviceType dt)
Set the kind of MAC this helper will create.
void SetAddressGenerator(Ptr< LoraDeviceAddressGenerator > addrGen)
Set the address generator to use for creation of these nodes.
static std::vector< int > SetSpreadingFactorsUp(NodeContainer endDevices, NodeContainer gateways, Ptr< LoraChannel > channel)
Initialize the end devices' data rate parameter.
void ApplyCommonEuConfigurations(Ptr< LorawanMac > lorawanMac) const
Apply configurations that are common both for the GatewayLorawanMac and the ClassAEndDeviceLorawanMac...
enum Regions m_region
The region in which the device will operate.
Regions
Define the operational region.
void SetRegion(enum Regions region)
Set the region in which the device is to operate.
void Set(std::string name, const AttributeValue &v)
Set an attribute of the underlying MAC object.
ObjectFactory m_mac
MAC-layer object factory.
Ptr< LorawanMac > Create(Ptr< Node > node, Ptr< NetDevice > device) const
Create the LorawanMac instance and connect it to a device.
static std::vector< int > SetSpreadingFactorsGivenDistribution(NodeContainer endDevices, NodeContainer gateways, std::vector< double > distribution)
Randomly initialize the end devices' data rate parameter according to the given distribution.
Ptr< LoraDeviceAddressGenerator > m_addrGen
Pointer to the address generator to use.
void ConfigureForSingleChannelRegion(Ptr< ClassAEndDeviceLorawanMac > edMac) const
Perform region-specific configurations for the SINGLECHANNEL band.
void ApplyCommonSingleChannelConfigurations(Ptr< LorawanMac > lorawanMac) const
Apply configurations that are common both for the GatewayLorawanMac and the ClassAEndDeviceLorawanMac...
DeviceType
Define the kind of device.
void ApplyCommonAlohaConfigurations(Ptr< LorawanMac > lorawanMac) const
Apply configurations that are common both for the GatewayLorawanMac and the ClassAEndDeviceLorawanMac...
enum DeviceType m_deviceType
The kind of device to install.
void ConfigureForEuRegion(Ptr< ClassAEndDeviceLorawanMac > edMac) const
Perform region-specific configurations for the 868 MHz EU band.
Class representing the LoRaWAN MAC layer.
Definition lorawan-mac.h:37
std::array< std::array< uint8_t, 6 >, 8 > ReplyDataRateMatrix
Matrix structure to store possible data rate value to be used by a LoRaWAN end device for listening d...
Definition lorawan-mac.h:53
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580