A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
class-a-end-device-lorawan-mac.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Davide Magrin <magrinda@dei.unipd.it>
18 * Martina Capuzzo <capuzzom@dei.unipd.it>
19 *
20 * Modified by: Peggy Anderson <peggy.anderson@usask.ca>
21 * qiuyukang <b612n@qq.com>
22 */
23
25
26#include "end-device-lora-phy.h"
28
29#include "ns3/log.h"
30
31#include <algorithm>
32
33namespace ns3
34{
35namespace lorawan
36{
37
38NS_LOG_COMPONENT_DEFINE("ClassAEndDeviceLorawanMac");
39
40NS_OBJECT_ENSURE_REGISTERED(ClassAEndDeviceLorawanMac);
41
42TypeId
44{
45 static TypeId tid = TypeId("ns3::ClassAEndDeviceLorawanMac")
47 .SetGroupName("lorawan")
48 .AddConstructor<ClassAEndDeviceLorawanMac>();
49 return tid;
50}
51
53 : // LoraWAN default
54 m_receiveDelay1(Seconds(1)),
55 // LoraWAN default
56 m_receiveDelay2(Seconds(2)),
57 m_rx1DrOffset(0)
58{
59 NS_LOG_FUNCTION(this);
60
61 // Void the two receiveWindow events
68}
69
71{
73}
74
75/////////////////////
76// Sending methods //
77/////////////////////
78
79void
81{
82 /////////////////////////////////////////////////////////
83 // Add headers, prepare TX parameters and send the packet
84 /////////////////////////////////////////////////////////
85
86 NS_LOG_DEBUG("PacketToSend: " << packetToSend);
87
88 // Data rate adaptation as in LoRaWAN specification, V1.0.2 (2016)
90 (m_retxParams.retxLeft % 2 == 0))
91 {
92 m_txPower = 14; // Reset transmission power
94 }
95
96 // Craft LoraTxParameters object
97 LoraTxParameters params;
98 params.sf = GetSfFromDataRate(m_dataRate);
99 params.headerDisabled = m_headerDisabled;
100 params.codingRate = m_codingRate;
101 params.bandwidthHz = GetBandwidthFromDataRate(m_dataRate);
102 params.nPreamble = m_nPreambleSymbols;
103 params.crcEnabled = true;
104 params.lowDataRateOptimizationEnabled = LoraPhy::GetTSym(params) > MilliSeconds(16);
105
106 // Wake up PHY layer and directly send the packet
107
109
110 NS_LOG_DEBUG("PacketToSend: " << packetToSend);
111 m_phy->Send(packetToSend, params, txChannel->GetFrequency(), m_txPower);
112
113 //////////////////////////////////////////////
114 // Register packet transmission for duty cycle
115 //////////////////////////////////////////////
116
117 // Compute packet duration
118 Time duration = m_phy->GetOnAirTime(packetToSend, params);
119
120 // Register the sent packet into the DutyCycleHelper
121 m_channelHelper.AddEvent(duration, txChannel);
122
123 //////////////////////////////
124 // Prepare for the downlink //
125 //////////////////////////////
126
127 // Switch the PHY to the channel so that it will listen here for downlink
128 m_phy->GetObject<EndDeviceLoraPhy>()->SetFrequency(txChannel->GetFrequency());
129
130 // Instruct the PHY on the right Spreading Factor to listen for during the window
131 // create a SetReplyDataRate function?
132 uint8_t replyDataRate = GetFirstReceiveWindowDataRate();
133 NS_LOG_DEBUG("m_dataRate: " << unsigned(m_dataRate)
134 << ", m_rx1DrOffset: " << unsigned(m_rx1DrOffset)
135 << ", replyDataRate: " << unsigned(replyDataRate) << ".");
136
137 m_phy->GetObject<EndDeviceLoraPhy>()->SetSpreadingFactor(GetSfFromDataRate(replyDataRate));
138}
139
140//////////////////////////
141// Receiving methods //
142//////////////////////////
143void
145{
146 NS_LOG_FUNCTION(this << packet);
147
148 // Work on a copy of the packet
149 Ptr<Packet> packetCopy = packet->Copy();
150
151 // Remove the Mac Header to get some information
152 LorawanMacHeader mHdr;
153 packetCopy->RemoveHeader(mHdr);
154
155 NS_LOG_DEBUG("Mac Header: " << mHdr);
156
157 // Only keep analyzing the packet if it's downlink
158 if (!mHdr.IsUplink())
159 {
160 NS_LOG_INFO("Found a downlink packet.");
161
162 // Remove the Frame Header
163 LoraFrameHeader fHdr;
164 fHdr.SetAsDownlink();
165 packetCopy->RemoveHeader(fHdr);
166
167 NS_LOG_DEBUG("Frame Header: " << fHdr);
168
169 // Determine whether this packet is for us
170 bool messageForUs = (m_address == fHdr.GetAddress());
171
172 if (messageForUs)
173 {
174 NS_LOG_INFO("The message is for us!");
175
176 // If it exists, cancel the second receive window event
177 // THIS WILL BE GetReceiveWindow()
179
180 // Parse the MAC commands
181 ParseCommands(fHdr);
182
183 // TODO Pass the packet up to the NetDevice
184
185 // Call the trace source
186 m_receivedPacket(packet);
187 }
188 else
189 {
190 NS_LOG_DEBUG("The message is intended for another recipient.");
191
192 // In this case, we are either receiving in the first receive window
193 // and finishing reception inside the second one, or receiving a
194 // packet in the second receive window and finding out, after the
195 // fact, that the packet is not for us. In either case, if we no
196 // longer have any retransmissions left, we declare failure.
198 {
199 if (m_retxParams.retxLeft == 0)
200 {
201 uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
203 false,
206 NS_LOG_DEBUG("Failure: no more retransmissions left. Used "
207 << unsigned(txs) << " transmissions.");
208
209 // Reset retransmission parameters
211 }
212 else // Reschedule
213 {
214 this->Send(m_retxParams.packet);
215 NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
216 << " retransmissions left: rescheduling transmission.");
217 }
218 }
219 }
220 }
222 {
223 NS_LOG_INFO("The packet we are receiving is in uplink.");
224 if (m_retxParams.retxLeft > 0)
225 {
226 this->Send(m_retxParams.packet);
227 NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
228 << " retransmissions left: rescheduling transmission.");
229 }
230 else
231 {
232 uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
234 NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
235 << " transmissions.");
236
237 // Reset retransmission parameters
239 }
240 }
241
242 m_phy->GetObject<EndDeviceLoraPhy>()->SwitchToSleep();
243}
244
245void
247{
248 NS_LOG_FUNCTION(this << packet);
249
250 // Switch to sleep after a failed reception
251 m_phy->GetObject<EndDeviceLoraPhy>()->SwitchToSleep();
252
254 {
255 if (m_retxParams.retxLeft > 0)
256 {
257 this->Send(m_retxParams.packet);
258 NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
259 << " retransmissions left: rescheduling transmission.");
260 }
261 else
262 {
263 uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
265 NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
266 << " transmissions.");
267
268 // Reset retransmission parameters
270 }
271 }
272}
273
274void
276{
278
279 // Schedule the opening of the first receive window
281
282 // Schedule the opening of the second receive window
285 this);
286 // // Schedule the opening of the first receive window
287 // Simulator::Schedule (m_receiveDelay1,
288 // &ClassAEndDeviceLorawanMac::OpenFirstReceiveWindow, this);
289 //
290 // // Schedule the opening of the second receive window
291 // m_secondReceiveWindow = Simulator::Schedule (m_receiveDelay2,
292 // &ClassAEndDeviceLorawanMac::OpenSecondReceiveWindow,
293 // this);
294
295 // Switch the PHY to sleep
296 m_phy->GetObject<EndDeviceLoraPhy>()->SwitchToSleep();
297}
298
299void
301{
303
304 // Set Phy in Standby mode
305 m_phy->GetObject<EndDeviceLoraPhy>()->SwitchToStandby();
306
307 // Calculate the duration of a single symbol for the first receive window data rate
308 double tSym = pow(2, GetSfFromDataRate(GetFirstReceiveWindowDataRate())) /
310
311 // Schedule return to sleep after "at least the time required by the end
312 // device's radio transceiver to effectively detect a downlink preamble"
313 // (LoraWAN specification)
316 this); // m_receiveWindowDuration
317}
318
319void
321{
323
324 Ptr<EndDeviceLoraPhy> phy = m_phy->GetObject<EndDeviceLoraPhy>();
325
326 // Check the Phy layer's state:
327 // - RX -> We are receiving a preamble.
328 // - STANDBY -> Nothing was received.
329 // - SLEEP -> We have received a packet.
330 // We should never be in TX or SLEEP mode at this point
331 switch (phy->GetState())
332 {
334 NS_ABORT_MSG("PHY was in TX mode when attempting to "
335 << "close a receive window.");
336 break;
338 // PHY is receiving: let it finish. The Receive method will switch it back to SLEEP.
340 // PHY has received, and the MAC's Receive already put the device to sleep
341 break;
343 // Turn PHY layer to SLEEP
344 phy->SwitchToSleep();
345 break;
346 }
347}
348
349void
351{
353
354 // Check for receiver status: if it's locked on a packet, don't open this
355 // window at all.
356 if (m_phy->GetObject<EndDeviceLoraPhy>()->GetState() == EndDeviceLoraPhy::RX)
357 {
358 NS_LOG_INFO("Won't open second receive window since we are in RX mode.");
359
360 return;
361 }
362
363 // Set Phy in Standby mode
364 m_phy->GetObject<EndDeviceLoraPhy>()->SwitchToStandby();
365
366 // Switch to appropriate channel and data rate
367 NS_LOG_INFO("Using parameters: " << m_secondReceiveWindowFrequency << "Hz, DR"
368 << unsigned(m_secondReceiveWindowDataRate));
369
370 m_phy->GetObject<EndDeviceLoraPhy>()->SetFrequency(m_secondReceiveWindowFrequency);
371 m_phy->GetObject<EndDeviceLoraPhy>()->SetSpreadingFactor(
373
374 // Calculate the duration of a single symbol for the second receive window data rate
375 double tSym = pow(2, GetSfFromDataRate(GetSecondReceiveWindowDataRate())) /
377
378 // Schedule return to sleep after "at least the time required by the end
379 // device's radio transceiver to effectively detect a downlink preamble"
380 // (LoraWAN specification)
383 this);
384}
385
386void
388{
390
391 Ptr<EndDeviceLoraPhy> phy = m_phy->GetObject<EndDeviceLoraPhy>();
392
393 // NS_ASSERT (phy->m_state != EndDeviceLoraPhy::TX &&
394 // phy->m_state != EndDeviceLoraPhy::SLEEP);
395
396 // Check the Phy layer's state:
397 // - RX -> We have received a preamble.
398 // - STANDBY -> Nothing was detected.
399 switch (phy->GetState())
400 {
403 break;
405 // PHY is receiving: let it finish
406 NS_LOG_DEBUG("PHY is receiving: Receive will handle the result.");
407 return;
409 // Turn PHY layer to sleep
410 phy->SwitchToSleep();
411 break;
412 }
413
415 {
416 NS_LOG_DEBUG("No reception initiated by PHY: rescheduling transmission.");
417 if (m_retxParams.retxLeft > 0)
418 {
419 NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
420 << " retransmissions left: rescheduling transmission.");
421 this->Send(m_retxParams.packet);
422 }
423
424 else if (m_retxParams.retxLeft == 0 &&
426 {
427 uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
429 NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
430 << " transmissions.");
431
432 // Reset retransmission parameters
434 }
435
436 else
437 {
438 NS_ABORT_MSG("The number of retransmissions left is negative ! ");
439 }
440 }
441 else
442 {
443 uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
446 "We have " << unsigned(m_retxParams.retxLeft)
447 << " transmissions left. We were not transmitting confirmed messages.");
448
449 // Reset retransmission parameters
451 }
452}
453
454/////////////////////////
455// Getters and Setters //
456/////////////////////////
457
458Time
460{
462
463 // This is a new packet from APP; it can not be sent until the end of the
464 // second receive window (if the second receive window has not closed yet)
466 {
469 {
470 NS_LOG_WARN("Attempting to send when there are receive windows:"
471 << " Transmission postponed.");
472 // Compute the duration of a single symbol for the second receive window data rate
473 double tSym = pow(2, GetSfFromDataRate(GetSecondReceiveWindowDataRate())) /
475 // Compute the closing time of the second receive window
476 Time endSecondRxWindow = Time(m_secondReceiveWindow.GetTs()) +
478
479 NS_LOG_DEBUG("Duration until endSecondRxWindow for new transmission:"
480 << (endSecondRxWindow - Simulator::Now()).GetSeconds());
481 waitingTime = std::max(waitingTime, endSecondRxWindow - Simulator::Now());
482 }
483 }
484 // This is a retransmitted packet, it can not be sent until the end of
485 // ACK_TIMEOUT (this timer starts when the second receive window was open)
486 else
487 {
488 double ack_timeout = m_uniformRV->GetValue(1, 3);
489 // Compute the duration until ACK_TIMEOUT (It may be a negative number, but it doesn't
490 // matter.)
491 Time retransmitWaitingTime =
493
494 NS_LOG_DEBUG("ack_timeout:" << ack_timeout << " retransmitWaitingTime:"
495 << retransmitWaitingTime.GetSeconds());
496 waitingTime = std::max(waitingTime, retransmitWaitingTime);
497 }
498
499 return waitingTime;
500}
501
502uint8_t
504{
506}
507
508void
510{
512}
513
514uint8_t
516{
518}
519
520void
522{
523 m_secondReceiveWindowFrequency = frequencyMHz;
524}
525
526double
528{
530}
531
532/////////////////////////
533// MAC command methods //
534/////////////////////////
535
536void
538{
539 NS_LOG_FUNCTION(this << rxParamSetupReq);
540
541 bool offsetOk = true;
542 bool dataRateOk = true;
543
544 uint8_t rx1DrOffset = rxParamSetupReq->GetRx1DrOffset();
545 uint8_t rx2DataRate = rxParamSetupReq->GetRx2DataRate();
546 double frequency = rxParamSetupReq->GetFrequency();
547
548 NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency);
549
550 // Check that the desired offset is valid
551 if (!(0 <= rx1DrOffset && rx1DrOffset <= 5))
552 {
553 offsetOk = false;
554 }
555
556 // Check that the desired data rate is valid
557 if (GetSfFromDataRate(rx2DataRate) == 0 || GetBandwidthFromDataRate(rx2DataRate) == 0)
558 {
559 dataRateOk = false;
560 }
561
562 // For now, don't check for validity of frequency
563 m_secondReceiveWindowDataRate = rx2DataRate;
564 m_rx1DrOffset = rx1DrOffset;
566
567 // Craft a RxParamSetupAns as response
568 NS_LOG_INFO("Adding RxParamSetupAns reply");
569 m_macCommandList.emplace_back(CreateObject<RxParamSetupAns>(offsetOk, dataRateOk, true));
570}
571
572} /* namespace lorawan */
573} /* namespace ns3 */
An identifier for simulation events.
Definition: event-id.h:56
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:69
uint64_t GetTs() const
Definition: event-id.cc:96
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:285
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
Class representing the MAC layer of a Class A LoRaWAN device.
uint8_t m_rx1DrOffset
The RX1DROffset parameter value.
void OpenSecondReceiveWindow()
Perform operations needed to open the second receive window.
uint8_t GetSecondReceiveWindowDataRate() const
Get the data rate that will be used in the second receive window.
Time m_receiveDelay2
The interval between when a packet is done sending and when the second receive window is opened.
void FailedReception(Ptr< const Packet > packet) override
Function called by lower layers to inform this layer that reception of a packet we were locked on fai...
double GetSecondReceiveWindowFrequency() const
Get the frequency that is used for the second receive window.
double m_secondReceiveWindowFrequency
The frequency to listen on for the second receive window.
EventId m_closeFirstWindow
The event of the closing the first receive window.
uint8_t m_secondReceiveWindowDataRate
The data rate to listen for during the second downlink transmission.
Time m_receiveDelay1
The interval between when a packet is done sending and when the first receive window is opened.
Time GetNextClassTransmissionDelay(Time waitingTime) override
Find the minimum waiting time before the next possible transmission based on end device's Class Type.
void OnRxClassParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq) override
Perform the actions that need to be taken when receiving a RxParamSetupReq command based on the Devic...
void CloseFirstReceiveWindow()
Perform operations needed to close the first receive window.
void SendToPhy(Ptr< Packet > packet) override
Add headers and send a packet with the sending function of the physical layer.
void TxFinished(Ptr< const Packet > packet) override
Perform actions after sending a packet.
void CloseSecondReceiveWindow()
Perform operations needed to close the second receive window.
uint8_t GetFirstReceiveWindowDataRate()
Get the data rate that will be used in the first receive window.
EventId m_closeSecondWindow
The event of the closing the second receive window.
EventId m_secondReceiveWindow
The event of the second receive window opening.
void SetSecondReceiveWindowDataRate(uint8_t dataRate)
Set the data rate to be used in the second receive window.
void Receive(Ptr< const Packet > packet) override
Receive a packet.
void SetSecondReceiveWindowFrequency(double frequencyMHz)
Set the frequency that will be used for the second receive window.
void OpenFirstReceiveWindow()
Perform operations needed to open the first receive window.
Class representing a LoRa transceiver.
EndDeviceLoraPhy::State GetState()
Return the state this end device is currently in.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ SLEEP
The PHY layer is sleeping.
@ STANDBY
The PHY layer is in STANDBY.
Class representing the MAC layer of a LoRaWAN device.
uint8_t m_maxNumbTx
Default number of unacknowledged redundant transmissions of each packet.
bool m_headerDisabled
Whether or not the LoRa PHY header is disabled for communications by this device.
Ptr< LogicalLoraChannel > GetChannelForTx()
Find a suitable channel for transmission.
TracedValue< double > m_txPower
The transmission power this device is using to transmit.
uint8_t m_codingRate
The coding rate used by this device.
bool m_enableDRAdapt
Enable data rate adaptation (ADR) during the retransmission procedure.
Ptr< UniformRandomVariable > m_uniformRV
An uniform random variable, used by the Shuffle method to randomly reorder the channel list.
virtual void resetRetransmissionParameters()
Reset retransmission parameters contained in the structure LoraRetxParams.
void ParseCommands(LoraFrameHeader frameHeader)
Parse and take action on the commands contained on this FrameHeader.
TracedCallback< uint8_t, bool, Time, Ptr< Packet > > m_requiredTxCallback
The trace source fired when the transmission procedure is finished.
std::list< Ptr< MacCommand > > m_macCommandList
List of the MAC commands that need to be applied to the next UL packet.
TracedValue< uint8_t > m_dataRate
The data rate this device is using to transmit.
LoraDeviceAddress m_address
The address of this device.
void Send(Ptr< Packet > packet) override
Send a packet.
uint8_t m_receiveWindowDurationInSymbols
The duration of a receive window in number of symbols.
struct LoraRetxParameters m_retxParams
Structure containing the retransmission parameters for this device.
void AddEvent(Time duration, Ptr< LogicalLoraChannel > channel)
Register the transmission of a packet.
This class represents the Frame header (FHDR) used in a LoraWAN network.
LoraDeviceAddress GetAddress() const
Get this header's device address value.
void SetAsDownlink()
State that this is a downlink message.
static Time GetTSym(LoraTxParameters txParams)
Compute the symbol time from spreading factor and bandwidth.
Definition: lora-phy.cc:161
This class represents the Mac header of a LoRaWAN packet.
bool IsUplink() const
Check whether this header is for an uplink message.
TracedCallback< Ptr< const Packet > > m_receivedPacket
Trace source that is fired when a packet reaches the MAC layer.
Definition: lorawan-mac.h:236
uint8_t GetSfFromDataRate(uint8_t dataRate)
Get the spreading factor corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:111
double GetBandwidthFromDataRate(uint8_t dataRate)
Get the bandwidth corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:125
ReplyDataRateMatrix m_replyDataRateMatrix
The matrix that decides the data rate the gateway will use in a reply based on the end device's sendi...
Definition: lorawan-mac.h:289
LogicalLoraChannelHelper m_channelHelper
The LogicalLoraChannelHelper instance that is assigned to this MAC.
Definition: lorawan-mac.h:257
Ptr< LoraPhy > m_phy
The PHY instance that sits under this MAC layer.
Definition: lorawan-mac.h:247
int m_nPreambleSymbols
The number of symbols to use in the PHY preamble.
Definition: lorawan-mac.h:278
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#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_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 ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool waitingAck
Whether the packet requires explicit acknowledgment.
uint8_t retxLeft
Number of retransmission attempts left.
Time firstAttempt
Timestamp of the first transmission of the packet.
Ptr< Packet > packet
A pointer to the packet being retransmitted.
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition: lora-phy.h:49