A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lr-wpan-mac.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 The Boeing Company
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors:
7 * Gary Pei <guangyu.pei@boeing.com>
8 * kwong yin <kwong-sang.yin@boeing.com>
9 * Tom Henderson <thomas.r.henderson@boeing.com>
10 * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
11 * Erwan Livolant <erwan.livolant@inria.fr>
12 * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
13 */
14#include "lr-wpan-mac.h"
15
16#include "lr-wpan-constants.h"
17#include "lr-wpan-csmaca.h"
19#include "lr-wpan-mac-trailer.h"
20
21#include "ns3/double.h"
22#include "ns3/log.h"
23#include "ns3/node.h"
24#include "ns3/packet.h"
25#include "ns3/random-variable-stream.h"
26#include "ns3/simulator.h"
27#include "ns3/uinteger.h"
28
29#undef NS_LOG_APPEND_CONTEXT
30#define NS_LOG_APPEND_CONTEXT \
31 std::clog << "[" << m_shortAddress << " | " << m_macExtendedAddress << "] ";
32
33namespace ns3
34{
35namespace lrwpan
36{
37
38NS_LOG_COMPONENT_DEFINE("LrWpanMac");
40
41std::ostream&
42operator<<(std::ostream& os, const MacState& state)
43{
44 switch (state)
45 {
47 os << "MAC IDLE";
48 break;
50 os << "CSMA";
51 break;
53 os << "SENDING";
54 break;
56 os << "ACK PENDING";
57 break;
59 os << "CHANNEL_ACCESS_FAILURE";
60 break;
62 os << "CHANNEL IDLE";
63 break;
65 os << "SET PHY to TX ON";
66 break;
68 os << "MAC GTS PERIOD";
69 break;
71 os << "SUPERFRAME INACTIVE PERIOD";
72 break;
74 os << "CSMA DEFERRED TO NEXT PERIOD";
75 break;
76 }
77 return os;
78}
79
82{
83 static TypeId tid =
84 TypeId("ns3::lrwpan::LrWpanMac")
85 .AddDeprecatedName("ns3::LrWpanMac")
87 .SetGroupName("LrWpan")
88 .AddConstructor<LrWpanMac>()
89 .AddAttribute("PanId",
90 "16-bit identifier of the associated PAN",
94 .AddTraceSource("MacTxEnqueue",
95 "Trace source indicating a packet has been "
96 "enqueued in the transaction queue",
98 "ns3::Packet::TracedCallback")
99 .AddTraceSource("MacTxDequeue",
100 "Trace source indicating a packet has was "
101 "dequeued from the transaction queue",
103 "ns3::Packet::TracedCallback")
104 .AddTraceSource("MacIndTxEnqueue",
105 "Trace source indicating a packet has been "
106 "enqueued in the indirect transaction queue",
108 "ns3::Packet::TracedCallback")
109 .AddTraceSource("MacIndTxDequeue",
110 "Trace source indicating a packet has was "
111 "dequeued from the indirect transaction queue",
113 "ns3::Packet::TracedCallback")
114 .AddTraceSource("MacTx",
115 "Trace source indicating a packet has "
116 "arrived for transmission by this device",
118 "ns3::Packet::TracedCallback")
119 .AddTraceSource("MacTxOk",
120 "Trace source indicating a packet has been "
121 "successfully sent",
123 "ns3::Packet::TracedCallback")
124 .AddTraceSource("MacTxDrop",
125 "Trace source indicating a packet has been "
126 "dropped during transmission",
128 "ns3::Packet::TracedCallback")
129 .AddTraceSource("MacIndTxDrop",
130 "Trace source indicating a packet has been "
131 "dropped from the indirect transaction queue"
132 "(The pending transaction list)",
134 "ns3::Packet::TracedCallback")
135 .AddTraceSource("MacPromiscRx",
136 "A packet has been received by this device, "
137 "has been passed up from the physical layer "
138 "and is being forwarded up the local protocol stack. "
139 "This is a promiscuous trace,",
141 "ns3::Packet::TracedCallback")
142 .AddTraceSource("MacRx",
143 "A packet has been received by this device, "
144 "has been passed up from the physical layer "
145 "and is being forwarded up the local protocol stack. "
146 "This is a non-promiscuous trace,",
148 "ns3::Packet::TracedCallback")
149 .AddTraceSource("MacRxDrop",
150 "Trace source indicating a packet was received, "
151 "but dropped before being forwarded up the stack",
153 "ns3::Packet::TracedCallback")
154 .AddTraceSource("Sniffer",
155 "Trace source simulating a non-promiscuous "
156 "packet sniffer attached to the device",
158 "ns3::Packet::TracedCallback")
159 .AddTraceSource("PromiscSniffer",
160 "Trace source simulating a promiscuous "
161 "packet sniffer attached to the device",
163 "ns3::Packet::TracedCallback")
164 .AddTraceSource("MacStateValue",
165 "The state of LrWpan Mac",
167 "ns3::TracedValueCallback::LrWpanMacState")
168 .AddTraceSource("MacIncSuperframeStatus",
169 "The period status of the incoming superframe",
171 "ns3::TracedValueCallback::SuperframeState")
172 .AddTraceSource("MacOutSuperframeStatus",
173 "The period status of the outgoing superframe",
175 "ns3::TracedValueCallback::SuperframeState")
176 .AddTraceSource("MacState",
177 "The state of LrWpan Mac",
179 "ns3::lrwpan::LrWpanMac::StateTracedCallback")
180 .AddTraceSource("MacSentPkt",
181 "Trace source reporting some information about "
182 "the sent packet",
184 "ns3::lrwpan::LrWpanMac::SentTracedCallback")
185 .AddTraceSource("IfsEnd",
186 "Trace source reporting the end of an "
187 "Interframe space (IFS)",
189 "ns3::Packet::TracedCallback");
190 return tid;
191}
192
194{
195 // First set the state to a known value, call ChangeMacState to fire trace source.
197
199
202
203 m_macRxOnWhenIdle = true;
204 m_macPanId = 0xffff;
206 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
209 m_macPromiscuousMode = false;
213 m_txPkt = nullptr;
214 m_rxPkt = nullptr;
216 m_ifs = 0;
217
218 m_macLIFSPeriod = 40;
219 m_macSIFSPeriod = 12;
220
221 m_panCoor = false;
222 m_coor = false;
223 m_macBeaconOrder = 15;
225 m_macTransactionPersistenceTime = 500; // 0x01F5
227 m_macAutoRequest = true;
228
231 m_beaconTrackingOn = false;
233
237
240
241 m_maxTxQueueSize = m_txQueue.max_size();
243
247 m_shortAddress = Mac16Address("FF:FF"); // FF:FF = The address is not assigned.
248}
249
254
255void
257{
258 NS_LOG_FUNCTION(this);
259
260 m_macDsn = SequenceNumber8(m_uniformVar->GetInteger(0, 255));
261 m_macBsn = SequenceNumber8(m_uniformVar->GetInteger(0, 255));
263 {
264 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
265 }
266 else
267 {
268 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
269 }
270
272}
273
274void
276{
277 NS_LOG_FUNCTION(this);
278
279 if (m_csmaCa)
280 {
281 m_csmaCa->Dispose();
282 m_csmaCa = nullptr;
283 }
284 m_txPkt = nullptr;
285
286 for (uint32_t i = 0; i < m_txQueue.size(); i++)
287 {
288 m_txQueue[i]->txQPkt = nullptr;
289 }
290 m_txQueue.clear();
291
292 for (uint32_t i = 0; i < m_indTxQueue.size(); i++)
293 {
294 m_indTxQueue[i]->txQPkt = nullptr;
295 }
296 m_indTxQueue.clear();
297
298 m_uniformVar = nullptr;
299 m_phy = nullptr;
312
313 m_panDescriptorList.clear();
314 m_energyDetectList.clear();
315 m_unscannedChannels.clear();
316
317 m_scanEvent.Cancel();
318 m_scanEnergyEvent.Cancel();
319 m_scanOrphanEvent.Cancel();
320 m_beaconEvent.Cancel();
322
324}
325
326bool
328{
329 return m_macRxOnWhenIdle;
330}
331
332void
334{
335 NS_LOG_FUNCTION(this << rxOnWhenIdle);
336 m_macRxOnWhenIdle = rxOnWhenIdle;
337
338 if (m_macState == MAC_IDLE)
339 {
341 {
342 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
343 }
344 else
345 {
346 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
347 }
348 }
349}
350
351void
356
357void
362
365{
366 return m_shortAddress;
367}
368
374
375void
377{
378 NS_LOG_FUNCTION(this << p);
379
380 McpsDataConfirmParams confirmParams;
381 confirmParams.m_msduHandle = params.m_msduHandle;
382
383 // TODO: We need a drop trace for the case that the packet is too large or the request
384 // parameters are maleformed.
385 // The current tx drop trace is not suitable, because packets dropped using this trace
386 // carry the mac header and footer, while packets being dropped here do not have them.
387
389 m_macDsn++;
390
392 {
393 // Note, this is just testing maximum theoretical frame size per the spec
394 // The frame could still be too large once headers are put on
395 // in which case the phy will reject it instead
396 NS_LOG_ERROR(this << " packet too big: " << p->GetSize());
397 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
398 if (!m_mcpsDataConfirmCallback.IsNull())
399 {
400 m_mcpsDataConfirmCallback(confirmParams);
401 }
402 return;
403 }
404
405 if ((params.m_srcAddrMode == NO_PANID_ADDR) && (params.m_dstAddrMode == NO_PANID_ADDR))
406 {
407 NS_LOG_ERROR(this << " Can not send packet with no Address field");
408 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
409 if (!m_mcpsDataConfirmCallback.IsNull())
410 {
411 m_mcpsDataConfirmCallback(confirmParams);
412 }
413 return;
414 }
415 switch (params.m_srcAddrMode)
416 {
417 case NO_PANID_ADDR:
418 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
419 macHdr.SetNoPanIdComp();
420 break;
422 NS_ABORT_MSG("Can not set source address type to ADDR_MODE_RESERVED. Aborting.");
423 break;
424 case SHORT_ADDR:
425 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
427 break;
428 case EXT_ADDR:
429 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
431 break;
432 default:
433 NS_LOG_ERROR(this << " Can not send packet with incorrect Source Address mode = "
434 << params.m_srcAddrMode);
435 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
436 if (!m_mcpsDataConfirmCallback.IsNull())
437 {
438 m_mcpsDataConfirmCallback(confirmParams);
439 }
440 return;
441 }
442 switch (params.m_dstAddrMode)
443 {
444 case NO_PANID_ADDR:
445 macHdr.SetDstAddrMode(params.m_dstAddrMode);
446 macHdr.SetNoPanIdComp();
447 break;
449 NS_ABORT_MSG("Can not set destination address type to ADDR_MODE_RESERVED. Aborting.");
450 break;
451 case SHORT_ADDR:
452 macHdr.SetDstAddrMode(params.m_dstAddrMode);
453 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstAddr);
454 break;
455 case EXT_ADDR:
456 macHdr.SetDstAddrMode(params.m_dstAddrMode);
457 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstExtAddr);
458 break;
459 default:
460 NS_LOG_ERROR(this << " Can not send packet with incorrect Destination Address mode = "
461 << params.m_dstAddrMode);
462 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
463 if (!m_mcpsDataConfirmCallback.IsNull())
464 {
465 m_mcpsDataConfirmCallback(confirmParams);
466 }
467 return;
468 }
469
470 // IEEE 802.15.4-2006 (7.5.6.1)
471 // Src & Dst PANs are identical, PAN compression is ON
472 // only the dst PAN is serialized making the MAC header 2 bytes smaller
473 if ((params.m_dstAddrMode != NO_PANID_ADDR && params.m_srcAddrMode != NO_PANID_ADDR) &&
474 (macHdr.GetDstPanId() == macHdr.GetSrcPanId()))
475 {
476 macHdr.SetPanIdComp();
477 }
478
479 macHdr.SetSecDisable();
480 // extract the first 3 bits in TxOptions
481 int b0 = params.m_txOptions & TX_OPTION_ACK;
482 int b1 = params.m_txOptions & TX_OPTION_GTS;
483 int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
484
485 if (b0 == TX_OPTION_ACK)
486 {
487 // Set AckReq bit only if the destination is not the broadcast address.
488 if (macHdr.GetDstAddrMode() == SHORT_ADDR)
489 {
490 // short address and ACK requested.
491 Mac16Address shortAddr = macHdr.GetShortDstAddr();
492 if (shortAddr.IsBroadcast() || shortAddr.IsMulticast())
493 {
494 NS_LOG_LOGIC("LrWpanMac::McpsDataRequest: requested an ACK on broadcast or "
495 "multicast destination ("
496 << shortAddr << ") - forcefully removing it.");
497 macHdr.SetNoAckReq();
498 params.m_txOptions &= ~uint8_t(TX_OPTION_ACK);
499 }
500 else
501 {
502 macHdr.SetAckReq();
503 }
504 }
505 else
506 {
507 // other address (not short) and ACK requested
508 macHdr.SetAckReq();
509 }
510 }
511 else
512 {
513 macHdr.SetNoAckReq();
514 }
515
516 if (b1 == TX_OPTION_GTS)
517 {
518 // TODO:GTS Transmission
519 }
520 else if (b2 == TX_OPTION_INDIRECT)
521 {
522 // Indirect Tx
523 // A COORDINATOR will save the packet in the pending queue and await for data
524 // requests from its associated devices. The devices are aware of pending data,
525 // from the pending bit information extracted from the received beacon.
526 // A DEVICE must be tracking beacons (MLME-SYNC.request is running) before attempting
527 // request data from the coordinator.
528
529 // Indirect Transmission can only be done by PAN coordinator or coordinators.
531 p->AddHeader(macHdr);
532
533 LrWpanMacTrailer macTrailer;
534 // Calculate FCS if the global attribute ChecksumEnabled is set.
536 {
537 macTrailer.EnableFcs(true);
538 macTrailer.SetFcs(p);
539 }
540 p->AddTrailer(macTrailer);
541
542 NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
543 // Note: The current Pending transaction list should work for indirect transmissions.
544 // However, this is not tested yet. For now, we block the use of indirect transmissions.
545 // TODO: Save packet in the Pending Transaction list.
546 // EnqueueInd (p);
547 }
548 else
549 {
550 // Direct Tx
551 // From this point the packet will be pushed to a Tx queue and immediately
552 // use a slotted (beacon-enabled) or unslotted (nonbeacon-enabled) version of CSMA/CA
553 // before sending the packet, depending on whether it has previously
554 // received a valid beacon or not.
555
556 p->AddHeader(macHdr);
557
558 LrWpanMacTrailer macTrailer;
559 // Calculate FCS if the global attribute ChecksumEnabled is set.
561 {
562 macTrailer.EnableFcs(true);
563 macTrailer.SetFcs(p);
564 }
565 p->AddTrailer(macTrailer);
566
567 auto txQElement = std::make_shared<TxQueueElement>();
568 txQElement->txQMsduHandle = params.m_msduHandle;
569 txQElement->txQPkt = p;
570 EnqueueTxQElement(txQElement);
571 CheckQueue();
572 }
573}
574
575void
577{
578 NS_LOG_FUNCTION(this);
580
581 MlmeStartConfirmParams confirmParams;
582
583 if (GetShortAddress() == Mac16Address("ff:ff"))
584 {
585 NS_LOG_ERROR(this << " Invalid MAC short address");
587 if (!m_mlmeStartConfirmCallback.IsNull())
588 {
589 m_mlmeStartConfirmCallback(confirmParams);
590 }
591 return;
592 }
593
594 if ((params.m_bcnOrd > 15) || (params.m_sfrmOrd > params.m_bcnOrd))
595 {
597 if (!m_mlmeStartConfirmCallback.IsNull())
598 {
599 m_mlmeStartConfirmCallback(confirmParams);
600 }
601 NS_LOG_ERROR(this << "Incorrect superframe order or beacon order.");
602 return;
603 }
604
605 // Mark primitive as pending and save the start params while the new page and channel is set.
607 m_startParams = params;
608
610 pibAttr->phyCurrentPage = m_startParams.m_logChPage;
611 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
612}
613
614void
616{
617 NS_LOG_FUNCTION(this);
618
619 MlmeScanConfirmParams confirmParams;
620 confirmParams.m_scanType = params.m_scanType;
621 confirmParams.m_chPage = params.m_chPage;
622
623 if ((m_scanEvent.IsPending() || m_scanEnergyEvent.IsPending()) || m_scanOrphanEvent.IsPending())
624 {
625 if (!m_mlmeScanConfirmCallback.IsNull())
626 {
628 m_mlmeScanConfirmCallback(confirmParams);
629 }
630 NS_LOG_ERROR(this << " A channel scan is already in progress");
631 return;
632 }
633
634 if (params.m_scanDuration > 14 || params.m_scanType > MLMESCAN_ORPHAN)
635 {
636 if (!m_mlmeScanConfirmCallback.IsNull())
637 {
639 m_mlmeScanConfirmCallback(confirmParams);
640 }
641 NS_LOG_ERROR(this << "Invalid scan duration or unsupported scan type");
642 return;
643 }
644 // Temporary store macPanId and set macPanId to 0xFFFF to accept all beacons.
646 m_macPanId = 0xFFFF;
647
648 m_panDescriptorList.clear();
649 m_energyDetectList.clear();
650 m_unscannedChannels.clear();
651
652 // TODO: stop beacon transmission
653
654 // Cancel any ongoing CSMA/CA operations and set to unslotted mode for scan
655 m_csmaCa->Cancel();
656 m_capEvent.Cancel();
657 m_cfpEvent.Cancel();
658 m_incCapEvent.Cancel();
659 m_incCfpEvent.Cancel();
660 m_trackingEvent.Cancel();
661 m_csmaCa->SetUnSlottedCsmaCa();
662
664
665 // Mark primitive as pending and save the scan params while the new page and/or channel is set.
666 m_scanParams = params;
668
670 pibAttr->phyCurrentPage = params.m_chPage;
671 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
672}
673
674void
676{
677 NS_LOG_FUNCTION(this);
678
679 // Association is typically preceded by beacon reception and a MLME-SCAN.request, therefore,
680 // the values of the Associate.request params usually come from the information
681 // obtained from those operations.
683 m_associateParams = params;
684 m_ignoreDataCmdAck = false;
685
686 bool invalidRequest = false;
687
688 if (params.m_coordPanId == 0xffff)
689 {
690 invalidRequest = true;
691 }
692
693 if (!invalidRequest && params.m_coordAddrMode == SHORT_ADDR)
694 {
695 if (params.m_coordShortAddr == Mac16Address("ff:ff") ||
696 params.m_coordShortAddr == Mac16Address("ff:fe"))
697 {
698 invalidRequest = true;
699 }
700 }
701 else if (!invalidRequest && params.m_coordAddrMode == EXT_ADDR)
702 {
703 if (params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ff") ||
704 params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed"))
705 {
706 invalidRequest = true;
707 }
708 }
709
710 if (invalidRequest)
711 {
714 NS_LOG_ERROR(this << " Invalid PAN id in Association request");
715 if (!m_mlmeAssociateConfirmCallback.IsNull())
716 {
717 MlmeAssociateConfirmParams confirmParams;
718 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
720 m_mlmeAssociateConfirmCallback(confirmParams);
721 }
722 }
723 else
724 {
726 pibAttr->phyCurrentPage = params.m_chPage;
727 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
728 }
729}
730
731void
733{
734 // the primitive is no longer pending (channel & page are set)
736 // As described in IEEE 802.15.4-2011 (Section 5.1.3.1)
737 m_macPanId = m_associateParams.m_coordPanId;
738 if (m_associateParams.m_coordAddrMode == SHORT_ADDR)
739 {
740 m_macCoordShortAddress = m_associateParams.m_coordShortAddr;
741 }
742 else
743 {
746 }
747
749}
750
751void
753{
754 // Associate Short Address (m_assocShortAddr)
755 // FF:FF = Association Request failed
756 // FF:FE = The association request is accepted, but the device should use its extended address
757 // Other = The assigned short address by the coordinator
758
759 NS_LOG_FUNCTION(this);
760
762 m_macDsn++;
763 LrWpanMacTrailer macTrailer;
764 Ptr<Packet> commandPacket = Create<Packet>();
765
766 // Mac header Assoc. Response Comm. See 802.15.4-2011 (Section 5.3.2.1)
769 macHdr.SetPanIdComp();
770 macHdr.SetDstAddrFields(m_macPanId, params.m_extDevAddr);
771 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
772
774 macPayload.SetShortAddr(params.m_assocShortAddr);
775 macPayload.SetAssociationStatus(static_cast<uint8_t>(params.m_status));
776
777 macHdr.SetSecDisable();
778 macHdr.SetAckReq();
779
780 commandPacket->AddHeader(macPayload);
781 commandPacket->AddHeader(macHdr);
782
783 // Calculate FCS if the global attribute ChecksumEnabled is set.
785 {
786 macTrailer.EnableFcs(true);
787 macTrailer.SetFcs(commandPacket);
788 }
789
790 commandPacket->AddTrailer(macTrailer);
791
792 // Save packet in the Pending Transaction list.
793 EnqueueInd(commandPacket);
794}
795
796void
798{
799 NS_LOG_FUNCTION(this);
800 // Mac header Coordinator realigment Command
801 // See 802.15.4-2011 (Section 6.2.7.2)
803 m_macDsn++;
804 LrWpanMacTrailer macTrailer;
805 Ptr<Packet> commandPacket = Create<Packet>();
806 macHdr.SetPanIdComp();
808 macHdr.SetDstAddrFields(0xffff, params.m_orphanAddr);
809
812 macHdr.SetSrcAddrFields(m_macPanId, Mac16Address("FF:FF"));
813
814 macHdr.SetFrameVer(0x01);
815 macHdr.SetSecDisable();
816 macHdr.SetAckReq();
817
819 macPayload.SetPanId(m_macPanId);
821 macPayload.SetChannel(m_phy->GetCurrentChannelNum());
822 macPayload.SetPage(m_phy->GetCurrentPage());
823
824 if (params.m_assocMember)
825 {
826 // The orphan device was associated with the coordinator
827
828 // Either FF:FE for extended address mode
829 // or the short address assigned by the coord.
830 macPayload.SetShortAddr(params.m_shortAddr);
831 }
832 else
833 {
834 // The orphan device was NOT associated with the coordinator
835 macPayload.SetShortAddr(Mac16Address("FF:FF"));
836 }
837
838 commandPacket->AddHeader(macPayload);
839 commandPacket->AddHeader(macHdr);
840
841 // Calculate FCS if the global attribute ChecksumEnabled is set.
843 {
844 macTrailer.EnableFcs(true);
845 macTrailer.SetFcs(commandPacket);
846 }
847
848 commandPacket->AddTrailer(macTrailer);
849
850 auto txQElement = std::make_shared<TxQueueElement>();
851 txQElement->txQPkt = commandPacket;
852 EnqueueTxQElement(txQElement);
853 CheckQueue();
854}
855
856void
858{
859 NS_LOG_FUNCTION(this);
860 NS_ASSERT(params.m_logCh <= 26 && m_macPanId != 0xffff);
861
862 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
863 // change phy current logical channel
865 pibAttr->phyCurrentChannel = params.m_logCh;
866 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
867
868 // Enable Phy receiver
869 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
870
871 uint64_t searchSymbols;
872 Time searchBeaconTime;
873
874 if (m_trackingEvent.IsPending())
875 {
876 m_trackingEvent.Cancel();
877 }
878
879 if (params.m_trackBcn)
880 {
882 // search for a beacon for a time = incomingSuperframe symbols + 960 symbols
883 searchSymbols =
885 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
886 m_beaconTrackingOn = true;
888 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
889 }
890 else
891 {
892 m_beaconTrackingOn = false;
893 }
894}
895
896void
898{
899 NS_LOG_FUNCTION(this);
900
902 m_macBsn++;
903
905
906 Ptr<Packet> beaconPacket = Create<Packet>();
907 // TODO: complete poll request (part of indirect transmissions)
908 NS_FATAL_ERROR(this << " Poll request currently not supported");
909}
910
911void
913{
914 MlmeSetConfirmParams confirmParams;
915 confirmParams.m_status = MacStatus::SUCCESS;
916
917 switch (id)
918 {
920 m_macAssociationPermit = attribute->macAssociationPermit;
921 break;
922 case macBeaconPayload:
923 if (attribute->macBeaconPayload.size() > aMaxBeaconPayloadLength)
924 {
926 }
927 else
928 {
929 m_macBeaconPayload = attribute->macBeaconPayload;
930 }
931 break;
933 if (attribute->macBeaconPayloadLength > aMaxBeaconPayloadLength)
934 {
936 }
937 else
938 {
939 m_macBeaconPayloadLength = attribute->macBeaconPayloadLength;
940 }
941 break;
942 case macShortAddress:
943 m_shortAddress = attribute->macShortAddress;
944 break;
946 confirmParams.m_status = MacStatus::READ_ONLY;
947 break;
948 case macPanId:
950 break;
952 m_macPromiscuousMode = attribute->macPromiscuousMode;
953 break;
954 case macRxOnWhenIdle:
955 m_macRxOnWhenIdle = attribute->macRxOnWhenIdle;
956 break;
957 case pCurrentChannel: {
959 pibAttr->phyCurrentChannel = attribute->pCurrentChannel;
960 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
961 break;
962 }
963 case pCurrentPage: {
965 pibAttr->phyCurrentPage = attribute->pCurrentPage;
966 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
967 break;
968 }
970 m_macCoordExtendedAddress = attribute->macCoordExtendedAddress;
971 break;
973 m_macCoordShortAddress = attribute->macCoordShortAddress;
974 break;
975 default:
976 // TODO: Add support for setting other attributes
978 break;
979 }
980
981 if (!m_mlmeSetConfirmCallback.IsNull())
982 {
983 confirmParams.id = id;
984 m_mlmeSetConfirmCallback(confirmParams);
985 }
986}
987
988void
990{
993
994 switch (id)
995 {
997 attributes->macAssociationPermit = m_macAssociationPermit;
998 break;
999 case macBeaconPayload:
1000 attributes->macBeaconPayload = m_macBeaconPayload;
1001 break;
1003 attributes->macBeaconPayloadLength = m_macBeaconPayloadLength;
1004 break;
1005 case macPromiscuousMode:
1006 attributes->macPromiscuousMode = m_macPromiscuousMode;
1007 break;
1008 case macRxOnWhenIdle:
1009 attributes->macRxOnWhenIdle = m_macRxOnWhenIdle;
1010 break;
1011 case macShortAddress:
1012 attributes->macShortAddress = m_shortAddress;
1013 break;
1014 case macExtendedAddress:
1015 attributes->macExtendedAddress = m_macExtendedAddress;
1016 break;
1017 case macPanId:
1018 attributes->macPanId = m_macPanId;
1019 break;
1020 case pCurrentChannel:
1021 attributes->pCurrentChannel = m_phy->GetCurrentChannelNum();
1022 break;
1023 case pCurrentPage:
1024 attributes->pCurrentPage = m_phy->GetCurrentPage();
1025 break;
1026 default:
1028 break;
1029 }
1030
1031 if (!m_mlmeGetConfirmCallback.IsNull())
1032 {
1033 m_mlmeGetConfirmCallback(status, id, attributes);
1034 }
1035}
1036
1037void
1039 int8_t rssi,
1040 const LrWpanMacHeader& receivedMacHdr,
1041 Ptr<Packet> p)
1042{
1043 NS_LOG_FUNCTION(this);
1044
1045 NS_LOG_DEBUG("promiscuous mode, forwarding up");
1046
1047 // TODO: Fix here, this should trigger different Indication Callbacks
1048 // depending the type of frame received (data,command, beacon)
1049 if (!m_mcpsDataIndicationCallback.IsNull())
1050 {
1052 params.m_dsn = receivedMacHdr.GetSeqNum();
1053 params.m_mpduLinkQuality = lqi;
1054 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
1055 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
1056 params.m_rssi = rssi;
1057
1058 switch (params.m_srcAddrMode)
1059 {
1060 case SHORT_ADDR:
1061 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
1062 break;
1063 case EXT_ADDR:
1064 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
1065 break;
1066 default:
1067 break;
1068 }
1069
1070 params.m_dstPanId = receivedMacHdr.GetDstPanId();
1071 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
1072
1073 switch (params.m_dstAddrMode)
1074 {
1075 case SHORT_ADDR:
1076 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
1077 break;
1078 case EXT_ADDR:
1079 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
1080 break;
1081 default:
1082 break;
1083 }
1085 }
1086}
1087
1088void
1090{
1091 NS_LOG_FUNCTION(this);
1093
1094 m_macBsn++;
1095
1096 Ptr<Packet> beaconPacket;
1097 if (m_macBeaconPayload.empty())
1098 {
1099 beaconPacket = Create<Packet>();
1100 }
1101 else
1102 {
1103 // Extract the octets from m_macBeaconPayload and place them in a packet
1104 beaconPacket = Create<Packet>(m_macBeaconPayload.data(), m_macBeaconPayload.size());
1105 }
1106
1109 macHdr.SetDstAddrFields(GetPanId(), Mac16Address("ff:ff"));
1110
1111 // see IEEE 802.15.4-2011 Section 5.1.2.4
1112 if (GetShortAddress() == Mac16Address("ff:fe"))
1113 {
1116 }
1117 else
1118 {
1121 }
1122
1123 macHdr.SetSecDisable();
1124 macHdr.SetNoAckReq();
1125
1126 BeaconPayloadHeader macPayload;
1128 macPayload.SetGtsFields(GetGtsFields());
1130
1131 beaconPacket->AddHeader(macPayload);
1132 beaconPacket->AddHeader(macHdr);
1133
1134 // Calculate FCS if the global attribute ChecksumEnabled is set.
1135 LrWpanMacTrailer macTrailer;
1137 {
1138 macTrailer.EnableFcs(true);
1139 macTrailer.SetFcs(beaconPacket);
1140 }
1141
1142 beaconPacket->AddTrailer(macTrailer);
1143
1144 if (m_csmaCa->IsSlottedCsmaCa())
1145 {
1146 // Beacon in beacon-enabled mode
1147 // Transmit beacon immediately (i.e. Without CSMA/CA)
1148 m_txPkt = beaconPacket;
1150 NS_LOG_DEBUG("Outgoing superframe Active Portion (Beacon + CAP + CFP): "
1151 << m_superframeDuration << " symbols");
1152
1154 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
1155 }
1156 else
1157 {
1158 // Beacon as a result of a beacon request
1159 // The beacon shall be transmitted using CSMA/CA
1160 // IEEE 802.15.4-2011 (Section 5.1.2.1.2)
1161 auto txQElement = std::make_shared<TxQueueElement>();
1162 txQElement->txQPkt = beaconPacket;
1163 EnqueueTxQElement(txQElement);
1164 CheckQueue();
1165 }
1166}
1167
1168void
1170{
1171 NS_LOG_FUNCTION(this);
1172
1174 m_macDsn++;
1175 LrWpanMacTrailer macTrailer;
1176 Ptr<Packet> commandPacket = Create<Packet>();
1177
1178 // Beacon Request Command Mac header values See IEEE 802.15.4-2011 (Section 5.3.7)
1179 macHdr.SetNoPanIdComp();
1182
1183 // Not associated PAN, broadcast dst address
1184 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1185
1186 macHdr.SetSecDisable();
1187 macHdr.SetNoAckReq();
1188
1189 CommandPayloadHeader macPayload;
1191
1192 commandPacket->AddHeader(macPayload);
1193 commandPacket->AddHeader(macHdr);
1194
1195 // Calculate FCS if the global attribute ChecksumEnabled is set.
1197 {
1198 macTrailer.EnableFcs(true);
1199 macTrailer.SetFcs(commandPacket);
1200 }
1201
1202 commandPacket->AddTrailer(macTrailer);
1203
1204 auto txQElement = std::make_shared<TxQueueElement>();
1205 txQElement->txQPkt = commandPacket;
1206 EnqueueTxQElement(txQElement);
1207 CheckQueue();
1208}
1209
1210void
1212{
1214 m_macDsn++;
1215 LrWpanMacTrailer macTrailer;
1216 Ptr<Packet> commandPacket = Create<Packet>();
1217
1218 // See IEEE 802.15.4-2011 (5.3.6)
1219 macHdr.SetPanIdComp();
1220
1222 macHdr.SetSrcAddrFields(0xFFFF, GetExtendedAddress());
1223
1225 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1226
1227 macHdr.SetSecDisable();
1228 macHdr.SetNoAckReq();
1229
1230 CommandPayloadHeader macPayload;
1232
1233 commandPacket->AddHeader(macPayload);
1234 commandPacket->AddHeader(macHdr);
1235
1236 // Calculate FCS if the global attribute ChecksumEnabled is set.
1238 {
1239 macTrailer.EnableFcs(true);
1240 macTrailer.SetFcs(commandPacket);
1241 }
1242
1243 commandPacket->AddTrailer(macTrailer);
1244
1245 auto txQElement = std::make_shared<TxQueueElement>();
1246 txQElement->txQPkt = commandPacket;
1247 EnqueueTxQElement(txQElement);
1248 CheckQueue();
1249}
1250
1251void
1253{
1254 NS_LOG_FUNCTION(this);
1255
1257 m_macDsn++;
1258 LrWpanMacTrailer macTrailer;
1259 Ptr<Packet> commandPacket = Create<Packet>();
1260
1261 // Assoc. Req. Comm. Mac header values See IEEE 802.15.4-2011 (Section 5.3.1.1)
1263 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
1264
1265 if (m_associateParams.m_coordAddrMode == SHORT_ADDR)
1266 {
1268 macHdr.SetDstAddrFields(m_associateParams.m_coordPanId, m_associateParams.m_coordShortAddr);
1269 }
1270 else
1271 {
1273 macHdr.SetDstAddrFields(m_associateParams.m_coordPanId, m_associateParams.m_coordExtAddr);
1274 }
1275
1276 macHdr.SetSecDisable();
1277 macHdr.SetAckReq();
1278
1280 macPayload.SetCapabilityField(m_associateParams.m_capabilityInfo);
1281
1282 commandPacket->AddHeader(macPayload);
1283 commandPacket->AddHeader(macHdr);
1284
1285 // Calculate FCS if the global attribute ChecksumEnabled is set.
1287 {
1288 macTrailer.EnableFcs(true);
1289 macTrailer.SetFcs(commandPacket);
1290 }
1291
1292 commandPacket->AddTrailer(macTrailer);
1293
1294 auto txQElement = std::make_shared<TxQueueElement>();
1295 txQElement->txQPkt = commandPacket;
1296 EnqueueTxQElement(txQElement);
1297 CheckQueue();
1298}
1299
1300void
1302{
1303 // See IEEE 802.15.4-2011 (Section 5.3.5)
1304 // This command can be sent for 3 different situations:
1305 // a) In response to a beacon indicating that there is data for the device.
1306 // b) Triggered by MLME-POLL.request.
1307 // c) To follow an ACK of an Association Request command and continue the associate process.
1308
1309 // TODO: Implementation of a) and b) will be done when Indirect transmissions are fully
1310 // supported.
1311 // for now, only case c) is considered.
1312
1313 NS_LOG_FUNCTION(this);
1314
1316 m_macDsn++;
1317 LrWpanMacTrailer macTrailer;
1318 Ptr<Packet> commandPacket = Create<Packet>();
1319
1320 // Mac Header values (Section 5.3.5)
1322 macHdr.SetSrcAddrFields(0xffff, m_macExtendedAddress);
1323
1324 if (m_macCoordShortAddress == Mac16Address("ff:fe"))
1325 {
1328 }
1329 else
1330 {
1333 }
1334
1335 macHdr.SetSecDisable();
1336 macHdr.SetAckReq();
1337
1339
1340 commandPacket->AddHeader(macPayload);
1341 commandPacket->AddHeader(macHdr);
1342
1343 // Calculate FCS if the global attribute ChecksumEnabled is set.
1345 {
1346 macTrailer.EnableFcs(true);
1347 macTrailer.SetFcs(commandPacket);
1348 }
1349
1350 commandPacket->AddTrailer(macTrailer);
1351
1352 // Set the Command packet to be transmitted
1353 auto txQElement = std::make_shared<TxQueueElement>();
1354 txQElement->txQPkt = commandPacket;
1355 EnqueueTxQElement(txQElement);
1356 CheckQueue();
1357}
1358
1359void
1361{
1362 LrWpanMacHeader receivedMacHdr;
1363 rxDataReqPkt->RemoveHeader(receivedMacHdr);
1364 CommandPayloadHeader receivedMacPayload;
1365 rxDataReqPkt->RemoveHeader(receivedMacPayload);
1366
1368
1369 auto indTxQElement = std::make_shared<IndTxQueueElement>();
1370 bool elementFound;
1371 elementFound = DequeueInd(receivedMacHdr.GetExtSrcAddr(), indTxQElement);
1372 if (elementFound)
1373 {
1374 auto txQElement = std::make_shared<TxQueueElement>();
1375 txQElement->txQPkt = indTxQElement->txQPkt;
1376 m_txQueue.emplace_back(txQElement);
1377 }
1378 else
1379 {
1380 NS_LOG_DEBUG("Requested element not found in pending list");
1381 }
1382}
1383
1384void
1386{
1387 // Association response command was not received, return to default values.
1388 m_macPanId = 0xffff;
1390 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1391
1392 if (!m_mlmeAssociateConfirmCallback.IsNull())
1393 {
1394 MlmeAssociateConfirmParams confirmParams;
1395 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
1396 confirmParams.m_status = MacStatus::NO_DATA;
1397 m_mlmeAssociateConfirmCallback(confirmParams);
1398 }
1399}
1400
1401void
1403{
1404 NS_LOG_FUNCTION(this);
1405 // The primitive is no longer pending (Channel & Page have been set)
1407
1408 if (m_startParams.m_coorRealgn) // Coordinator Realignment
1409 {
1410 // TODO: Send realignment request command frame in CSMA/CA
1411 NS_LOG_ERROR(this << " Coordinator realignment request not supported");
1412 return;
1413 }
1414 else
1415 {
1416 if (m_startParams.m_panCoor)
1417 {
1418 m_panCoor = true;
1419 }
1420
1421 m_coor = true;
1422 m_macPanId = m_startParams.m_PanId;
1423
1424 NS_ASSERT(m_startParams.m_PanId != 0xffff);
1425
1427 if (m_macBeaconOrder == 15)
1428 {
1429 // Non-beacon enabled PAN
1430 // Cancel any ongoing events and CSMA-CA process
1432 m_fnlCapSlot = 15;
1433 m_beaconInterval = 0;
1434
1435 m_csmaCa->Cancel();
1436 m_capEvent.Cancel();
1437 m_cfpEvent.Cancel();
1438 m_incCapEvent.Cancel();
1439 m_incCfpEvent.Cancel();
1440 m_trackingEvent.Cancel();
1441 m_scanEvent.Cancel();
1442 m_scanOrphanEvent.Cancel();
1443 m_scanEnergyEvent.Cancel();
1444
1445 m_csmaCa->SetUnSlottedCsmaCa();
1446
1447 if (!m_mlmeStartConfirmCallback.IsNull())
1448 {
1449 MlmeStartConfirmParams confirmParams;
1450 confirmParams.m_status = MacStatus::SUCCESS;
1451 m_mlmeStartConfirmCallback(confirmParams);
1452 }
1453
1454 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
1455 }
1456 else
1457 {
1459 m_csmaCa->SetBatteryLifeExtension(m_startParams.m_battLifeExt);
1460
1461 m_csmaCa->SetSlottedCsmaCa();
1462
1463 // TODO: Calculate the real Final CAP slot (requires GTS implementation)
1464 // FinalCapSlot = Superframe duration slots - CFP slots.
1465 // In the current implementation the value of the final cap slot is equal to
1466 // the total number of possible slots in the superframe (15).
1467 m_fnlCapSlot = 15;
1468
1471 m_superframeDuration = (static_cast<uint32_t>(1 << m_macSuperframeOrder)) *
1473
1474 // TODO: change the beacon sending according to the startTime parameter (if not PAN
1475 // coordinator)
1476
1478 }
1479 }
1480}
1481
1482void
1484{
1485 NS_LOG_FUNCTION(this);
1486
1488
1489 bool channelFound = false;
1490
1491 for (int i = m_channelScanIndex; i <= 26; i++)
1492 {
1493 if ((m_scanParams.m_scanChannels & (1 << m_channelScanIndex)) != 0)
1494 {
1495 channelFound = true;
1496 break;
1497 }
1499 }
1500
1501 if (channelFound)
1502 {
1503 // Switch to the next channel in the list and restart scan
1505 pibAttr->phyCurrentChannel = m_channelScanIndex;
1506 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1507 }
1508 else
1509 {
1510 // All channels in the list scan completed.
1511 // Return variables to the values before the scan and return the status to the next layer.
1513 m_macPanIdScan = 0;
1514
1515 // TODO: restart beacon transmissions that were active before the beginning of the scan
1516 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1517 MlmeScanConfirmParams confirmParams;
1518 confirmParams.m_chPage = m_scanParams.m_chPage;
1519 confirmParams.m_scanType = m_scanParams.m_scanType;
1520 confirmParams.m_energyDetList = {};
1521 confirmParams.m_unscannedCh = m_unscannedChannels;
1522 confirmParams.m_resultListSize = m_panDescriptorList.size();
1523
1524 // See IEEE 802.15.4-2011, Table 31 (panDescriptorList value on macAutoRequest)
1525 // and Section 6.2.10.2
1526 switch (confirmParams.m_scanType)
1527 {
1528 case MLMESCAN_PASSIVE:
1529 if (m_macAutoRequest)
1530 {
1531 confirmParams.m_panDescList = m_panDescriptorList;
1532 }
1533 confirmParams.m_status = MacStatus::SUCCESS;
1534 break;
1535 case MLMESCAN_ACTIVE:
1536 if (m_panDescriptorList.empty())
1537 {
1538 confirmParams.m_status = MacStatus::NO_BEACON;
1539 }
1540 else
1541 {
1542 if (m_macAutoRequest)
1543 {
1544 confirmParams.m_panDescList = m_panDescriptorList;
1545 }
1546 confirmParams.m_status = MacStatus::SUCCESS;
1547 }
1548 break;
1549 case MLMESCAN_ORPHAN:
1550 confirmParams.m_panDescList = {};
1551 confirmParams.m_status = MacStatus::NO_BEACON;
1552 confirmParams.m_resultListSize = 0;
1553 // The device lost track of the coordinator and was unable
1554 // to locate it, disassociate from the network.
1555 m_macPanId = 0xffff;
1556 m_shortAddress = Mac16Address("FF:FF");
1558 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1559 break;
1560 default:
1561 NS_LOG_ERROR(this << " Invalid scan type");
1562 }
1563
1566 m_scanParams = {};
1567
1568 if (!m_mlmeScanConfirmCallback.IsNull())
1569 {
1570 m_mlmeScanConfirmCallback(confirmParams);
1571 }
1572 }
1573}
1574
1575void
1577{
1578 NS_LOG_FUNCTION(this);
1579 // Add the results of channel energy scan to the detectList
1581 m_maxEnergyLevel = 0;
1582
1584
1585 bool channelFound = false;
1586 for (int i = m_channelScanIndex; i <= 26; i++)
1587 {
1588 if ((m_scanParams.m_scanChannels & (1 << m_channelScanIndex)) != 0)
1589 {
1590 channelFound = true;
1591 break;
1592 }
1594 }
1595
1596 if (channelFound)
1597 {
1598 // switch to the next channel in the list and restart scan
1600 pibAttr->phyCurrentChannel = m_channelScanIndex;
1601 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1602 }
1603 else
1604 {
1605 // Scan on all channels on the list completed
1606 // Return to the MAC values previous to start of the first scan.
1608 m_macPanIdScan = 0;
1609
1610 // TODO: restart beacon transmissions that were active before the beginning of the scan
1611 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1612
1613 // All channels scanned, report success
1614 MlmeScanConfirmParams confirmParams;
1615 confirmParams.m_status = MacStatus::SUCCESS;
1616 confirmParams.m_chPage = m_phy->GetCurrentPage();
1617 confirmParams.m_scanType = m_scanParams.m_scanType;
1618 confirmParams.m_energyDetList = m_energyDetectList;
1619 confirmParams.m_resultListSize = m_energyDetectList.size();
1620
1623 m_scanParams = {};
1624
1625 if (!m_mlmeScanConfirmCallback.IsNull())
1626 {
1627 m_mlmeScanConfirmCallback(confirmParams);
1628 }
1629 }
1630}
1631
1632void
1634{
1635 uint32_t activeSlot;
1636 uint64_t capDuration;
1637 Time endCapTime;
1638 uint64_t symbolRate;
1639
1640 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1641
1642 if (superframeType == OUTGOING)
1643 {
1645 activeSlot = m_superframeDuration / 16;
1646 capDuration = activeSlot * (m_fnlCapSlot + 1);
1647 endCapTime = Seconds((double)capDuration / symbolRate);
1648 // Obtain the end of the CAP by adjust the time it took to send the beacon
1649 endCapTime -= (Simulator::Now() - m_macBeaconTxTime);
1650
1651 NS_LOG_DEBUG("Outgoing superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1652 << " symbols (" << endCapTime.As(Time::S)
1653 << ")");
1654 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1655
1656 m_capEvent =
1658 }
1659 else
1660 {
1662 activeSlot = m_incomingSuperframeDuration / 16;
1663 capDuration = activeSlot * (m_incomingFnlCapSlot + 1);
1664 endCapTime = Seconds((double)capDuration / symbolRate);
1665 // Obtain the end of the CAP by adjust the time it took to receive the beacon
1666 endCapTime -= (Simulator::Now() - m_macBeaconRxTime);
1667
1668 NS_LOG_DEBUG("Incoming superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1669 << " symbols (" << endCapTime.As(Time::S)
1670 << ")");
1671 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1672
1673 m_capEvent =
1675 }
1676
1677 CheckQueue();
1678}
1679
1680void
1682{
1683 uint32_t activeSlot;
1684 uint64_t cfpDuration;
1685 Time endCfpTime;
1686 uint64_t symbolRate;
1687
1688 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1689
1690 if (superframeType == INCOMING)
1691 {
1692 activeSlot = m_incomingSuperframeDuration / 16;
1693 cfpDuration = activeSlot * (15 - m_incomingFnlCapSlot);
1694 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1695 if (cfpDuration > 0)
1696 {
1698 }
1699
1700 NS_LOG_DEBUG("Incoming superframe CFP duration " << cfpDuration << " symbols ("
1701 << endCfpTime.As(Time::S) << ")");
1702
1705 this,
1707 }
1708 else
1709 {
1710 activeSlot = m_superframeDuration / 16;
1711 cfpDuration = activeSlot * (15 - m_fnlCapSlot);
1712 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1713
1714 if (cfpDuration > 0)
1715 {
1717 }
1718
1719 NS_LOG_DEBUG("Outgoing superframe CFP duration " << cfpDuration << " symbols ("
1720 << endCfpTime.As(Time::S) << ")");
1721
1722 m_cfpEvent = Simulator::Schedule(endCfpTime,
1724 this,
1726 }
1727 // TODO: Start transmit or receive GTS here.
1728}
1729
1730void
1732{
1733 uint64_t inactiveDuration;
1734 Time endInactiveTime;
1735 uint64_t symbolRate;
1736
1737 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1738
1739 if (superframeType == INCOMING)
1740 {
1742 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1743
1744 if (inactiveDuration > 0)
1745 {
1747 }
1748
1749 NS_LOG_DEBUG("Incoming superframe Inactive Portion duration "
1750 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1751 m_beaconEvent = Simulator::Schedule(endInactiveTime, &LrWpanMac::AwaitBeacon, this);
1752 }
1753 else
1754 {
1755 inactiveDuration = m_beaconInterval - m_superframeDuration;
1756 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1757
1758 if (inactiveDuration > 0)
1759 {
1761 }
1762
1763 NS_LOG_DEBUG("Outgoing superframe Inactive Portion duration "
1764 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1766 }
1767}
1768
1769void
1771{
1773
1774 // TODO: If the device waits more than the expected time to receive the beacon (wait = 46
1775 // symbols for default beacon size)
1776 // it should continue with the start of the incoming CAP even if it did not receive the
1777 // beacon. At the moment, the start of the incoming CAP is only triggered if the beacon is
1778 // received. See MLME-SyncLoss for details.
1779}
1780
1781void
1783{
1784 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1785
1787 {
1788 MlmeSyncLossIndicationParams syncLossParams;
1789 // syncLossParams.m_logCh =
1790 syncLossParams.m_lossReason = MacStatus::BEACON_LOSS;
1791 syncLossParams.m_panId = m_macPanId;
1792 m_mlmeSyncLossIndicationCallback(syncLossParams);
1793
1794 m_beaconTrackingOn = false;
1795 m_numLostBeacons = 0;
1796 }
1797 else
1798 {
1800
1801 // Search for one more beacon
1802 uint64_t searchSymbols;
1803 Time searchBeaconTime;
1804 searchSymbols =
1806 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
1808 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
1809 }
1810}
1811
1812void
1813LrWpanMac::ReceiveBeacon(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
1814{
1815 NS_LOG_FUNCTION(this << lqi << p);
1816 // The received beacon size in symbols
1817 // Beacon = Sync Header (SHR)[5 bytes] +
1818 // PHY header (PHR) [1 byte] +
1819 // PSDU (MAC header + beacon payload) [default 17 bytes]
1820 m_rxBeaconSymbols = m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
1821 (p->GetSize() * m_phy->GetPhySymbolsPerOctet());
1822
1823 // The start of Rx beacon time and start of the Incoming superframe Active Period
1824 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1825 m_macBeaconRxTime = Simulator::Now() - Seconds(double(m_rxBeaconSymbols) / symbolRate);
1826
1827 NS_LOG_DEBUG("Beacon Received; forwarding up (m_macBeaconRxTime: "
1828 << m_macBeaconRxTime.As(Time::S) << ")");
1829
1830 // Strip the Beacon Payload
1831 BeaconPayloadHeader receivedMacPayload;
1832 p->RemoveHeader(receivedMacPayload);
1833
1834 // Fill the PAN descriptor
1835 PanDescriptor panDescriptor;
1836
1837 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR)
1838 {
1839 panDescriptor.m_coorAddrMode = SHORT_ADDR;
1840 panDescriptor.m_coorShortAddr = receivedMacHdr.GetShortSrcAddr();
1841 }
1842 else
1843 {
1844 panDescriptor.m_coorAddrMode = EXT_ADDR;
1845 panDescriptor.m_coorExtAddr = receivedMacHdr.GetExtSrcAddr();
1846 }
1847
1848 panDescriptor.m_coorPanId = receivedMacHdr.GetSrcPanId();
1849 panDescriptor.m_gtsPermit = receivedMacPayload.GetGtsFields().GetGtsPermit();
1850 panDescriptor.m_linkQuality = lqi;
1851 panDescriptor.m_logChPage = m_phy->GetCurrentPage();
1852 panDescriptor.m_logCh = m_phy->GetCurrentChannelNum();
1853 panDescriptor.m_superframeSpec = receivedMacPayload.GetSuperframeSpecField();
1854 panDescriptor.m_timeStamp = m_macBeaconRxTime;
1855
1856 // Process beacon when device belongs to a PAN (associated device)
1857 if (!m_scanEvent.IsPending() && m_macPanId == receivedMacHdr.GetDstPanId())
1858 {
1859 // We need to make sure to cancel any possible ongoing unslotted CSMA/CA
1860 // operations when receiving a beacon (e.g. Those taking place at the
1861 // beginning of an Association).
1862 m_csmaCa->Cancel();
1863
1864 SuperframeField incomingSuperframe(receivedMacPayload.GetSuperframeSpecField());
1865
1866 m_incomingBeaconOrder = incomingSuperframe.GetBeaconOrder();
1867 m_incomingSuperframeOrder = incomingSuperframe.GetFrameOrder();
1868 m_incomingFnlCapSlot = incomingSuperframe.GetFinalCapSlot();
1869
1870 if (m_incomingBeaconOrder < 15)
1871 {
1872 // Start Beacon-enabled mode
1873 m_csmaCa->SetSlottedCsmaCa();
1877 (static_cast<uint32_t>(1 << m_incomingSuperframeOrder));
1878
1879 if (incomingSuperframe.IsBattLifeExt())
1880 {
1881 m_csmaCa->SetBatteryLifeExtension(true);
1882 }
1883 else
1884 {
1885 m_csmaCa->SetBatteryLifeExtension(false);
1886 }
1887
1888 // TODO: get Incoming frame GTS Fields here
1889
1890 // Begin CAP on the current device using info from
1891 // the Incoming superframe
1892 NS_LOG_DEBUG("Incoming superframe Active Portion "
1893 << "(Beacon + CAP + CFP): " << m_incomingSuperframeDuration << " symbols");
1894
1897 }
1898 else
1899 {
1900 // Start non-beacon enabled mode
1901 m_csmaCa->SetUnSlottedCsmaCa();
1902 }
1903
1905 }
1906 else if (!m_scanEvent.IsPending() && m_macPanId == 0xFFFF)
1907 {
1908 NS_LOG_DEBUG(this << " Device not associated, cannot process beacon");
1909 }
1910
1911 if (m_macAutoRequest)
1912 {
1913 if (p->GetSize() > 0)
1914 {
1916 {
1917 // The beacon contains payload, send the beacon notification.
1919 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
1920 beaconParams.m_panDescriptor = panDescriptor;
1921 beaconParams.m_sduLength = p->GetSize();
1922 beaconParams.m_sdu = p;
1924 }
1925 }
1926
1927 if (m_scanEvent.IsPending())
1928 {
1929 // Channel scanning is taking place, save only unique PAN descriptors
1930 bool descriptorExists = false;
1931
1932 for (const auto& descriptor : m_panDescriptorList)
1933 {
1934 if (descriptor.m_coorAddrMode == SHORT_ADDR)
1935 {
1936 // Found a coordinator in PAN descriptor list with the same
1937 // registered short address
1938 descriptorExists =
1939 (descriptor.m_coorShortAddr == panDescriptor.m_coorShortAddr &&
1940 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
1941 }
1942 else
1943 {
1944 // Found a coordinator in PAN descriptor list with the same
1945 // registered extended address
1946 descriptorExists = (descriptor.m_coorExtAddr == panDescriptor.m_coorExtAddr &&
1947 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
1948 }
1949
1950 if (descriptorExists)
1951 {
1952 break;
1953 }
1954 }
1955
1956 if (!descriptorExists)
1957 {
1958 m_panDescriptorList.emplace_back(panDescriptor);
1959 }
1960 return;
1961 }
1962 else if (m_trackingEvent.IsPending())
1963 {
1964 // check if MLME-SYNC.request was previously issued and running
1965 // Sync. is necessary to handle pending messages (indirect
1966 // transmissions)
1967 m_trackingEvent.Cancel();
1968 m_numLostBeacons = 0;
1969
1971 {
1972 // if tracking option is on keep tracking the next beacon
1973 uint64_t searchSymbols;
1974 Time searchBeaconTime;
1975
1976 searchSymbols = (static_cast<uint64_t>(1 << m_incomingBeaconOrder)) +
1978 searchBeaconTime = Seconds(static_cast<double>(searchSymbols / symbolRate));
1980 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
1981 }
1982
1983 PendingAddrFields pndAddrFields;
1984 pndAddrFields = receivedMacPayload.GetPndAddrFields();
1985
1986 // TODO: Ignore pending data, and do not send data command request if
1987 // the address is in the GTS list.
1988 // If the address is not in the GTS list, then check if the
1989 // address is in the short address pending list or in the extended
1990 // address pending list and send a data command request.
1991 }
1992 }
1993 else
1994 {
1995 // m_macAutoRequest is FALSE
1996 // Data command request are not send, only the beacon notification.
1997 // see IEEE 802.15.4-2011 Section 6.2.4.1
1999 {
2001 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2002 beaconParams.m_panDescriptor = panDescriptor;
2003 beaconParams.m_sduLength = p->GetSize();
2004 beaconParams.m_sdu = p;
2006 }
2007 }
2008}
2009
2010void
2011LrWpanMac::ReceiveCommand(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
2012{
2013 NS_LOG_FUNCTION(this << lqi << p);
2014
2015 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
2016
2017 CommandPayloadHeader receivedMacPayload;
2018 p->RemoveHeader(receivedMacPayload);
2019
2020 switch (receivedMacPayload.GetCommandFrameType())
2021 {
2023 if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
2024 {
2025 // Jitter = Between 0 and 2 aUnitBackoffPeriods
2026 // (0, 320us or 640us in 2.4Ghz O-QPSK)
2027 // While this jitter is not described by the standard,
2028 // it reduces the probability of collisions in beacons
2029 // transmitted as a result of a beacon request
2030 Time jitter =
2031 Seconds(static_cast<double>(m_uniformVar->GetInteger(0, 3) * aUnitBackoffPeriod) /
2032 symbolRate);
2033
2035 }
2036 else
2037 {
2038 NS_LOG_DEBUG("Beacon Request command received in beacon mode: Ignore");
2039 }
2040 break;
2042 if (m_coor)
2043 {
2044 if (!m_mlmeOrphanIndicationCallback.IsNull())
2045 {
2046 MlmeOrphanIndicationParams orphanParams;
2047 orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
2048 m_mlmeOrphanIndicationCallback(orphanParams);
2049 }
2050 }
2051 break;
2053 if (m_scanOrphanEvent.IsPending())
2054 {
2055 // Coordinator located, no need to keep scanning other channels
2056 m_scanOrphanEvent.Cancel();
2057
2058 m_macPanIdScan = 0;
2061
2062 // Update the device information with the received information
2063 // from the Coordinator Realigment command.
2064 m_macPanId = receivedMacPayload.GetPanId();
2065 m_shortAddress = receivedMacPayload.GetShortAddr();
2066 m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
2067 m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
2068
2069 if (!m_mlmeScanConfirmCallback.IsNull())
2070 {
2071 MlmeScanConfirmParams confirmParams;
2072 confirmParams.m_scanType = m_scanParams.m_scanType;
2073 confirmParams.m_chPage = m_scanParams.m_chPage;
2074 confirmParams.m_status = MacStatus::SUCCESS;
2075 m_mlmeScanConfirmCallback(confirmParams);
2076 }
2077 m_scanParams = {};
2078 }
2079 // TODO: handle Coordinator realignment when not
2080 // used during an orphan scan.
2081 break;
2082 default:
2083 break;
2084 }
2085}
2086
2087void
2089 int8_t rssi,
2090 const LrWpanMacHeader& receivedMacHdr,
2091 Ptr<Packet> p)
2092{
2093 NS_LOG_FUNCTION(this << lqi << p);
2094
2095 NS_LOG_DEBUG("Data Packet is for me; forwarding up");
2096
2097 if (!m_mcpsDataIndicationCallback.IsNull())
2098 {
2100 params.m_dsn = receivedMacHdr.GetSeqNum();
2101 params.m_mpduLinkQuality = lqi;
2102 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
2103 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
2104 params.m_rssi = rssi;
2105
2106 switch (params.m_srcAddrMode)
2107 {
2108 case SHORT_ADDR:
2109 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
2110 break;
2111 case EXT_ADDR:
2112 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
2113 break;
2114 default:
2115 break;
2116 }
2117
2118 params.m_dstPanId = receivedMacHdr.GetDstPanId();
2119 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
2120
2121 switch (params.m_dstAddrMode)
2122 {
2123 case SHORT_ADDR:
2124 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
2125 break;
2126 case EXT_ADDR:
2127 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
2128 break;
2129 default:
2130 break;
2131 }
2132
2134 }
2135}
2136
2137void
2139{
2140 NS_LOG_FUNCTION(this << p);
2141
2142 // Make a copy of the original transmitted packet that required ACK and
2143 // extract its MAC header.
2144 Ptr<Packet> txPkt = m_txPkt->Copy();
2145 LrWpanMacHeader txMacHdr;
2146 txPkt->RemoveHeader(txMacHdr);
2147
2148 // If it is an ACK with an unexpected sequence number, mark the current
2149 // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
2150 if (receivedMacHdr.GetSeqNum() != txMacHdr.GetSeqNum())
2151 {
2152 m_ackWaitTimeout.Cancel();
2153 if (!PrepareRetransmission())
2154 {
2155 m_setMacState.Cancel();
2157 }
2158 else
2159 {
2160 m_setMacState.Cancel();
2162 }
2163
2164 return;
2165 }
2166
2167 // If it is an ACK with the expected sequence number, finish the transmission
2168 m_ackWaitTimeout.Cancel();
2170
2171 // TODO: check if the IFS is the correct size after ACK.
2172 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2173 Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
2174
2175 if (txMacHdr.IsCommand())
2176 {
2177 // We received an ACK to a command, we need to take actions depending on the
2178 // transmitted command.
2179
2180 // Extract the command payload of the originally transmitted packet to know
2181 // what command we transmitted.
2182 CommandPayloadHeader txCmdPayload;
2183 txPkt->RemoveHeader(txCmdPayload);
2184
2185 switch (txCmdPayload.GetCommandFrameType())
2186 {
2188 Time waitTime = Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
2189 if (!m_beaconTrackingOn)
2190 {
2193 }
2194 else
2195 {
2196 // TODO: The data must be extracted by the coordinator within
2197 // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
2198 // with status NO_DATA, and this should trigger the cancellation
2199 // of the beacon tracking (MLME-SYNC.request trackBeacon
2200 // =FALSE)
2201 }
2202 break;
2203 }
2204
2206 // MLME-comm-status.Indication generated as a result of an
2207 // association response command, therefore src and dst address use
2208 // extended mode (see 5.3.2.1)
2210 {
2211 MlmeCommStatusIndicationParams commStatusParams;
2212 commStatusParams.m_panId = m_macPanId;
2213 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2214 commStatusParams.m_srcExtAddr = txMacHdr.GetExtSrcAddr();
2215 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2216 commStatusParams.m_dstExtAddr = txMacHdr.GetExtDstAddr();
2217 commStatusParams.m_status = MacStatus::SUCCESS;
2218 m_mlmeCommStatusIndicationCallback(commStatusParams);
2219 }
2220 // Remove element from Pending Transaction List
2222 break;
2223 }
2224
2226 if (!m_ignoreDataCmdAck)
2227 {
2228 // Schedule an event in case the Association Response Command
2229 // never reached this device during an association process.
2230 Time waitTime = Seconds(static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
2233 }
2234
2235 if (!m_mlmePollConfirmCallback.IsNull())
2236 {
2237 MlmePollConfirmParams pollConfirmParams;
2238 pollConfirmParams.m_status = MacStatus::SUCCESS;
2239 m_mlmePollConfirmCallback(pollConfirmParams);
2240 }
2241 break;
2242 }
2243
2245 // ACK of coordinator realigment commands is not specified in the
2246 // standard, in here, we assume they are required as in other
2247 // commands.
2249 {
2250 MlmeCommStatusIndicationParams commStatusParams;
2251 commStatusParams.m_panId = m_macPanId;
2252 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2253 commStatusParams.m_srcExtAddr = txMacHdr.GetExtSrcAddr();
2254 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2255 commStatusParams.m_dstExtAddr = txMacHdr.GetExtDstAddr();
2256 commStatusParams.m_status = MacStatus::SUCCESS;
2257 m_mlmeCommStatusIndicationCallback(commStatusParams);
2258 }
2259 break;
2260 }
2261
2262 default: {
2263 // TODO: add response to other request commands (e.g. Orphan)
2264 break;
2265 }
2266 }
2267 }
2268 else
2269 {
2270 // Receive ACK to data packet
2271 if (!m_mcpsDataConfirmCallback.IsNull())
2272 {
2273 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
2274 McpsDataConfirmParams confirmParams;
2275 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2276 confirmParams.m_status = MacStatus::SUCCESS;
2277 m_mcpsDataConfirmCallback(confirmParams);
2278 }
2279 }
2280
2281 // Ack was successfully received, wait for the Interframe Space (IFS) and
2282 // then proceed
2284 m_setMacState.Cancel();
2286 m_ifsEvent = Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
2287}
2288
2289void
2291{
2292 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
2293 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2294 {
2295 NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetShortSrcAddr() << "] to ["
2296 << receivedMacHdr.GetShortDstAddr() << "]");
2297 }
2298 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
2299 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2300 {
2301 NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetExtSrcAddr() << "] to ["
2302 << receivedMacHdr.GetExtDstAddr() << "]");
2303 }
2304 else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
2305 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2306 {
2307 NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetShortSrcAddr() << "] to ["
2308 << receivedMacHdr.GetExtDstAddr() << "]");
2309 }
2310 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
2311 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2312 {
2313 NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetExtSrcAddr() << "] to ["
2314 << receivedMacHdr.GetShortDstAddr() << "]");
2315 }
2316}
2317
2318void
2320{
2321 NS_LOG_FUNCTION(this);
2322 // Pull a packet from the queue and start sending if we are not already sending.
2323 if (m_macState == MAC_IDLE && !m_txQueue.empty() && !m_setMacState.IsPending())
2324 {
2325 if (m_csmaCa->IsUnSlottedCsmaCa() || (m_outSuperframeStatus == CAP && m_coor) ||
2327 {
2328 // check MAC is not in a IFS
2329 if (!m_ifsEvent.IsPending())
2330 {
2331 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
2332 m_txPkt = txQElement->txQPkt;
2333
2336 }
2337 }
2338 }
2339}
2340
2341uint16_t
2343{
2344 SuperframeField sfrmSpec;
2345
2348 sfrmSpec.SetFinalCapSlot(m_fnlCapSlot);
2349
2350 if (m_csmaCa->GetBatteryLifeExtension())
2351 {
2352 sfrmSpec.SetBattLifeExt(true);
2353 }
2354
2355 if (m_panCoor)
2356 {
2357 sfrmSpec.SetPanCoor(true);
2358 }
2359
2360 // used to associate devices via Beacons
2362 {
2363 sfrmSpec.SetAssocPermit(true);
2364 }
2365
2366 return sfrmSpec.GetSuperframe();
2367}
2368
2371{
2372 GtsFields gtsFields;
2373
2374 // TODO: Logic to populate the GTS Fields from local information here
2375
2376 return gtsFields;
2377}
2378
2381{
2382 PendingAddrFields pndAddrFields;
2383
2384 // TODO: Logic to populate the Pending Address Fields from local information here
2385 return pndAddrFields;
2386}
2387
2388void
2390{
2391 m_csmaCa = csmaCa;
2392}
2393
2394void
2396{
2397 m_phy = phy;
2398}
2399
2402{
2403 return m_phy;
2404}
2405
2406void
2408{
2410 NS_LOG_FUNCTION(this << psduLength << p << (uint16_t)lqi);
2411
2412 Ptr<Packet> originalPkt = p->Copy();
2413
2414 // If active, pass the complete packet to the traces
2415 if (!m_promiscSnifferTrace.IsEmpty())
2416 {
2417 m_promiscSnifferTrace(p->Copy());
2418 }
2419 else if (!m_macPromiscRxTrace.IsEmpty())
2420 {
2421 m_macPromiscRxTrace(p->Copy());
2422 }
2423
2424 // Extract the MAC trailer
2425 LrWpanMacTrailer receivedMacTrailer;
2426 p->RemoveTrailer(receivedMacTrailer);
2427
2428 // Extract the MAC Header from the packet
2429 LrWpanMacHeader receivedMacHdr;
2430 p->RemoveHeader(receivedMacHdr);
2431
2433 {
2434 receivedMacTrailer.EnableFcs(true);
2435 }
2436
2437 // From section 7.5.6.2 Reception and rejection, IEEE 802.15.4-2006
2438 // - Level 1 filtering: Test FCS field and reject if frame fails.
2439 // - Level 2 filtering: If promiscuous mode pass frame to higher layer
2440 // otherwise perform Level 3 filtering.
2441 // - Level 3 filtering: Accept frame if Frame type and version is not reserved, and if
2442 // there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
2443 // shortDstAddr then shortDstAddr=shortMacAddr or broadcastAddr, and if beacon frame then
2444 // srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
2445 // srcPanId=m_macPanId.
2446
2447 // Level 1 filtering
2448 if (!receivedMacTrailer.CheckFcs(p))
2449 {
2450 m_macRxDropTrace(originalPkt);
2451 return;
2452 }
2453
2454 // Level 2 filtering
2456 {
2457 PrintReceivedPacket(receivedMacHdr);
2458 ReceiveInPromiscuousMode(lqi, rssi, receivedMacHdr, p);
2459 return;
2460 }
2461
2462 // Level 3 frame filtering
2463 bool acceptFrame;
2464 acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
2465
2466 if (acceptFrame)
2467 {
2468 acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
2469 }
2470
2471 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
2472 {
2473 // Accept frame if one of the following is true:
2474
2475 // 1) Have the same macPanId
2476 // 2) Is Message to all PANs
2477 // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
2478 acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
2479 receivedMacHdr.GetDstPanId() == 0xffff) ||
2480 (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
2481 (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
2482 }
2483
2484 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
2485 {
2486 if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
2487 {
2488 // unicast, for me
2489 acceptFrame = true;
2490 }
2491 else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2492 receivedMacHdr.GetShortDstAddr().IsMulticast())
2493 {
2494 // Broadcast or multicast.
2495 // Discard broadcast/multicast with the ACK bit set.
2496 acceptFrame = !receivedMacHdr.IsAckReq();
2497 }
2498 else
2499 {
2500 acceptFrame = false;
2501 }
2502 }
2503
2504 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
2505 {
2506 acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_macExtendedAddress);
2507 }
2508
2509 if (acceptFrame && m_scanEvent.IsPending())
2510 {
2511 if (!receivedMacHdr.IsBeacon())
2512 {
2513 acceptFrame = false;
2514 }
2515 }
2516 else if (acceptFrame && m_scanOrphanEvent.IsPending())
2517 {
2518 if (!receivedMacHdr.IsCommand())
2519 {
2520 acceptFrame = false;
2521 }
2522 }
2523 else if (m_scanEnergyEvent.IsPending())
2524 {
2525 // Reject any frames if energy scan is running
2526 acceptFrame = false;
2527 }
2528
2529 // Check device is panCoor with association permit when receiving Association Request
2530 // Commands.
2531 if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
2532 {
2533 CommandPayloadHeader receivedMacPayload;
2534 p->PeekHeader(receivedMacPayload);
2535
2536 if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::ASSOCIATION_REQ &&
2538 {
2539 acceptFrame = false;
2540 }
2541
2542 // Although ACKs do not use CSMA to to be transmitted, we need to make sure
2543 // that the transmitted ACK will not collide with the transmission of a beacon
2544 // when beacon-enabled mode is running in the coordinator.
2545 if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsPending()))
2546 {
2547 Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
2548 uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
2549 ceil(6 * m_phy->GetPhySymbolsPerOctet());
2550 auto symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
2551 Time ackTime = Seconds((double)ackSymbols / symbolRate);
2552
2553 if (ackTime >= timeLeftInCap)
2554 {
2555 NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
2556 "before the end of CAP ");
2557 acceptFrame = false;
2558 }
2559 }
2560 }
2561
2562 if (!acceptFrame)
2563 {
2564 m_macRxDropTrace(originalPkt);
2565 return;
2566 }
2567
2568 m_macRxTrace(originalPkt);
2569 // \todo: What should we do if we receive a frame while waiting for an ACK?
2570 // Especially if this frame has the ACK request bit set, should we reply with
2571 // an ACK, possibly missing the pending ACK?
2572
2573 // If the received frame is a frame with the ACK request bit set, we immediately
2574 // send back an ACK. If we are currently waiting for a pending ACK, we assume the
2575 // ACK was lost and trigger a retransmission after sending the ACK.
2576 if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) && receivedMacHdr.IsAckReq() &&
2577 !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
2578 (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2579 receivedMacHdr.GetShortDstAddr().IsMulticast())))
2580 {
2581 // If this is a data or mac command frame, which is not a broadcast or
2582 // multicast, with ack req set, generate and send an ack frame. If there is a
2583 // CSMA medium access in progress we cancel the medium access for sending the
2584 // ACK frame. A new transmission attempt will be started after the ACK was send.
2586 {
2587 m_ackWaitTimeout.Cancel();
2589 }
2590 else if (m_macState == MAC_CSMA)
2591 {
2592 // \todo: If we receive a packet while doing CSMA/CA, should we drop the
2593 // packet because of channel busy,
2594 // or should we restart CSMA/CA for the packet after sending the ACK?
2595 // Currently we simply restart CSMA/CA after sending the ACK.
2596 NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
2597 "current CSMA-CA");
2598 m_csmaCa->Cancel();
2599 }
2600 // Cancel any pending MAC state change, ACKs have higher priority.
2601 m_setMacState.Cancel();
2603
2604 // save received packet and LQI to process the appropriate indication/response
2605 // after sending ACK (PD-DATA.confirm)
2606 m_rxPkt = originalPkt;
2607 m_lastRxFrameLqi = lqi;
2608
2609 // LOG Commands with ACK required.
2610 CommandPayloadHeader receivedMacPayload;
2611 p->PeekHeader(receivedMacPayload);
2612 switch (receivedMacPayload.GetCommandFrameType())
2613 {
2615 NS_LOG_DEBUG("Data Request Command Received; processing ACK");
2616 break;
2618 NS_LOG_DEBUG("Association Request Command Received; processing ACK");
2619 break;
2621 if (m_assocResCmdWaitTimeout.IsPending())
2622 {
2623 m_assocResCmdWaitTimeout.Cancel(); // cancel event to a lost assoc resp cmd.
2624 NS_LOG_DEBUG("Association Response Command Received; processing ACK");
2625 }
2626 else
2627 {
2628 // Association response command was received before (or never received)
2629 // a Data request command ACK. This is an extreme case and it is
2630 // essentially caused by saturation in the network.
2631 // We turn a flag ON to not react once
2632 // we finally receive the Data request command ACK. This behavior is not
2633 // standard, but necessary to address this flaw in design of the
2634 // original association process.
2635 m_ignoreDataCmdAck = true;
2636 NS_LOG_DEBUG("Assoc. Resp Cmd received before Data Req. Cmd. in "
2637 "Association request");
2638 }
2639 break;
2640 }
2641 default:
2642 break;
2643 }
2644
2646 Simulator::ScheduleNow(&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum());
2647 }
2648
2649 PrintReceivedPacket(receivedMacHdr);
2650
2651 if (receivedMacHdr.IsBeacon())
2652 {
2653 ReceiveBeacon(lqi, receivedMacHdr, p);
2654 }
2655 else if (receivedMacHdr.IsCommand())
2656 {
2657 ReceiveCommand(lqi, receivedMacHdr, p);
2658 }
2659 else if (receivedMacHdr.IsData())
2660 {
2661 ReceiveData(lqi, rssi, receivedMacHdr, p);
2662 }
2663 else if (receivedMacHdr.IsAcknowledgment() && m_txPkt && m_macState == MAC_ACK_PENDING)
2664 {
2665 ReceiveAcknowledgment(receivedMacHdr, p);
2666 }
2667}
2668
2669void
2671{
2672 NS_LOG_FUNCTION(this << static_cast<uint32_t>(seqno));
2673
2675
2676 // Generate a corresponding ACK Frame.
2678 LrWpanMacTrailer macTrailer;
2679 Ptr<Packet> ackPacket = Create<Packet>(0);
2680 ackPacket->AddHeader(macHdr);
2681 // Calculate FCS if the global attribute ChecksumEnabled is set.
2683 {
2684 macTrailer.EnableFcs(true);
2685 macTrailer.SetFcs(ackPacket);
2686 }
2687 ackPacket->AddTrailer(macTrailer);
2688
2689 // Enqueue the ACK packet for further processing
2690 // when the transmitter is activated.
2691 m_txPkt = ackPacket;
2692
2693 // Switch transceiver to TX mode. Proceed sending the Ack on confirm.
2695 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
2696}
2697
2698void
2699LrWpanMac::EnqueueTxQElement(std::shared_ptr<TxQueueElement> txQElement)
2700{
2701 if (m_txQueue.size() < m_maxTxQueueSize)
2702 {
2703 m_txQueue.emplace_back(txQElement);
2704 m_macTxEnqueueTrace(txQElement->txQPkt);
2705 }
2706 else
2707 {
2708 if (!m_mcpsDataConfirmCallback.IsNull())
2709 {
2710 McpsDataConfirmParams confirmParams;
2711 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2713 m_mcpsDataConfirmCallback(confirmParams);
2714 }
2715 NS_LOG_DEBUG("TX Queue with size " << m_txQueue.size() << " is full, dropping packet");
2716 m_macTxDropTrace(txQElement->txQPkt);
2717 }
2718}
2719
2720void
2722{
2723 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
2724 Ptr<const Packet> p = txQElement->txQPkt;
2725 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2726
2727 Ptr<Packet> pkt = p->Copy();
2728 LrWpanMacHeader hdr;
2729 pkt->RemoveHeader(hdr);
2730 if (!hdr.GetShortDstAddr().IsBroadcast() && !hdr.GetShortDstAddr().IsMulticast())
2731 {
2733 }
2734
2735 txQElement->txQPkt = nullptr;
2736 txQElement = nullptr;
2737 m_txQueue.pop_front();
2738 m_txPkt = nullptr;
2739 m_retransmission = 0;
2740 m_numCsmacaRetry = 0;
2742}
2743
2744void
2746{
2747 NS_LOG_FUNCTION(this);
2748
2749 // TODO: If we are a PAN coordinator and this was an indirect transmission,
2750 // we will not initiate a retransmission. Instead we wait for the data
2751 // being extracted after a new data request command.
2752 if (!PrepareRetransmission())
2753 {
2755 }
2756 else
2757 {
2759 }
2760}
2761
2762void
2764{
2765 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false);
2766 Time lifsTime = Seconds((double)m_macLIFSPeriod / symbolRate);
2767 Time sifsTime = Seconds((double)m_macSIFSPeriod / symbolRate);
2768
2769 if (ifsTime == lifsTime)
2770 {
2771 NS_LOG_DEBUG("LIFS of " << m_macLIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2772 << ") completed ");
2773 }
2774 else if (ifsTime == sifsTime)
2775 {
2776 NS_LOG_DEBUG("SIFS of " << m_macSIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2777 << ") completed ");
2778 }
2779 else
2780 {
2781 NS_LOG_DEBUG("Unknown IFS size (" << ifsTime.As(Time::S) << ") completed ");
2782 }
2783
2784 m_macIfsEndTrace(ifsTime);
2785 CheckQueue();
2786}
2787
2788bool
2790{
2791 NS_LOG_FUNCTION(this);
2792
2793 // Max retransmissions reached without receiving ACK,
2794 // send the proper indication/confirmation
2795 // according to the frame type and call drop trace.
2797 {
2798 LrWpanMacHeader peekedMacHdr;
2799 m_txPkt->PeekHeader(peekedMacHdr);
2800
2801 if (peekedMacHdr.IsCommand())
2802 {
2804
2805 Ptr<Packet> pkt = m_txPkt->Copy();
2806 LrWpanMacHeader macHdr;
2807 CommandPayloadHeader cmdPayload;
2808 pkt->RemoveHeader(macHdr);
2809 pkt->RemoveHeader(cmdPayload);
2810
2811 switch (cmdPayload.GetCommandFrameType())
2812 {
2814 m_macPanId = 0xffff;
2816 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2817 m_incCapEvent.Cancel();
2818 m_incCfpEvent.Cancel();
2819 m_csmaCa->SetUnSlottedCsmaCa();
2822
2823 if (!m_mlmeAssociateConfirmCallback.IsNull())
2824 {
2825 MlmeAssociateConfirmParams confirmParams;
2826 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
2827 confirmParams.m_status = MacStatus::NO_ACK;
2828 m_mlmeAssociateConfirmCallback(confirmParams);
2829 }
2830 break;
2831 }
2833 // IEEE 802.15.4-2006 (Section 7.1.3.3.3 and 7.1.8.2.3)
2835 {
2836 MlmeCommStatusIndicationParams commStatusParams;
2837 commStatusParams.m_panId = m_macPanId;
2838 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2839 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2840 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2841 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2842 commStatusParams.m_status = MacStatus::NO_ACK;
2843 m_mlmeCommStatusIndicationCallback(commStatusParams);
2844 }
2846 break;
2847 }
2849 // IEEE 802.15.4-2006 (Section 7.1.16.1.3)
2850 m_macPanId = 0xffff;
2852 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2853 m_incCapEvent.Cancel();
2854 m_incCfpEvent.Cancel();
2855 m_csmaCa->SetUnSlottedCsmaCa();
2858
2859 if (!m_mlmePollConfirmCallback.IsNull())
2860 {
2861 MlmePollConfirmParams pollConfirmParams;
2862 pollConfirmParams.m_status = MacStatus::NO_ACK;
2863 m_mlmePollConfirmCallback(pollConfirmParams);
2864 }
2865 break;
2866 }
2867 default: {
2868 // TODO: Specify other indications according to other commands
2869 break;
2870 }
2871 }
2872 }
2873 else
2874 {
2875 // Maximum number of retransmissions has been reached.
2876 // remove the copy of the DATA packet that was just sent
2877 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
2878 m_macTxDropTrace(txQElement->txQPkt);
2879 if (!m_mcpsDataConfirmCallback.IsNull())
2880 {
2881 McpsDataConfirmParams confirmParams;
2882 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2883 confirmParams.m_status = MacStatus::NO_ACK;
2884 m_mcpsDataConfirmCallback(confirmParams);
2885 }
2886 }
2887
2889 return false;
2890 }
2891 else
2892 {
2894 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2895 // Start next CCA process for this packet.
2896 return true;
2897 }
2898}
2899
2900void
2902{
2903 auto indTxQElement = std::make_shared<IndTxQueueElement>();
2904 LrWpanMacHeader peekedMacHdr;
2905 p->PeekHeader(peekedMacHdr);
2906
2907 PurgeInd();
2908
2909 NS_ASSERT(peekedMacHdr.GetDstAddrMode() == SHORT_ADDR ||
2910 peekedMacHdr.GetDstAddrMode() == EXT_ADDR);
2911
2912 if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2913 {
2914 indTxQElement->dstShortAddress = peekedMacHdr.GetShortDstAddr();
2915 }
2916 else
2917 {
2918 indTxQElement->dstExtAddress = peekedMacHdr.GetExtDstAddr();
2919 }
2920
2921 indTxQElement->seqNum = peekedMacHdr.GetSeqNum();
2922
2923 // See IEEE 802.15.4-2006, Table 86
2924 uint32_t unit = 0; // The persistence time in symbols
2925 if (m_macBeaconOrder == 15)
2926 {
2927 // Non-beacon enabled mode
2929 }
2930 else
2931 {
2932 // Beacon-enabled mode
2933 unit = ((static_cast<uint32_t>(1) << m_macBeaconOrder) * lrwpan::aBaseSuperframeDuration) *
2935 }
2936
2937 if (m_indTxQueue.size() < m_maxIndTxQueueSize)
2938 {
2939 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2940 Time expireTime = Seconds(unit / symbolRate);
2941 expireTime += Simulator::Now();
2942 indTxQElement->expireTime = expireTime;
2943 indTxQElement->txQPkt = p;
2944 m_indTxQueue.emplace_back(indTxQElement);
2946 }
2947 else
2948 {
2950 {
2951 LrWpanMacHeader peekedMacHdr;
2952 indTxQElement->txQPkt->PeekHeader(peekedMacHdr);
2953 MlmeCommStatusIndicationParams commStatusParams;
2954 commStatusParams.m_panId = m_macPanId;
2955 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2956 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2957 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2958 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2959 commStatusParams.m_status = MacStatus::TRANSACTION_OVERFLOW;
2960 m_mlmeCommStatusIndicationCallback(commStatusParams);
2961 }
2963 }
2964}
2965
2966bool
2967LrWpanMac::DequeueInd(Mac64Address dst, std::shared_ptr<IndTxQueueElement> entry)
2968{
2969 PurgeInd();
2970
2971 for (auto iter = m_indTxQueue.begin(); iter != m_indTxQueue.end(); iter++)
2972 {
2973 if ((*iter)->dstExtAddress == dst)
2974 {
2975 *entry = **iter;
2976 m_macIndTxDequeueTrace((*iter)->txQPkt->Copy());
2977 m_indTxQueue.erase(iter);
2978 return true;
2979 }
2980 }
2981 return false;
2982}
2983
2984void
2986{
2987 for (uint32_t i = 0; i < m_indTxQueue.size();)
2988 {
2989 if (Simulator::Now() > m_indTxQueue[i]->expireTime)
2990 {
2991 // Transaction expired, remove and send proper confirmation/indication to a higher layer
2992 LrWpanMacHeader peekedMacHdr;
2993 m_indTxQueue[i]->txQPkt->PeekHeader(peekedMacHdr);
2994
2995 if (peekedMacHdr.IsCommand())
2996 {
2997 // IEEE 802.15.4-2006 (Section 7.1.3.3.3)
2999 {
3000 MlmeCommStatusIndicationParams commStatusParams;
3001 commStatusParams.m_panId = m_macPanId;
3002 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3003 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
3004 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3005 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
3006 commStatusParams.m_status = MacStatus::TRANSACTION_EXPIRED;
3007 m_mlmeCommStatusIndicationCallback(commStatusParams);
3008 }
3009 }
3010 else if (peekedMacHdr.IsData())
3011 {
3012 // IEEE 802.15.4-2006 (Section 7.1.1.1.3)
3013 if (!m_mcpsDataConfirmCallback.IsNull())
3014 {
3015 McpsDataConfirmParams confParams;
3017 m_mcpsDataConfirmCallback(confParams);
3018 }
3019 }
3020 m_macIndTxDropTrace(m_indTxQueue[i]->txQPkt->Copy());
3021 m_indTxQueue.erase(m_indTxQueue.begin() + i);
3022 }
3023 else
3024 {
3025 i++;
3026 }
3027 }
3028}
3029
3030void
3031LrWpanMac::PrintPendingTxQueue(std::ostream& os) const
3032{
3033 LrWpanMacHeader peekedMacHdr;
3034
3035 os << "Pending Transaction List [" << GetShortAddress() << " | " << GetExtendedAddress()
3036 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
3037 << " Destination |"
3038 << " Sequence Number |"
3039 << " Frame type |"
3040 << " Expire time\n";
3041
3042 for (const auto& transaction : m_indTxQueue)
3043 {
3044 transaction->txQPkt->PeekHeader(peekedMacHdr);
3045 os << transaction->dstExtAddress << " "
3046 << static_cast<uint32_t>(transaction->seqNum) << " ";
3047
3048 if (peekedMacHdr.IsCommand())
3049 {
3050 os << " Command Frame ";
3051 }
3052 else if (peekedMacHdr.IsData())
3053 {
3054 os << " Data Frame ";
3055 }
3056 else
3057 {
3058 os << " Unknown Frame ";
3059 }
3060
3061 os << transaction->expireTime.As(Time::S) << "\n";
3062 }
3063}
3064
3065void
3066LrWpanMac::PrintTxQueue(std::ostream& os) const
3067{
3068 LrWpanMacHeader peekedMacHdr;
3069
3070 os << "\nTx Queue [" << GetShortAddress() << " | " << GetExtendedAddress()
3071 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
3072 << " Destination |"
3073 << " Sequence Number |"
3074 << " Dst PAN id |"
3075 << " Frame type |\n";
3076
3077 for (const auto& transaction : m_txQueue)
3078 {
3079 transaction->txQPkt->PeekHeader(peekedMacHdr);
3080
3081 os << "[" << peekedMacHdr.GetShortDstAddr() << "]"
3082 << ", [" << peekedMacHdr.GetExtDstAddr() << "] "
3083 << static_cast<uint32_t>(peekedMacHdr.GetSeqNum()) << " "
3084 << peekedMacHdr.GetDstPanId() << " ";
3085
3086 if (peekedMacHdr.IsCommand())
3087 {
3088 os << " Command Frame ";
3089 }
3090 else if (peekedMacHdr.IsData())
3091 {
3092 os << " Data Frame ";
3093 }
3094 else
3095 {
3096 os << " Unknown Frame ";
3097 }
3098
3099 os << "\n";
3100 }
3101 os << "\n";
3102}
3103
3104int64_t
3106{
3107 NS_LOG_FUNCTION(this);
3108 m_uniformVar->SetStream(stream);
3109 m_csmaCa->AssignStreams(stream + 1);
3110 return 2;
3111}
3112
3113void
3115{
3116 LrWpanMacHeader peekedMacHdr;
3117 p->PeekHeader(peekedMacHdr);
3118
3119 for (auto it = m_indTxQueue.begin(); it != m_indTxQueue.end(); it++)
3120 {
3121 if (peekedMacHdr.GetDstAddrMode() == EXT_ADDR)
3122 {
3123 if (((*it)->dstExtAddress == peekedMacHdr.GetExtDstAddr()) &&
3124 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
3125 {
3127 m_indTxQueue.erase(it);
3128 break;
3129 }
3130 }
3131 else if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
3132 {
3133 if (((*it)->dstShortAddress == peekedMacHdr.GetShortDstAddr()) &&
3134 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
3135 {
3137 m_indTxQueue.erase(it);
3138 break;
3139 }
3140 }
3141 }
3142
3143 p = nullptr;
3144}
3145
3146void
3148{
3150 NS_LOG_FUNCTION(this << status << m_txQueue.size());
3151
3152 LrWpanMacHeader macHdr;
3153 Time ifsWaitTime;
3154 double symbolRate;
3155
3156 symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
3157
3158 m_txPkt->PeekHeader(macHdr);
3159
3160 if (status == IEEE_802_15_4_PHY_SUCCESS)
3161 {
3162 if (!macHdr.IsAcknowledgment())
3163 {
3164 if (macHdr.IsBeacon())
3165 {
3166 // Start CAP only if we are in beacon mode (i.e. if slotted csma-ca is running)
3167 if (m_csmaCa->IsSlottedCsmaCa())
3168 {
3169 // The Tx Beacon in symbols
3170 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
3171 // 17 bytes)
3172 uint64_t beaconSymbols = m_phy->GetPhySHRDuration() +
3173 1 * m_phy->GetPhySymbolsPerOctet() +
3174 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
3175
3176 // The beacon Tx time and start of the Outgoing superframe Active Period
3178 Simulator::Now() - Seconds(static_cast<double>(beaconSymbols) / symbolRate);
3179
3181 this,
3183 NS_LOG_DEBUG("Beacon Sent (m_macBeaconTxTime: " << m_macBeaconTxTime.As(Time::S)
3184 << ")");
3185
3186 if (!m_mlmeStartConfirmCallback.IsNull())
3187 {
3188 MlmeStartConfirmParams mlmeConfirmParams;
3189 mlmeConfirmParams.m_status = MacStatus::SUCCESS;
3190 m_mlmeStartConfirmCallback(mlmeConfirmParams);
3191 }
3192 }
3193
3194 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3195
3196 if (m_csmaCa->IsSlottedCsmaCa())
3197 {
3198 // The beacon was sent immediately in beacon-enabled mode
3199 m_txPkt = nullptr;
3200 }
3201 else
3202 {
3203 // The beacon was sent using CSMA/CA as a result of a beacon request
3204 // therefore, remove it from TX Queue
3206 }
3207 }
3208 else if (macHdr.IsAckReq()) // We have sent a regular data packet, check if we have to
3209 // wait for an ACK.
3210 {
3211 // we sent a regular data frame or command frame (e.g. AssocReq command) that
3212 // require ACK wait for the ack or the next retransmission timeout start
3213 // retransmission timer
3214 Time waitTime = Seconds(static_cast<double>(GetMacAckWaitDuration()) / symbolRate);
3215 NS_ASSERT(m_ackWaitTimeout.IsExpired());
3217 m_setMacState.Cancel();
3220 return;
3221 }
3222 else if (macHdr.IsCommand())
3223 {
3224 // We handle commands that do not require ACK
3225 // (e.g. Coordinator realigment command in an orphan response)
3226 // Other command with ACK required are handle by the previous if statement.
3227
3228 // Check the transmitted packet command type and issue the appropriate indication.
3229 Ptr<Packet> txOriginalPkt = m_txPkt->Copy();
3230 LrWpanMacHeader txMacHdr;
3231 txOriginalPkt->RemoveHeader(txMacHdr);
3232 CommandPayloadHeader txMacPayload;
3233 txOriginalPkt->RemoveHeader(txMacPayload);
3234
3236 {
3238 {
3239 MlmeCommStatusIndicationParams commStatusParams;
3240 commStatusParams.m_panId = m_macPanId;
3241
3242 commStatusParams.m_srcAddrMode = macHdr.GetSrcAddrMode();
3243 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3244 commStatusParams.m_srcShortAddr = macHdr.GetShortSrcAddr();
3245
3246 commStatusParams.m_dstAddrMode = macHdr.GetDstAddrMode();
3247 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3248 commStatusParams.m_dstShortAddr = macHdr.GetShortDstAddr();
3249
3250 commStatusParams.m_status = MacStatus::SUCCESS;
3251 m_mlmeCommStatusIndicationCallback(commStatusParams);
3252 }
3253 }
3254
3255 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3257 }
3258 else
3259 {
3261 // remove the copy of the packet that was just sent
3262 if (!m_mcpsDataConfirmCallback.IsNull())
3263 {
3264 McpsDataConfirmParams confirmParams;
3265 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3266 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
3267 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3268 confirmParams.m_status = MacStatus::SUCCESS;
3269 m_mcpsDataConfirmCallback(confirmParams);
3270 }
3271 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3273 }
3274 }
3275 else
3276 {
3277 // The packet sent was a successful ACK
3278
3279 // Check the received frame before the transmission of the ACK,
3280 // and send the appropriate Indication or Confirmation
3281 Ptr<Packet> recvOriginalPkt = m_rxPkt->Copy();
3282 LrWpanMacHeader receivedMacHdr;
3283 recvOriginalPkt->RemoveHeader(receivedMacHdr);
3284
3285 if (receivedMacHdr.IsCommand())
3286 {
3287 CommandPayloadHeader receivedMacPayload;
3288 recvOriginalPkt->RemoveHeader(receivedMacPayload);
3289
3290 if (receivedMacPayload.GetCommandFrameType() ==
3292 {
3294 {
3295 // NOTE: The LQI parameter is not part of the standard but found
3296 // in some implementations as is required for higher layers (See Zboss
3297 // implementation).
3298 MlmeAssociateIndicationParams associateParams;
3299 associateParams.capabilityInfo = receivedMacPayload.GetCapabilityField();
3300 associateParams.m_extDevAddr = receivedMacHdr.GetExtSrcAddr();
3301 associateParams.lqi = m_lastRxFrameLqi;
3302 m_mlmeAssociateIndicationCallback(associateParams);
3303 }
3304
3305 // Clear the packet buffer for the packet request received.
3306 m_rxPkt = nullptr;
3307 }
3308 else if (receivedMacPayload.GetCommandFrameType() ==
3310 {
3311 MlmeAssociateConfirmParams confirmParams;
3312
3313 switch (static_cast<MacStatus>(receivedMacPayload.GetAssociationStatus()))
3314 {
3315 case MacStatus::SUCCESS:
3316 // The assigned short address by the coordinator
3317 SetShortAddress(receivedMacPayload.GetShortAddr());
3318 m_macPanId = receivedMacHdr.GetSrcPanId();
3319
3320 confirmParams.m_status = MacStatus::SUCCESS;
3321 confirmParams.m_assocShortAddr = GetShortAddress();
3322 break;
3324 confirmParams.m_status = MacStatus::FULL_CAPACITY;
3325 m_macPanId = 0xffff;
3327 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3328 m_incCapEvent.Cancel();
3329 m_incCfpEvent.Cancel();
3330 m_csmaCa->SetUnSlottedCsmaCa();
3333 break;
3335 default:
3336 confirmParams.m_status = MacStatus::ACCESS_DENIED;
3337 m_macPanId = 0xffff;
3339 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3340 m_incCapEvent.Cancel();
3341 m_incCfpEvent.Cancel();
3342 m_csmaCa->SetUnSlottedCsmaCa();
3345 break;
3346 }
3347
3348 if (!m_mlmeAssociateConfirmCallback.IsNull())
3349 {
3350 m_mlmeAssociateConfirmCallback(confirmParams);
3351 }
3352 }
3353 else if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::DATA_REQ)
3354 {
3355 // We enqueue the the Assoc Response command frame in the Tx queue
3356 // and the packet is transmitted as soon as the PHY is free and the IFS have
3357 // taken place.
3359 }
3360 }
3361
3362 // Clear the packet buffer for the ACK packet sent.
3363 m_txPkt = nullptr;
3364 }
3365 }
3366 else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
3367 {
3368 if (!macHdr.IsAcknowledgment())
3369 {
3370 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3371 std::shared_ptr<TxQueueElement> txQElement = m_txQueue.front();
3372 m_macTxDropTrace(txQElement->txQPkt);
3373 if (!m_mcpsDataConfirmCallback.IsNull())
3374 {
3375 McpsDataConfirmParams confirmParams;
3376 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3377 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
3378 m_mcpsDataConfirmCallback(confirmParams);
3379 }
3381 }
3382 else
3383 {
3384 NS_LOG_ERROR("Unable to send ACK");
3385 }
3386 }
3387 else
3388 {
3389 // Something went really wrong. The PHY is not in the correct state for
3390 // data transmission.
3391 NS_FATAL_ERROR("Transmission attempt failed with PHY status " << status);
3392 }
3393
3394 if (!ifsWaitTime.IsZero())
3395 {
3396 m_ifsEvent =
3397 Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
3398 }
3399
3400 m_setMacState.Cancel();
3402}
3403
3404void
3406{
3407 NS_LOG_FUNCTION(this << status);
3408 // Direct this call through the csmaCa object
3409 m_csmaCa->PlmeCcaConfirm(status);
3410}
3411
3412void
3413LrWpanMac::PlmeEdConfirm(PhyEnumeration status, uint8_t energyLevel)
3414{
3415 NS_LOG_FUNCTION(this << status << energyLevel);
3416
3417 if (energyLevel > m_maxEnergyLevel)
3418 {
3419 m_maxEnergyLevel = energyLevel;
3420 }
3421
3423 Seconds(8.0 / m_phy->GetDataOrSymbolRate(false)))
3424 {
3425 m_phy->PlmeEdRequest();
3426 }
3427}
3428
3429void
3432 Ptr<PhyPibAttributes> attribute)
3433{
3434 NS_LOG_FUNCTION(this << status << id << attribute);
3435}
3436
3437void
3439{
3440 NS_LOG_FUNCTION(this << status << m_macState);
3441
3442 if (m_macState == MAC_SENDING &&
3443 (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3444 {
3446
3447 // Start sending if we are in state SENDING and the PHY transmitter was enabled.
3451 m_phy->PdDataRequest(m_txPkt->GetSize(), m_txPkt);
3452 }
3453 else if (m_macState == MAC_CSMA &&
3454 (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3455 {
3456 // Start the CSMA algorithm as soon as the receiver is enabled.
3457 m_csmaCa->Start();
3458 }
3459 else if (m_macState == MAC_IDLE)
3460 {
3462 status == IEEE_802_15_4_PHY_TRX_OFF);
3463
3464 if (status == IEEE_802_15_4_PHY_RX_ON && m_scanEnergyEvent.IsPending())
3465 {
3466 // Kick start Energy Detection Scan
3467 m_phy->PlmeEdRequest();
3468 }
3469 else if (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS)
3470 {
3471 // Check if there is not messages to transmit when going idle
3472 CheckQueue();
3473 }
3474 }
3475 else if (m_macState == MAC_ACK_PENDING)
3476 {
3478 }
3479 else
3480 {
3481 // TODO: What to do when we receive an error?
3482 // If we want to transmit a packet, but switching the transceiver on results
3483 // in an error, we have to recover somehow (and start sending again).
3484 NS_FATAL_ERROR("Error changing transceiver state");
3485 }
3486}
3487
3488void
3490{
3491 NS_LOG_FUNCTION(this << status << id);
3493 {
3495 {
3496 // get the first channel to scan from scan channel list
3497 bool channelFound = false;
3498 for (int i = m_channelScanIndex; i <= 26; i++)
3499 {
3500 if ((m_scanParams.m_scanChannels & (1 << m_channelScanIndex)) != 0)
3501 {
3502 channelFound = true;
3503 break;
3504 }
3506 }
3507
3508 if (channelFound)
3509 {
3511 pibAttr->phyCurrentChannel = m_channelScanIndex;
3512 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel,
3513 pibAttr);
3514 }
3515 }
3516 else
3517 {
3518 if (!m_mlmeScanConfirmCallback.IsNull())
3519 {
3520 MlmeScanConfirmParams confirmParams;
3521 confirmParams.m_scanType = m_scanParams.m_scanType;
3522 confirmParams.m_chPage = m_scanParams.m_chPage;
3523 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3524 m_mlmeScanConfirmCallback(confirmParams);
3525 }
3526 NS_LOG_ERROR(this << "Channel Scan: Invalid channel page");
3527 }
3528 }
3530 {
3532 {
3533 auto symbolRate = static_cast<uint64_t>(m_phy->GetDataOrSymbolRate(false));
3534 Time nextScanTime;
3535
3536 if (m_scanParams.m_scanType == MLMESCAN_ORPHAN)
3537 {
3538 nextScanTime = Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
3539 }
3540 else
3541 {
3542 uint64_t scanDurationSym =
3543 lrwpan::aBaseSuperframeDuration * (pow(2, m_scanParams.m_scanDuration) + 1);
3544
3545 nextScanTime = Seconds(static_cast<double>(scanDurationSym) / symbolRate);
3546 }
3547
3548 switch (m_scanParams.m_scanType)
3549 {
3550 case MLMESCAN_ED:
3551 m_maxEnergyLevel = 0;
3554 // set phy to RX_ON and kick start the first PLME-ED.request
3555 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3556 break;
3557 case MLMESCAN_ACTIVE:
3560 break;
3561 case MLMESCAN_PASSIVE:
3563 // turn back the phy to RX_ON after setting Page/channel
3564 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3565 break;
3566 case MLMESCAN_ORPHAN:
3568 Simulator::Schedule(nextScanTime, &LrWpanMac::EndChannelScan, this);
3570 break;
3571
3572 default:
3573 MlmeScanConfirmParams confirmParams;
3574 confirmParams.m_scanType = m_scanParams.m_scanType;
3575 confirmParams.m_chPage = m_scanParams.m_chPage;
3576 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3577 if (!m_mlmeScanConfirmCallback.IsNull())
3578 {
3579 m_mlmeScanConfirmCallback(confirmParams);
3580 }
3581 NS_LOG_ERROR("Scan Type currently not supported");
3582 return;
3583 }
3584 }
3585 else
3586 {
3587 if (!m_mlmeScanConfirmCallback.IsNull())
3588 {
3589 MlmeScanConfirmParams confirmParams;
3590 confirmParams.m_scanType = m_scanParams.m_scanType;
3591 confirmParams.m_chPage = m_scanParams.m_chPage;
3592 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3593 m_mlmeScanConfirmCallback(confirmParams);
3594 }
3595 NS_LOG_ERROR("Channel " << m_channelScanIndex
3596 << " could not be set in the current page");
3597 }
3598 }
3600 {
3602 {
3604 pibAttr->phyCurrentChannel = m_startParams.m_logCh;
3605 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3606 }
3607 else
3608 {
3609 if (!m_mlmeStartConfirmCallback.IsNull())
3610 {
3611 MlmeStartConfirmParams confirmParams;
3612 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3613 m_mlmeStartConfirmCallback(confirmParams);
3614 }
3615 NS_LOG_ERROR("Invalid page parameter in MLME-start");
3616 }
3617 }
3620 {
3622 {
3624 }
3625 else
3626 {
3627 if (!m_mlmeStartConfirmCallback.IsNull())
3628 {
3629 MlmeStartConfirmParams confirmParams;
3630 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3631 m_mlmeStartConfirmCallback(confirmParams);
3632 }
3633 NS_LOG_ERROR("Invalid channel parameter in MLME-start");
3634 }
3635 }
3637 {
3639 {
3641 pibAttr->phyCurrentChannel = m_associateParams.m_chNum;
3642 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3643 }
3644 else
3645 {
3646 m_macPanId = 0xffff;
3648 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3649 m_incCapEvent.Cancel();
3650 m_incCfpEvent.Cancel();
3651 m_csmaCa->SetUnSlottedCsmaCa();
3654
3655 if (!m_mlmeAssociateConfirmCallback.IsNull())
3656 {
3657 MlmeAssociateConfirmParams confirmParams;
3658 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3659 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3660 m_mlmeAssociateConfirmCallback(confirmParams);
3661 }
3662 NS_LOG_ERROR("Invalid page parameter in MLME-associate");
3663 }
3664 }
3667 {
3669 {
3671 }
3672 else
3673 {
3674 m_macPanId = 0xffff;
3676 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3677 m_incCapEvent.Cancel();
3678 m_incCfpEvent.Cancel();
3679 m_csmaCa->SetUnSlottedCsmaCa();
3682
3683 if (!m_mlmeAssociateConfirmCallback.IsNull())
3684 {
3685 MlmeAssociateConfirmParams confirmParams;
3686 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3687 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3688 m_mlmeAssociateConfirmCallback(confirmParams);
3689 }
3690 NS_LOG_ERROR("Invalid channel parameter in MLME-associate");
3691 }
3692 }
3693 else
3694 {
3695 if (!m_mlmeSetConfirmCallback.IsNull())
3696 {
3697 MlmeSetConfirmParams confirmParams;
3699 {
3700 confirmParams.m_status = MacStatus::SUCCESS;
3701 }
3702 else
3703 {
3705 }
3706
3708 {
3710 }
3712 {
3714 }
3715
3716 m_mlmeSetConfirmCallback(confirmParams);
3717 }
3718 }
3719}
3720
3721void
3723{
3724 NS_LOG_FUNCTION(this << "mac state = " << macState);
3725
3726 if (macState == MAC_IDLE)
3727 {
3730 {
3731 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3732 }
3733 else
3734 {
3735 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3736 }
3737 }
3738 else if (macState == MAC_ACK_PENDING)
3739 {
3741 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3742 }
3743 else if (macState == MAC_CSMA)
3744 {
3747 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3748 }
3749 else if (m_macState == MAC_CSMA && macState == CHANNEL_IDLE)
3750 {
3751 // Channel is idle, set transmitter to TX_ON
3753 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
3754 }
3755 else if (m_macState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
3756 {
3758
3759 // Cannot find a clear channel, drop the current packet
3760 // and send the proper confirm/indication according to the packet type
3761 NS_LOG_DEBUG(this << " cannot find clear channel");
3762
3764
3765 Ptr<Packet> pkt = m_txPkt->Copy();
3766 LrWpanMacHeader macHdr;
3767 pkt->RemoveHeader(macHdr);
3768
3769 if (macHdr.IsCommand())
3770 {
3771 CommandPayloadHeader cmdPayload;
3772 pkt->RemoveHeader(cmdPayload);
3773
3774 switch (cmdPayload.GetCommandFrameType())
3775 {
3777 m_macPanId = 0xffff;
3779 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3780 m_incCapEvent.Cancel();
3781 m_incCfpEvent.Cancel();
3782 m_csmaCa->SetUnSlottedCsmaCa();
3785
3786 if (!m_mlmeAssociateConfirmCallback.IsNull())
3787 {
3788 MlmeAssociateConfirmParams confirmParams;
3789 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3791 m_mlmeAssociateConfirmCallback(confirmParams);
3792 }
3793 break;
3794 }
3797 {
3798 MlmeCommStatusIndicationParams commStatusParams;
3799 commStatusParams.m_panId = m_macPanId;
3800 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3801 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3802 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3803 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3805 m_mlmeCommStatusIndicationCallback(commStatusParams);
3806 }
3808 break;
3809 }
3811 m_macPanId = 0xffff;
3813 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3814 m_incCapEvent.Cancel();
3815 m_incCfpEvent.Cancel();
3816 m_csmaCa->SetUnSlottedCsmaCa();
3819
3820 if (!m_mlmePollConfirmCallback.IsNull())
3821 {
3822 MlmePollConfirmParams pollConfirmParams;
3823 pollConfirmParams.m_status = MacStatus::CHANNEL_ACCESS_FAILURE;
3824 m_mlmePollConfirmCallback(pollConfirmParams);
3825 }
3826 break;
3827 }
3830 {
3831 MlmeCommStatusIndicationParams commStatusParams;
3832 commStatusParams.m_panId = m_macPanId;
3833 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3834 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3835 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3836 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3838 m_mlmeCommStatusIndicationCallback(commStatusParams);
3839 }
3840 break;
3841 }
3843 if (m_scanOrphanEvent.IsPending())
3844 {
3845 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3846 }
3847 // TODO: Handle orphan notification command during a
3848 // channel access failure when not is not scanning.
3849 break;
3850 }
3852 if (m_scanEvent.IsPending())
3853 {
3854 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3855 }
3856 // TODO: Handle beacon request command during a
3857 // channel access failure when not scanning.
3858 break;
3859 }
3860 default: {
3861 // TODO: Other commands(e.g. Disassociation notification, etc)
3862 break;
3863 }
3864 }
3866 }
3867 else if (macHdr.IsData())
3868 {
3869 if (!m_mcpsDataConfirmCallback.IsNull())
3870 {
3871 McpsDataConfirmParams confirmParams;
3872 confirmParams.m_msduHandle = m_txQueue.front()->txQMsduHandle;
3874 m_mcpsDataConfirmCallback(confirmParams);
3875 }
3876 // remove the copy of the packet that was just sent
3878 }
3879 else
3880 {
3881 // TODO:: specify behavior for other packets
3882 m_txPkt = nullptr;
3883 m_retransmission = 0;
3884 m_numCsmacaRetry = 0;
3885 }
3886
3889 {
3890 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3891 }
3892 else
3893 {
3894 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3895 }
3896 }
3897 else if (m_macState == MAC_CSMA && macState == MAC_CSMA_DEFERRED)
3898 {
3900 m_txPkt = nullptr;
3901 // The MAC is running on beacon mode and the current packet could not be sent in the
3902 // current CAP. The packet will be send on the next CAP after receiving the beacon.
3903 // The PHY state does not change from its current form. The PHY change (RX_ON) will be
3904 // triggered by the scheduled beacon event.
3905
3906 NS_LOG_DEBUG("****** PACKET DEFERRED to the next superframe *****");
3907 }
3908}
3909
3910void
3915
3916void
3921
3922uint16_t
3924{
3925 return m_macPanId;
3926}
3927
3933
3939
3940void
3941LrWpanMac::SetPanId(uint16_t panId)
3942{
3943 m_macPanId = panId;
3944}
3945
3946void
3948{
3949 NS_LOG_LOGIC(this << " change lrwpan mac state from " << m_macState << " to " << newState);
3950 m_macStateLogger(m_macState, newState);
3951 m_macState = newState;
3952}
3953
3954uint64_t
3956{
3957 return lrwpan::aUnitBackoffPeriod + lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
3958 ceil(6 * m_phy->GetPhySymbolsPerOctet());
3959}
3960
3961uint8_t
3966
3967void
3969{
3970 NS_LOG_DEBUG("Transmit Queue Size: " << m_txQueue.size());
3971}
3972
3973void
3975{
3976 m_macMaxFrameRetries = retries;
3977}
3978
3979bool
3981{
3983 LrWpanMacHeader macHdr;
3984 m_txPkt->PeekHeader(macHdr);
3985
3986 if (m_coor)
3987 {
3988 // The device is its coordinator and the packet is not to itself
3989 return false;
3990 }
3991 else if (m_macCoordShortAddress == macHdr.GetShortDstAddr() ||
3993 {
3994 return true;
3995 }
3996 else
3997 {
3998 NS_LOG_DEBUG("ERROR: Packet not for the coordinator!");
3999 return false;
4000 }
4001}
4002
4005{
4007
4008 if (m_txPkt->GetSize() <= lrwpan::aMaxSIFSFrameSize)
4009 {
4010 return m_macSIFSPeriod;
4011 }
4012 else
4013 {
4014 return m_macLIFSPeriod;
4015 }
4016}
4017
4018void
4023
4024void
4029
4030uint64_t
4032{
4034 // Sync Header (SHR) + 8 bits PHY header (PHR) + PSDU
4035 return (m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
4036 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet()));
4037}
4038
4039bool
4041{
4043 LrWpanMacHeader macHdr;
4044 m_txPkt->PeekHeader(macHdr);
4045
4046 return macHdr.IsAckReq();
4047}
4048
4049} // namespace lrwpan
4050} // namespace ns3
This class can contain 16 bit addresses.
bool IsMulticast() const
Checks if the address is a multicast address according to RFC 4944 Section 9 (i.e....
bool IsBroadcast() const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
an EUI-64 address
static Mac64Address Allocate()
Allocate a new Mac64Address.
static bool ChecksumEnabled()
Definition node.cc:267
virtual void DoInitialize()
Initialize() implementation.
Definition object.cc:437
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:614
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:200
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
@ S
second
Definition nstime.h:106
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:305
a unique identifier for an interface.
Definition type-id.h:50
TypeId AddDeprecatedName(const std::string &name)
Add an deprecated name for a TypeId.
Definition type-id.cc:860
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Hold an unsigned integer type.
Definition uinteger.h:34
Implements the header for the MAC payload beacon frame according to the IEEE 802.15....
void SetSuperframeSpecField(uint16_t sfrmField)
Set the superframe specification field to the beacon payload header.
uint16_t GetSuperframeSpecField() const
Get the superframe specification field from the beacon payload header.
GtsFields GetGtsFields() const
Get the Guaranteed Time Slots (GTS) fields from the beacon payload header.
void SetGtsFields(GtsFields gtsFields)
Set the superframe Guaranteed Time Slot (GTS) fields to the beacon payload header.
PendingAddrFields GetPndAddrFields() const
Get the pending address fields from the beacon payload header.
void SetPndAddrFields(PendingAddrFields pndAddrFields)
Set the superframe Pending Address fields to the beacon payload header.
Implements the header for the MAC payload command frame according to the IEEE 802....
MacCommand GetCommandFrameType() const
Get the command frame type ID.
Mac16Address GetShortAddr() const
Get the Short address assigned by the coordinator (Association Response and Coordinator Realigment co...
uint16_t GetPanId() const
Get the PAN identifier.
void SetPage(uint8_t page)
Set the logical channel page number.
void SetShortAddr(Mac16Address shortAddr)
Set the Short Address Assigned by the coordinator (Association Response and Coordinator Realigment Co...
uint8_t GetCapabilityField() const
Get the Capability Information Field from the command payload header.
void SetCommandFrameType(MacCommand macCmd)
Set the command frame type.
Mac16Address GetCoordShortAddr() const
Get the coordinator short address.
void SetCapabilityField(uint8_t cap)
Set the Capability Information Field to the command payload header (Association Request Command).
void SetCoordShortAddr(Mac16Address addr)
Set the coordinator short address (16 bit address).
@ ASSOCIATION_RESP
Association response (RFD true: Rx).
@ DATA_REQ
Data Request (RFD true: Tx).
@ COOR_REALIGN
Coordinator Realignment (RFD true: Rx).
@ ORPHAN_NOTIF
Orphan Notification (RFD true: Tx).
@ ASSOCIATION_REQ
Association request (RFD true: Tx).
@ BEACON_REQ
Beacon Request (RFD true: none ).
void SetAssociationStatus(uint8_t status)
Set status resulting from the association attempt (Association Response Command).
uint8_t GetAssociationStatus() const
Get the status resulting from an association request (Association Response Command).
void SetPanId(uint16_t id)
Get the PAN identifier.
void SetChannel(uint8_t channel)
Set the logical channel number.
Represent the GTS information fields.
bool GetGtsPermit() const
Get the GTS Specification Permit.
Lr-wpan MAC layer abstraction.
MlmeOrphanIndicationCallback m_mlmeOrphanIndicationCallback
This callback is used to indicate the reception of a orphan notification command.
MlmeGetConfirmCallback m_mlmeGetConfirmCallback
This callback is used to report the result of an attribute read request to the upper layers.
MlmeAssociateIndicationCallback m_mlmeAssociateIndicationCallback
This callback is used to indicate the reception of an association request command.
MlmeSetConfirmCallback m_mlmeSetConfirmCallback
This callback is used to report the result of an attribute writing request to the upper layers.
MlmePollConfirmCallback m_mlmePollConfirmCallback
This callback is used to report the status after a device send data command request to the coordinato...
MlmeCommStatusIndicationCallback m_mlmeCommStatusIndicationCallback
This callback is instigated through a response primitive.
McpsDataConfirmCallback m_mcpsDataConfirmCallback
This callback is used to report data transmission request status to the upper layers.
McpsDataIndicationCallback m_mcpsDataIndicationCallback
This callback is used to notify incoming packets to the upper layers.
MlmeScanConfirmCallback m_mlmeScanConfirmCallback
This callback is used to report the result of a scan on a group of channels for the selected channel ...
MlmeAssociateConfirmCallback m_mlmeAssociateConfirmCallback
This callback is used to report the status after a device request an association with a coordinator.
MlmeSyncLossIndicationCallback m_mlmeSyncLossIndicationCallback
This callback is used to indicate the loss of synchronization with a coordinator.
MlmeBeaconNotifyIndicationCallback m_mlmeBeaconNotifyIndicationCallback
This callback is used to notify incoming beacon packets to the upper layers.
MlmeStartConfirmCallback m_mlmeStartConfirmCallback
This callback is used to report the start of a new PAN or the begin of a new superframe configuration...
Represent the Mac Header with the Frame Control and Sequence Number fields.
LrWpanMacType GetType() const
Get the header type.
Mac16Address GetShortSrcAddr() const
Get the Source Short address.
void SetDstAddrMode(uint8_t addrMode)
Set the Destination address mode.
void SetNoAckReq()
Set the Frame Control field "Ack. Request" bit to false.
void SetDstAddrFields(uint16_t panId, Mac16Address addr)
Set Destination address fields.
Mac64Address GetExtSrcAddr() const
Get the Source Extended address.
bool IsData() const
Returns true if the header is a data.
bool IsBeacon() const
Returns true if the header is a beacon.
@ LRWPAN_MAC_ACKNOWLEDGMENT
LRWPAN_MAC_ACKNOWLEDGMENT.
@ LRWPAN_MAC_RESERVED
LRWPAN_MAC_RESERVED.
@ LRWPAN_MAC_COMMAND
LRWPAN_MAC_COMMAND.
@ LRWPAN_MAC_BEACON
LRWPAN_MAC_BEACON.
void SetPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to true.
Mac16Address GetShortDstAddr() const
Get the Destination Short address.
void SetSrcAddrMode(uint8_t addrMode)
Set the Source address mode.
bool IsCommand() const
Returns true if the header is a command.
uint8_t GetSeqNum() const
Get the frame Sequence number.
void SetFrameVer(uint8_t ver)
Set the Frame version.
uint8_t GetFrameVer() const
Get the Frame Version of Frame control field.
void SetSrcAddrFields(uint16_t panId, Mac16Address addr)
Set Source address fields.
uint16_t GetSrcPanId() const
Get the Source PAN ID.
void SetNoPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to false.
uint16_t GetDstPanId() const
Get the Destination PAN ID.
void SetAckReq()
Set the Frame Control field "Ack. Request" bit to true.
bool IsAckReq() const
Check if Ack.
uint8_t GetDstAddrMode() const
Get the Dest.
void SetSecDisable()
Set the Frame Control field "Security Enabled" bit to false.
Mac64Address GetExtDstAddr() const
Get the Destination Extended address.
bool IsAcknowledgment() const
Returns true if the header is an ack.
uint8_t GetSrcAddrMode() const
Get the Source Addressing Mode of Frame control field.
Ptr< Packet > m_rxPkt
The command request packet received.
TracedCallback< Ptr< const Packet > > m_macTxDequeueTrace
The trace source fired when packets are dequeued from the L3/l2 transmission queue.
void RemovePendTxQElement(Ptr< Packet > p)
Remove an element from the pending transaction list.
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired for packets successfully received by the device but dropped before being forwa...
uint8_t m_deviceCapability
Indication of current device capability (FFD or RFD).
std::vector< uint8_t > m_macBeaconPayload
The set with the contents of the beacon payload.
void SetExtendedAddress(Mac64Address address)
Set the extended address of this MAC.
TracedCallback< Ptr< const Packet > > m_macIndTxDequeueTrace
The trace source fired when packets are dequeued from the L3/l2 indirect transmission queue (Pending ...
Ptr< LrWpanPhy > GetPhy()
Get the underlying PHY of the MAC.
uint32_t m_superframeDuration
Indication of the superframe duration in symbols.
void AwaitBeacon()
Called after the end of an INCOMING superframe to start the moment a device waits for a new incoming ...
void EndStartRequest()
Called to end a MLME-START.request after changing the page and channel number.
void MlmeAssociateResponse(MlmeAssociateResponseParams params) override
IEEE 802.15.4-2011, section 6.2.2.3 MLME-ASSOCIATE.response Primitive used to initiate a response to ...
bool m_macPromiscuousMode
Indicates if MAC sublayer is in receive all mode.
Ptr< LrWpanCsmaCa > m_csmaCa
The CSMA/CA implementation used by this MAC.
void SendAck(uint8_t seqno)
Send an acknowledgment packet for the given sequence number.
uint8_t m_numCsmacaRetry
The number of CSMA/CA retries used for sending the current packet.
Ptr< Packet > m_txPkt
The packet which is currently being sent by the MAC layer.
MlmeStartRequestParams m_startParams
The parameters used during a MLME-START.request.
void PurgeInd()
Purge expired transactions from the pending transactions list.
void SetCsmaCa(Ptr< LrWpanCsmaCa > csmaCa)
Set the CSMA/CA implementation to be used by the MAC.
EventId m_scanEvent
Scheduler event for the end of an ACTIVE or PASSIVE channel scan.
void PdDataConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.1.2 Confirm the end of transmission of an MPDU to MAC.
void SendOrphanNotificationCommand()
Called to send a orphan notification command.
Mac64Address m_macExtendedAddress
The extended 64 address (IEEE EUI-64) used by this MAC.
EventId m_scanEnergyEvent
Scheduler event for the end of a ED channel scan.
uint16_t m_macPanIdScan
Temporarily stores the value of the current m_macPanId when a MLME-SCAN.request is performed.
EventId m_setMacState
Scheduler event for a deferred MAC state change.
void ReceiveData(uint8_t lqi, int8_t rssi, const LrWpanMacHeader &receivedMacHdr, Ptr< Packet > p)
Used to process the reception of data.
uint32_t m_macBeaconPayloadLength
The length, in octets, of the beacon payload.
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
A trace source that emulates a promiscuous mode protocol sniffer connected to the device.
TracedCallback< Ptr< const Packet >, uint8_t, uint8_t > m_sentPktTrace
The trace source fired when packets are considered as successfully sent or the transmission has been ...
void ReceiveInPromiscuousMode(uint8_t lqi, int8_t rssi, const LrWpanMacHeader &receivedMacHdr, Ptr< Packet > p)
Process a frame when promiscuous mode is active.
uint64_t m_assocRespCmdWaitTime
The maximum wait time for an association response command after the reception of data request command...
GtsFields GetGtsFields()
Constructs the Guaranteed Time Slots (GTS) Fields from local information.
void SetIndTxQMaxSize(uint32_t queueSize)
Set the max size of the indirect transmit queue (Pending Transaction list).
uint8_t m_incomingSuperframeOrder
Used by all devices that have a parent.
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
uint32_t m_macLIFSPeriod
The minimum time forming a Long InterFrame Spacing (LIFS) period.
TracedCallback< Ptr< const Packet > > m_macRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
std::vector< uint8_t > m_unscannedChannels
The list of unscanned channels during a scan operation.
bool m_macRxOnWhenIdle
Indication of whether the MAC sublayer is to enable its receiver during idle periods.
bool DequeueInd(Mac64Address dst, std::shared_ptr< IndTxQueueElement > entry)
Extracts a packet from pending transactions list (Indirect transmissions).
void PrintTransmitQueueSize()
Print the number of elements in the packet transmit queue.
uint16_t m_channelScanIndex
The channel list index used to obtain the current scanned channel.
void SendAssocRequestCommand()
Called to send an associate request command.
void PrintReceivedPacket(const LrWpanMacHeader &receivedMacHdr)
Display the MAC header contents of a successfully received packet when logs are active.
EventId m_beaconEvent
Scheduler event for generation of one beacon.
void BeaconSearchTimeout()
Called if the device is unable to locate a beacon in the time set by MLME-SYNC.request.
uint32_t m_macSIFSPeriod
The minimum time forming a Short InterFrame Spacing (SIFS) period.
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets are being sent down to L1.
void MlmeSyncRequest(MlmeSyncRequestParams params) override
IEEE 802.15.4-2011, section 6.2.13.1 MLME-SYNC.request Request to synchronize with the coordinator by...
SequenceNumber8 m_macDsn
Sequence number added to transmitted data or MAC command frame, 00-ff.
void ChangeMacState(MacState newState)
Change the current MAC state to the given new state.
Mac16Address m_macCoordShortAddress
The short address of the coordinator through which the device is associated.
Mac64Address GetCoordExtAddress() const
Get the coordinator extended address currently associated to this device.
void MlmeGetRequest(MacPibAttributeIdentifier id) override
IEEE 802.15.4-2006, section 7.1.6.1 MLME-GET.request Request information about a given PIB attribute.
void ReceiveBeacon(uint8_t lqi, const LrWpanMacHeader &receivedMacHdr, Ptr< Packet > p)
Used to process the reception of a beacon packet.
uint8_t m_macSuperframeOrder
Used by a PAN coordinator or coordinator.
TracedValue< SuperframeStatus > m_incSuperframeStatus
The current period of the incoming superframe.
void SetPanId(uint16_t panId)
Set the PAN id used by this MAC.
void MlmeStartRequest(MlmeStartRequestParams params) override
IEEE 802.15.4-2006, section 7.1.14.1 MLME-START.request Request to allow a PAN coordinator to initiat...
MlmeScanRequestParams m_scanParams
The parameters used during a MLME-SCAN.request.
void SetLrWpanMacState(MacState macState)
CSMA-CA algorithm calls back the MAC after executing channel assessment.
void SetShortAddress(Mac16Address address)
Set the short address of this MAC.
uint8_t m_incomingBeaconOrder
The beaconOrder value of the INCOMING frame.
void PrintTxQueue(std::ostream &os) const
Print the Transmit Queue.
void CheckQueue()
Check the transmission queue.
uint32_t m_incomingSuperframeDuration
Indication of the superframe duration in symbols (e.g.
TracedCallback< Ptr< const Packet > > m_macIndTxEnqueueTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
The trace source fired when packets are dropped due to missing ACKs or because of transmission failur...
void SetMacMaxFrameRetries(uint8_t retries)
Set the macMaxFrameRetries attribute value.
uint16_t m_macTransactionPersistenceTime
The maximum time (in UNIT periods) that a transaction is stored by a coordinator and indicated in its...
void MlmeOrphanResponse(MlmeOrphanResponseParams params) override
IEEE 802.15.4-2011, section 6.2.7.2 MLME-ORPHAN.response Primitive used to initiatte a response to an...
void AckWaitTimeout()
Handle an ACK timeout with a packet retransmission, if there are retransmission left,...
uint32_t m_maxTxQueueSize
The maximum size of the transmit queue.
TracedCallback< Ptr< const Packet > > m_macIndTxDropTrace
The trace source fired when packets are dropped due to indirect Tx queue overflows or expiration.
uint8_t m_retransmission
The number of already used retransmission for the currently transmitted packet.
LrWpanMac()
Default constructor.
EventId m_incCfpEvent
Scheduler event for the end of the incoming superframe CFP.
std::vector< uint8_t > m_energyDetectList
The list of energy measurements, one for each channel searched during an ED scan.
void ReceiveAcknowledgment(const LrWpanMacHeader &receivedMacHdr, Ptr< Packet > p)
Used to process an acknowledgment packet.
SequenceNumber8 m_macBsn
Sequence number added to transmitted beacon frame, 00-ff.
TracedCallback< MacState, MacState > m_macStateLogger
A trace source that fires when the MAC changes states.
TracedCallback< Ptr< const Packet > > m_snifferTrace
A trace source that emulates a non-promiscuous protocol sniffer connected to the device.
Mac64Address GetExtendedAddress() const
Get the extended address of this MAC.
void DoDispose() override
Destructor implementation.
uint8_t m_fnlCapSlot
Indication of the Slot where the CAP portion of the OUTGOING Superframe ends.
MlmeAssociateRequestParams m_associateParams
The parameters used during a MLME-ASSOCIATE.request.
uint32_t m_incomingBeaconInterval
Indication of the interval a node should receive a superframe expressed in symbols.
bool m_macAssociationPermit
Indication of whether a coordinator is currently allowing association.
static TypeId GetTypeId()
Get the type ID.
uint64_t GetMacAckWaitDuration() const
Get the macAckWaitDuration attribute value.
void SetTxQMaxSize(uint32_t queueSize)
Set the max size of the transmit queue.
TracedCallback< Time > m_macIfsEndTrace
The trace source is fired at the end of any Interframe Space (IFS).
void MlmeAssociateRequest(MlmeAssociateRequestParams params) override
IEEE 802.15.4-2011, section 6.2.2.1 MLME-ASSOCIATE.request Request primitive used by a device to requ...
bool GetRxOnWhenIdle() const
Check if the receiver will be enabled when the MAC is idle.
void EnqueueInd(Ptr< Packet > p)
Adds a packet to the pending transactions list (Indirect transmissions).
Time m_macBeaconTxTime
The time that the device transmitted its last beacon frame.
std::vector< PanDescriptor > m_panDescriptorList
The list of PAN descriptors accumulated during channel scans, used to select a PAN to associate.
uint8_t m_maxEnergyLevel
The maximum energy level detected during ED scan on the current channel.
Mac16Address GetShortAddress() const
Get the short address of this MAC.
bool m_macAutoRequest
Indication of whether a device automatically sends data request command if its address is listed in t...
PendingAddrFields GetPendingAddrFields()
Constructs Pending Address Fields from the local information, the Pending Address Fields are part of ...
uint64_t m_rxBeaconSymbols
The total size of the received beacon in symbols.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< LrWpanPhy > m_phy
The PHY associated with this MAC.
EventId m_cfpEvent
Scheduler event for the end of the outgoing superframe CFP.
uint16_t GetPanId() const
Get the PAN id used by this MAC.
TracedCallback< Ptr< const Packet > > m_macTxOkTrace
The trace source fired when packets where successfully transmitted, that is an acknowledgment was rec...
bool m_panCoor
Indication of whether the current device is the PAN coordinator.
std::deque< std::shared_ptr< IndTxQueueElement > > m_indTxQueue
The indirect transmit queue used by the MAC pending messages (The pending transaction list).
void SendAssocResponseCommand(Ptr< Packet > rxDataReqPkt)
Called to send an associate response command.
Time m_macBeaconRxTime
The time that the device received its last bit of the beacon frame.
void PdDataIndication(uint32_t psduLength, Ptr< Packet > p, uint8_t lqi, int8_t rssi)
IEEE 802.15.4-2006 section 6.2.1.3 PD-DATA.indication Indicates the transfer of an MPDU from PHY to M...
void SetAssociatedCoor(Mac16Address mac)
Check if the packet destination is its coordinator.
void StartCFP(SuperframeType superframeType)
Called to begin the Contention Free Period (CFP) in a beacon-enabled mode.
uint16_t m_macPanId
16 bits id of PAN on which this device is operating.
bool PrepareRetransmission()
Check for remaining retransmissions for the packet currently being sent.
void PrintPendingTxQueue(std::ostream &os) const
Print the Pending transaction list.
uint32_t m_ifs
The value of the necessary InterFrame Space after the transmission of a packet.
void MlmeSetRequest(MacPibAttributeIdentifier id, Ptr< MacPibAttributes > attribute) override
IEEE 802.15.4-2011, section 6.2.11.1 MLME-SET.request Attempts to write the given value to the indica...
bool m_beaconTrackingOn
Indication of whether the current device is tracking incoming beacons.
void SendBeaconRequestCommand()
Called to send a beacon request command.
uint32_t m_maxIndTxQueueSize
The maximum size of the indirect transmit queue (The pending transaction list).
void ReceiveCommand(uint8_t lqi, const LrWpanMacHeader &receivedMacHdr, Ptr< Packet > p)
Used to process the reception of a command packet.
void IfsWaitTimeout(Time ifsTime)
After a successful transmission of a frame (beacon, data) or an ack frame reception,...
EventId m_ifsEvent
Scheduler event for Interframe spacing wait time.
void MlmeScanRequest(MlmeScanRequestParams params) override
IEEE 802.15.4-2011, section 6.2.10.1 MLME-SCAN.request Request primitive used to initiate a channel s...
Ptr< UniformRandomVariable > m_uniformVar
The uniform random variable used in this mac layer.
uint8_t m_macMaxFrameRetries
The maximum number of retries allowed after a transmission failure.
PendingPrimitiveStatus m_pendPrimitive
Indicates the pending primitive when PLME.SET operation (page or channel switch) is called from withi...
EventId m_respWaitTimeout
Scheduler event for a response to a request command frame.
uint16_t GetSuperframeField()
Constructs a Superframe specification field from the local information, the superframe Specification ...
bool IsCoordDest()
Check if the packet destination is its coordinator.
EventId m_ackWaitTimeout
Scheduler event for the ACK timeout of the currently transmitted data packet.
void StartCAP(SuperframeType superframeType)
Called to begin the Contention Access Period (CAP) in a beacon-enabled mode.
Mac64Address m_macCoordExtendedAddress
The extended address of the coordinator through which the device is associated.
void McpsDataRequest(McpsDataRequestParams params, Ptr< Packet > p) override
IEEE 802.15.4-2006, section 7.1.1.1 MCPS-DATA.request Request to transfer a MSDU.
void EnqueueTxQElement(std::shared_ptr< TxQueueElement > txQElement)
Add an element to the transmission queue.
EventId m_incCapEvent
Scheduler event for the end of the incoming superframe CAP.
Mac16Address GetCoordShortAddress() const
Get the coordinator short address currently associated to this device.
std::deque< std::shared_ptr< TxQueueElement > > m_txQueue
The transmit queue used by the MAC.
void SendDataRequestCommand()
Used to send a data request command (i.e.
EventId m_trackingEvent
Scheduler event to track the incoming beacons.
uint64_t GetTxPacketSymbols()
Obtain the number of symbols in the packet which is currently being sent by the MAC layer.
uint32_t m_beaconInterval
Indication of the Interval used by the coordinator to transmit beacon frames expressed in symbols.
Mac16Address m_shortAddress
The short address (16 bit address) used by this MAC.
EventId m_assocResCmdWaitTimeout
Scheduler event for the lost of a association response command frame.
void PlmeGetAttributeConfirm(PhyEnumeration status, PhyPibAttributeIdentifier id, Ptr< PhyPibAttributes > attribute)
IEEE 802.15.4-2006 section 6.2.2.6 PLME-GET.confirm Get attributes per definition from Table 23 in se...
uint8_t m_macBeaconOrder
Used by a PAN coordinator or coordinator.
void SetPhy(Ptr< LrWpanPhy > phy)
Set the underlying PHY for the MAC.
void MlmePollRequest(MlmePollRequestParams params) override
IEEE 802.15.4-2011, section 6.2.14.2 MLME-POLL.request Prompts the device to request data from the co...
void RemoveFirstTxQElement()
Remove the tip of the transmission queue, including clean up related to the last packet transmission.
TracedValue< SuperframeStatus > m_outSuperframeStatus
The current period of the outgoing superframe.
void SetRxOnWhenIdle(bool rxOnWhenIdle)
Set if the receiver should be enabled when the MAC is idle.
void PlmeCcaConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
void PlmeSetAttributeConfirm(PhyEnumeration status, PhyPibAttributeIdentifier id)
IEEE 802.15.4-2006 section 6.2.2.10 PLME-SET.confirm Set attributes per definition from Table 23 in s...
EventId m_scanOrphanEvent
Scheduler event for the end of an ORPHAN channel scan.
void StartInactivePeriod(SuperframeType superframeType)
Start the Inactive Period in a beacon-enabled mode.
uint32_t GetIfsSize()
Get the size of the Interframe Space according to MPDU size (m_txPkt).
EventId m_capEvent
Scheduler event for the end of the outgoing superframe CAP.
void PlmeSetTRXStateConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.8 PLME-SET-TRX-STATE.confirm Set PHY state.
TracedValue< MacState > m_macState
The current state of the MAC layer.
void EndChannelEnergyScan()
Called at the end of one ED channel scan.
uint8_t m_incomingFnlCapSlot
Indication of the Slot where the CAP portion of the INCOMING Superframe ends.
bool m_ignoreDataCmdAck
This flag informs the MAC that an association response command was received before the acknowledgment...
TracedCallback< Ptr< const Packet > > m_macTxEnqueueTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
uint8_t m_numLostBeacons
The number of consecutive loss beacons in a beacon tracking operation.
uint8_t GetMacMaxFrameRetries() const
Get the macMaxFrameRetries attribute value.
bool IsTxAckReq()
Check if the packet to transmit requires acknowledgment.
void SendOneBeacon()
Called to send a single beacon frame.
void LostAssocRespCommand()
Called after m_assocRespCmdWaitTime timeout while waiting for an association response command.
void PlmeEdConfirm(PhyEnumeration status, uint8_t energyLevel)
IEEE 802.15.4-2006 section 6.2.2.4 PLME-ED.confirm status and energy level.
bool m_coor
Indicates if the current device is a coordinator type.
uint8_t m_lastRxFrameLqi
Keep track of the last received frame Link Quality Indicator.
void EndChannelScan()
Called at the end of the current channel scan (Active or Passive) for a given duration.
void EndAssociateRequest()
Called to end an MLME-ASSOCIATE.request after changing the page and channel number.
uint64_t m_macResponseWaitTime
The maximum time, in multiples of aBaseSuperframeDuration, a device shall wait for a response command...
void DoInitialize() override
Initialize() implementation.
Represent the Mac Trailer with the Frame Check Sequence field.
void EnableFcs(bool enable)
Enable or disable FCS calculation for this trailer.
void SetFcs(Ptr< const Packet > p)
Calculate and set the FCS value based on the given packet.
bool CheckFcs(Ptr< const Packet > p)
Check the FCS of a given packet against the FCS value stored in the trailer.
Represent the Pending Address Specification field.
Represent the Superframe Specification information field.
void SetPanCoor(bool panCoor)
Set the Superframe Specification PAN coordinator field.
uint8_t GetFinalCapSlot() const
Get the the Final CAP Slot.
void SetAssocPermit(bool assocPermit)
Set the Superframe Specification Association Permit field.
void SetBattLifeExt(bool battLifeExt)
Set the Superframe Specification Battery Life Extension (BLE).
bool IsBattLifeExt() const
Check if the Battery Life Extension bit is enabled.
uint8_t GetBeaconOrder() const
Get the Superframe Specification Beacon Order field.
uint8_t GetFrameOrder() const
Get the Superframe Specification Frame Order field.
uint16_t GetSuperframe() const
Get the Superframe specification information field.
void SetFinalCapSlot(uint8_t capSlot)
Set the superframe specification Final CAP slot field.
void SetBeaconOrder(uint8_t bcnOrder)
Set the superframe specification Beacon Order field.
void SetSuperframeOrder(uint8_t frmOrder)
Set the superframe specification Superframe Order field.
constexpr uint32_t aMaxSIFSFrameSize
The maximum size of an MPDU, in octets, that can be followed by a Short InterFrame Spacing (SIFS) per...
constexpr uint32_t aMaxLostBeacons
The number of consecutive lost beacons that will cause the MAC sublayer of a receiving device to decl...
constexpr uint32_t aMaxBeaconPayloadLength
The maximum size, in octets, of a beacon payload.
constexpr uint32_t aMaxPhyPacketSize
The maximum packet size accepted by the PHY.
constexpr uint32_t aUnitBackoffPeriod
Number of symbols per CSMA/CA time unit, default 20 symbols.
constexpr uint32_t aTurnaroundTime
The turnaround time in symbol periods for switching the transceiver from RX to TX or vice-versa.
constexpr uint32_t aBaseSuperframeDuration
Length of a superframe in symbols.
constexpr uint32_t aMinMPDUOverhead
The minimum number of octets added by the MAC sublayer to the PSDU.
#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_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
Callback< R, Args... > MakeNullCallback()
Build null Callbacks which take no arguments, for varying number of template arguments,...
Definition callback.h:734
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:246
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
MacPibAttributeIdentifier
IEEE 802.15.4-2006 PHY and MAC PIB Attribute Identifiers Table 23 and Table 86.
MacState
MAC states.
Definition lr-wpan-mac.h:65
SuperframeType
Superframe type.
PhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
MacStatus
The status of a confirm or an indication primitive as a result of a previous request.
PhyPibAttributeIdentifier
IEEE802.15.4-2006 PHY PIB Attribute Identifiers Table 23 in section 6.4.2.
@ macCoordShortAddress
The 16-bit short address assigned to the coordinator through which the device is associated.
@ macPanId
The 16-bit identifier of the Personal Area Network (PAN).
@ pCurrentChannel
RF channel used for transmissions and receptions.
@ macShortAddress
The short address of the device (16 bit address).
@ macRxOnWhenIdle
Indication of whether the MAC is enabled during idle periods.
@ macBeaconPayloadLength
The length in octets of the beacon payload.
@ macPromiscuousMode
Indication of whether the MAC sublayer is in a promiscuous mode.
@ pCurrentPage
The current channel page.
@ macExtendedAddress
The extended address of the device (64 bit address).
@ macAssociationPermit
Indication of whether a coordinator is allowing association.
@ macCoordExtendedAddress
The 64-bit address of the coordinator through which the device is associated.
@ macBeaconPayload
The contents of the beacon payload.
@ MAC_CSMA
MAC_CSMA.
Definition lr-wpan-mac.h:67
@ MAC_GTS
MAC_GTS.
Definition lr-wpan-mac.h:73
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition lr-wpan-mac.h:70
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition lr-wpan-mac.h:71
@ SET_PHY_TX_ON
SET_PHY_TX_ON.
Definition lr-wpan-mac.h:72
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition lr-wpan-mac.h:75
@ MAC_IDLE
MAC_IDLE.
Definition lr-wpan-mac.h:66
@ MAC_INACTIVE
MAC_INACTIVE.
Definition lr-wpan-mac.h:74
@ MAC_SENDING
MAC_SENDING.
Definition lr-wpan-mac.h:68
@ MAC_ACK_PENDING
MAC_ACK_PENDING.
Definition lr-wpan-mac.h:69
@ BEACON
The Beacon transmission or reception Period.
Definition lr-wpan-mac.h:94
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition lr-wpan-mac.h:97
@ CAP
Contention Access Period.
Definition lr-wpan-mac.h:95
@ CFP
Contention Free Period.
Definition lr-wpan-mac.h:96
@ MLME_SCAN_REQ
Pending MLME-SCAN.request primitive.
@ MLME_NONE
No pending primitive.
@ MLME_START_REQ
Pending MLME-START.request primitive.
@ MLME_ASSOC_REQ
Pending MLME-ASSOCIATION.request primitive.
@ FFD
Full Functional Device (FFD).
@ INCOMING
Incoming Superframe.
@ OUTGOING
Outgoing Superframe.
@ IEEE_802_15_4_PHY_RX_ON
@ IEEE_802_15_4_PHY_TRX_OFF
@ IEEE_802_15_4_PHY_TX_ON
@ IEEE_802_15_4_PHY_SUCCESS
@ IEEE_802_15_4_PHY_UNSPECIFIED
@ TX_OPTION_GTS
TX_OPTION_GTS.
Definition lr-wpan-mac.h:55
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition lr-wpan-mac.h:54
@ TX_OPTION_INDIRECT
TX_OPTION_INDIRECT.
Definition lr-wpan-mac.h:56
@ TRANSACTION_OVERFLOW
There is no capacity to store the transaction.
@ NO_BEACON
A scan operation failed to find any network beacons.
@ UNSUPPORTED_ATTRIBUTE
SET/GET request issued with a non supported ID.
@ NO_SHORT_ADDRESS
Failure due to unallocated 16-bit short address.
@ ACCESS_DENIED
PAN access denied.
@ BEACON_LOSS
The beacon was lost following a synchronization request.
@ CHANNEL_ACCESS_FAILURE
A Tx could not take place due to activity in the CH.
@ READ_ONLY
SET/GET request issued for a read only attribute.
@ TRANSACTION_EXPIRED
The transaction expired and its information discarded.
@ SCAN_IN_PROGRESS
Scan failed because already performing another scan.
@ FRAME_TOO_LONG
Frame more than aMaxPHYPacketSize or too large for CAP or GTS.
@ INVALID_ADDRESS
Invalid source or destination address.
@ FULL_CAPACITY
PAN at capacity.
@ SUCCESS
The operation was completed successfully.
@ NO_ACK
No acknowledgment was received after macMaxFrameRetries.
@ NO_DATA
No response data were available following a request.
@ INVALID_PARAMETER
Primitive parameter not supported or out of range.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
SequenceNumber< uint8_t, int8_t > SequenceNumber8
8 bit Sequence number.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
std::ostream & operator<<(std::ostream &os, const SuperframeField &superframeField)
Stream insertion operator.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
MacStatus m_status
The status of the last MSDU transmission.
MLME-ASSOCIATE.confirm params.
Mac16Address m_assocShortAddr
The short address used in the association request.
MacStatus m_status
The status of a MLME-associate.request.
MLME-ASSOCIATE.indication params.
uint8_t lqi
The link quality indicator of the received associate request command (Not officially supported in the...
Mac64Address m_extDevAddr
The extended address of the device requesting association.
uint8_t capabilityInfo
The operational capabilities of the device requesting association.
MLME-ASSOCIATE.request params.
MLME-ASSOCIATE.response params.
MLME-BEACON-NOTIFY.indication params.
PanDescriptor m_panDescriptor
The PAN descriptor for the received beacon.
uint32_t m_sduLength
The number of octets contained in the beacon payload.
uint8_t m_bsn
The beacon sequence number.
Ptr< Packet > m_sdu
The set of octets comprising the beacon payload.
MLME-COMM-STATUS.indication params.
uint8_t m_dstAddrMode
The destination addressing mode for this primitive.
uint16_t m_panId
The PAN identifier of the device from which the frame was received or to which the frame was being se...
Mac64Address m_srcExtAddr
The extended address of the entity from which the frame causing the error originated.
MacStatus m_status
The communication status.
Mac16Address m_srcShortAddr
The short address of the entity from which the frame causing the error originated.
Mac16Address m_dstShortAddr
The short address of the device for which the frame was intended.
uint8_t m_srcAddrMode
The source addressing mode for this primitive.
Mac64Address m_dstExtAddr
The extended address of the device for which the frame was intended.
MLME-ORPHAN.indication params.
Mac64Address m_orphanAddr
The address of the orphaned device.
MacStatus m_status
The confirmation status resulting from a MLME-poll.request.
std::vector< uint8_t > m_unscannedCh
A list of channels given in the request which were not scanned (Not valid for ED scans).
uint32_t m_chPage
The channel page on which the scan was performed.
std::vector< uint8_t > m_energyDetList
A list of energy measurements, one for each channel searched during ED scan (Not valid for Active,...
MacStatus m_status
The status of the scan request.
std::vector< PanDescriptor > m_panDescList
A list of PAN descriptor, one for each beacon found (Not valid for ED and Orphan scans).
uint8_t m_resultListSize
The number of elements returned in the appropriate result list.
uint8_t m_scanType
Indicates the type of scan performed (ED,ACTIVE,PASSIVE,ORPHAN).
MacStatus m_status
The result of the request to write the PIB attribute.
MacPibAttributeIdentifier id
The id of the PIB attribute that was written.
MacStatus m_status
The status of a MLME-start.request.
MLME-SYNC-LOSS.indication params.
uint16_t m_panId
The PAN identifier with which the device lost synchronization or to which it was realigned.
MacStatus m_lossReason
The reason for the lost of synchronization.
PAN Descriptor, Table 17 IEEE 802.15.4-2011.
uint16_t m_coorPanId
The PAN ID of the coordinator as specified in the received beacon frame.
uint8_t m_logCh
The current channel number occupied by the network.
Time m_timeStamp
Beacon frame reception time.
bool m_gtsPermit
TRUE if the beacon is from the PAN coordinator that is accepting GTS requests.
Mac16Address m_coorShortAddr
The coordinator short address as specified in the coordinator address mode.
uint16_t m_superframeSpec
The superframe specification as specified in the received beacon frame.
AddressMode m_coorAddrMode
The coordinator addressing mode corresponding to the received beacon frame.
uint8_t m_linkQuality
The LQI at which the network beacon was received.
uint8_t m_logChPage
The current channel page occupied by the network.
Mac64Address m_coorExtAddr
The coordinator extended address as specified in the coordinator address mode.
std::ofstream queueSize