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"
18#include "lr-wpan-mac-header.h"
20#include "lr-wpan-mac-trailer.h"
21
22#include "ns3/double.h"
23#include "ns3/log.h"
24#include "ns3/node.h"
25#include "ns3/packet.h"
26#include "ns3/random-variable-stream.h"
27#include "ns3/simulator.h"
28#include "ns3/uinteger.h"
29
30#undef NS_LOG_APPEND_CONTEXT
31#define NS_LOG_APPEND_CONTEXT \
32 std::clog << "[" << m_shortAddress << " | " << m_macExtendedAddress << "] ";
33
34namespace ns3
35{
36namespace lrwpan
37{
38
39NS_LOG_COMPONENT_DEFINE("LrWpanMac");
41
42std::ostream&
43operator<<(std::ostream& os, const MacState& state)
44{
45 switch (state)
46 {
48 os << "MAC IDLE";
49 break;
51 os << "CSMA";
52 break;
54 os << "SENDING";
55 break;
57 os << "ACK PENDING";
58 break;
60 os << "CHANNEL_ACCESS_FAILURE";
61 break;
63 os << "CHANNEL IDLE";
64 break;
66 os << "SET PHY to TX ON";
67 break;
69 os << "MAC GTS PERIOD";
70 break;
72 os << "SUPERFRAME INACTIVE PERIOD";
73 break;
75 os << "CSMA DEFERRED TO NEXT PERIOD";
76 break;
77 }
78 return os;
79}
80
83{
84 static TypeId tid =
85 TypeId("ns3::lrwpan::LrWpanMac")
86 .AddDeprecatedName("ns3::LrWpanMac")
88 .SetGroupName("LrWpan")
89 .AddConstructor<LrWpanMac>()
90 .AddAttribute("PanId",
91 "16-bit identifier of the associated PAN",
95 .AddTraceSource("MacTxEnqueue",
96 "Trace source indicating a packet has been "
97 "enqueued in the transaction queue",
99 "ns3::Packet::TracedCallback")
100 .AddTraceSource("MacTxDequeue",
101 "Trace source indicating a packet has was "
102 "dequeued from the transaction queue",
104 "ns3::Packet::TracedCallback")
105 .AddTraceSource("MacIndTxEnqueue",
106 "Trace source indicating a packet has been "
107 "enqueued in the indirect transaction queue",
109 "ns3::Packet::TracedCallback")
110 .AddTraceSource("MacIndTxDequeue",
111 "Trace source indicating a packet has was "
112 "dequeued from the indirect transaction queue",
114 "ns3::Packet::TracedCallback")
115 .AddTraceSource("MacTx",
116 "Trace source indicating a packet has "
117 "arrived for transmission by this device",
119 "ns3::Packet::TracedCallback")
120 .AddTraceSource("MacTxOk",
121 "Trace source indicating a packet has been "
122 "successfully sent",
124 "ns3::Packet::TracedCallback")
125 .AddTraceSource("MacTxDrop",
126 "Trace source indicating a packet has been "
127 "dropped during transmission",
129 "ns3::Packet::TracedCallback")
130 .AddTraceSource("MacIndTxDrop",
131 "Trace source indicating a packet has been "
132 "dropped from the indirect transaction queue"
133 "(The pending transaction list)",
135 "ns3::Packet::TracedCallback")
136 .AddTraceSource("MacPromiscRx",
137 "A packet has been received by this device, "
138 "has been passed up from the physical layer "
139 "and is being forwarded up the local protocol stack. "
140 "This is a promiscuous trace,",
142 "ns3::Packet::TracedCallback")
143 .AddTraceSource("MacRx",
144 "A packet has been received by this device, "
145 "has been passed up from the physical layer "
146 "and is being forwarded up the local protocol stack. "
147 "This is a non-promiscuous trace,",
149 "ns3::Packet::TracedCallback")
150 .AddTraceSource("MacRxDrop",
151 "Trace source indicating a packet was received, "
152 "but dropped before being forwarded up the stack",
154 "ns3::Packet::TracedCallback")
155 .AddTraceSource("Sniffer",
156 "Trace source simulating a non-promiscuous "
157 "packet sniffer attached to the device",
159 "ns3::Packet::TracedCallback")
160 .AddTraceSource("PromiscSniffer",
161 "Trace source simulating a promiscuous "
162 "packet sniffer attached to the device",
164 "ns3::Packet::TracedCallback")
165 .AddTraceSource("MacStateValue",
166 "The state of LrWpan Mac",
168 "ns3::TracedValueCallback::LrWpanMacState")
169 .AddTraceSource("MacIncSuperframeStatus",
170 "The period status of the incoming superframe",
172 "ns3::TracedValueCallback::SuperframeState")
173 .AddTraceSource("MacOutSuperframeStatus",
174 "The period status of the outgoing superframe",
176 "ns3::TracedValueCallback::SuperframeState")
177 .AddTraceSource("MacState",
178 "The state of LrWpan Mac",
180 "ns3::lrwpan::LrWpanMac::StateTracedCallback")
181 .AddTraceSource("MacSentPkt",
182 "Trace source reporting some information about "
183 "the sent packet",
185 "ns3::lrwpan::LrWpanMac::SentTracedCallback")
186 .AddTraceSource("IfsEnd",
187 "Trace source reporting the end of an "
188 "Interframe space (IFS)",
190 "ns3::Packet::TracedCallback");
191 return tid;
192}
193
195{
196 // First set the state to a known value, call ChangeMacState to fire trace source.
198
200
203
204 m_macRxOnWhenIdle = true;
205 m_macPanId = 0xffff;
207 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
210 m_macPromiscuousMode = false;
214 m_txPkt = nullptr;
215 m_rxPkt = nullptr;
217 m_ifs = 0;
218
219 m_macLIFSPeriod = 40;
220 m_macSIFSPeriod = 12;
221
222 m_panCoor = false;
223 m_coor = false;
224 m_macBeaconOrder = 15;
226 m_macTransactionPersistenceTime = 500; // 0x01F5
228 m_macAutoRequest = true;
229
232 m_beaconTrackingOn = false;
234
238
241
242 m_maxTxQueueSize = m_txQueue.max_size();
244
246 m_macDsn = SequenceNumber8(m_uniformVar->GetInteger(0, 255));
247 m_macBsn = SequenceNumber8(m_uniformVar->GetInteger(0, 255));
250 m_shortAddress = Mac16Address("FF:FF"); // FF:FF = The address is not assigned.
251}
252
257
258void
260{
261 NS_LOG_FUNCTION(this);
262
264 {
265 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
266 }
267 else
268 {
269 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
270 }
271
273}
274
275void
277{
278 NS_LOG_FUNCTION(this);
279
280 if (m_csmaCa)
281 {
282 m_csmaCa->Dispose();
283 m_csmaCa = nullptr;
284 }
285 m_txPkt = nullptr;
286
287 for (uint32_t i = 0; i < m_txQueue.size(); i++)
288 {
289 m_txQueue[i]->txQPkt = nullptr;
290 }
291 m_txQueue.clear();
292
293 for (uint32_t i = 0; i < m_indTxQueue.size(); i++)
294 {
295 m_indTxQueue[i]->txQPkt = nullptr;
296 }
297 m_indTxQueue.clear();
298
299 m_uniformVar = nullptr;
300 m_phy = nullptr;
313
314 m_panDescriptorList.clear();
315 m_energyDetectList.clear();
316 m_unscannedChannels.clear();
317
323
325}
326
327bool
329{
330 return m_macRxOnWhenIdle;
331}
332
333void
335{
336 NS_LOG_FUNCTION(this << rxOnWhenIdle);
337 m_macRxOnWhenIdle = rxOnWhenIdle;
338
339 if (m_macState == MAC_IDLE)
340 {
342 {
343 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
344 }
345 else
346 {
347 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
348 }
349 }
350}
351
352void
357
358void
363
366{
367 return m_shortAddress;
368}
369
375
376void
378{
379 NS_LOG_FUNCTION(this << p);
380
381 McpsDataConfirmParams confirmParams;
382 confirmParams.m_msduHandle = params.m_msduHandle;
383
384 // TODO: We need a drop trace for the case that the packet is too large or the request
385 // parameters are maleformed.
386 // The current tx drop trace is not suitable, because packets dropped using this trace
387 // carry the mac header and footer, while packets being dropped here do not have them.
388
390 m_macDsn++;
391
393 {
394 // Note, this is just testing maximum theoretical frame size per the spec
395 // The frame could still be too large once headers are put on
396 // in which case the phy will reject it instead
397 NS_LOG_ERROR(this << " packet too big: " << p->GetSize());
398 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
400 {
401 m_mcpsDataConfirmCallback(confirmParams);
402 }
403 return;
404 }
405
406 if ((params.m_srcAddrMode == NO_PANID_ADDR) && (params.m_dstAddrMode == NO_PANID_ADDR))
407 {
408 NS_LOG_ERROR(this << " Can not send packet with no Address field");
409 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
411 {
412 m_mcpsDataConfirmCallback(confirmParams);
413 }
414 return;
415 }
416 switch (params.m_srcAddrMode)
417 {
418 case NO_PANID_ADDR:
419 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
420 macHdr.SetNoPanIdComp();
421 break;
423 NS_ABORT_MSG("Can not set source address type to ADDR_MODE_RESERVED. Aborting.");
424 break;
425 case SHORT_ADDR:
426 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
428 break;
429 case EXT_ADDR:
430 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
432 break;
433 default:
434 NS_LOG_ERROR(this << " Can not send packet with incorrect Source Address mode = "
435 << params.m_srcAddrMode);
436 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
438 {
439 m_mcpsDataConfirmCallback(confirmParams);
440 }
441 return;
442 }
443 switch (params.m_dstAddrMode)
444 {
445 case NO_PANID_ADDR:
446 macHdr.SetDstAddrMode(params.m_dstAddrMode);
447 macHdr.SetNoPanIdComp();
448 break;
450 NS_ABORT_MSG("Can not set destination address type to ADDR_MODE_RESERVED. Aborting.");
451 break;
452 case SHORT_ADDR:
453 macHdr.SetDstAddrMode(params.m_dstAddrMode);
454 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstAddr);
455 break;
456 case EXT_ADDR:
457 macHdr.SetDstAddrMode(params.m_dstAddrMode);
458 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstExtAddr);
459 break;
460 default:
461 NS_LOG_ERROR(this << " Can not send packet with incorrect Destination Address mode = "
462 << params.m_dstAddrMode);
463 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
465 {
466 m_mcpsDataConfirmCallback(confirmParams);
467 }
468 return;
469 }
470
471 // IEEE 802.15.4-2006 (7.5.6.1)
472 // Src & Dst PANs are identical, PAN compression is ON
473 // only the dst PAN is serialized making the MAC header 2 bytes smaller
474 if ((params.m_dstAddrMode != NO_PANID_ADDR && params.m_srcAddrMode != NO_PANID_ADDR) &&
475 (macHdr.GetDstPanId() == macHdr.GetSrcPanId()))
476 {
477 macHdr.SetPanIdComp();
478 }
479
480 macHdr.SetSecDisable();
481 // extract the first 3 bits in TxOptions
482 int b0 = params.m_txOptions & TX_OPTION_ACK;
483 int b1 = params.m_txOptions & TX_OPTION_GTS;
484 int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
485
486 if (b0 == TX_OPTION_ACK)
487 {
488 // Set AckReq bit only if the destination is not the broadcast address.
489 if (macHdr.GetDstAddrMode() == SHORT_ADDR)
490 {
491 // short address and ACK requested.
492 Mac16Address shortAddr = macHdr.GetShortDstAddr();
493 if (shortAddr.IsBroadcast() || shortAddr.IsMulticast())
494 {
495 NS_LOG_LOGIC("LrWpanMac::McpsDataRequest: requested an ACK on broadcast or "
496 "multicast destination ("
497 << shortAddr << ") - forcefully removing it.");
498 macHdr.SetNoAckReq();
499 params.m_txOptions &= ~uint8_t(TX_OPTION_ACK);
500 }
501 else
502 {
503 macHdr.SetAckReq();
504 }
505 }
506 else
507 {
508 // other address (not short) and ACK requested
509 macHdr.SetAckReq();
510 }
511 }
512 else
513 {
514 macHdr.SetNoAckReq();
515 }
516
517 if (b1 == TX_OPTION_GTS)
518 {
519 // TODO:GTS Transmission
520 }
521 else if (b2 == TX_OPTION_INDIRECT)
522 {
523 // Indirect Tx
524 // A COORDINATOR will save the packet in the pending queue and await for data
525 // requests from its associated devices. The devices are aware of pending data,
526 // from the pending bit information extracted from the received beacon.
527 // A DEVICE must be tracking beacons (MLME-SYNC.request is running) before attempting
528 // request data from the coordinator.
529
530 // Indirect Transmission can only be done by PAN coordinator or coordinators.
532 p->AddHeader(macHdr);
533
534 LrWpanMacTrailer macTrailer;
535 // Calculate FCS if the global attribute ChecksumEnabled is set.
537 {
538 macTrailer.EnableFcs(true);
539 macTrailer.SetFcs(p);
540 }
541 p->AddTrailer(macTrailer);
542
543 NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
544 // Note: The current Pending transaction list should work for indirect transmissions.
545 // However, this is not tested yet. For now, we block the use of indirect transmissions.
546 // TODO: Save packet in the Pending Transaction list.
547 // EnqueueInd (p);
548 }
549 else
550 {
551 // Direct Tx
552 // From this point the packet will be pushed to a Tx queue and immediately
553 // use a slotted (beacon-enabled) or unslotted (nonbeacon-enabled) version of CSMA/CA
554 // before sending the packet, depending on whether it has previously
555 // received a valid beacon or not.
556
557 p->AddHeader(macHdr);
558
559 LrWpanMacTrailer macTrailer;
560 // Calculate FCS if the global attribute ChecksumEnabled is set.
562 {
563 macTrailer.EnableFcs(true);
564 macTrailer.SetFcs(p);
565 }
566 p->AddTrailer(macTrailer);
567
569 txQElement->txQMsduHandle = params.m_msduHandle;
570 txQElement->txQPkt = p;
571 EnqueueTxQElement(txQElement);
572 CheckQueue();
573 }
574}
575
576void
578{
579 NS_LOG_FUNCTION(this);
581
582 MlmeStartConfirmParams confirmParams;
583
584 if (GetShortAddress() == Mac16Address("ff:ff"))
585 {
586 NS_LOG_ERROR(this << " Invalid MAC short address");
589 {
590 m_mlmeStartConfirmCallback(confirmParams);
591 }
592 return;
593 }
594
595 if ((params.m_bcnOrd > 15) || (params.m_sfrmOrd > params.m_bcnOrd))
596 {
599 {
600 m_mlmeStartConfirmCallback(confirmParams);
601 }
602 NS_LOG_ERROR(this << "Incorrect superframe order or beacon order.");
603 return;
604 }
605
606 // Mark primitive as pending and save the start params while the new page and channel is set.
608 m_startParams = params;
609
611 pibAttr->phyCurrentPage = m_startParams.m_logChPage;
612 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
613}
614
615void
617{
618 NS_LOG_FUNCTION(this);
619
620 MlmeScanConfirmParams confirmParams;
621 confirmParams.m_scanType = params.m_scanType;
622 confirmParams.m_chPage = params.m_chPage;
623
625 {
627 {
629 m_mlmeScanConfirmCallback(confirmParams);
630 }
631 NS_LOG_ERROR(this << " A channel scan is already in progress");
632 return;
633 }
634
635 if (params.m_scanDuration > 14 || params.m_scanType > MLMESCAN_ORPHAN)
636 {
638 {
640 m_mlmeScanConfirmCallback(confirmParams);
641 }
642 NS_LOG_ERROR(this << "Invalid scan duration or unsupported scan type");
643 return;
644 }
645 // Temporary store macPanId and set macPanId to 0xFFFF to accept all beacons.
647 m_macPanId = 0xFFFF;
648
649 m_panDescriptorList.clear();
650 m_energyDetectList.clear();
651 m_unscannedChannels.clear();
652
653 // TODO: stop beacon transmission
654
655 // Cancel any ongoing CSMA/CA operations and set to unslotted mode for scan
656 m_csmaCa->Cancel();
662 m_csmaCa->SetUnSlottedCsmaCa();
663
665
666 // Mark primitive as pending and save the scan params while the new page and/or channel is set.
667 m_scanParams = params;
669
671 pibAttr->phyCurrentPage = params.m_chPage;
672 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
673}
674
675void
677{
678 NS_LOG_FUNCTION(this);
679
680 // Association is typically preceded by beacon reception and a MLME-SCAN.request, therefore,
681 // the values of the Associate.request params usually come from the information
682 // obtained from those operations.
684 m_associateParams = params;
685 m_ignoreDataCmdAck = false;
686
687 bool invalidRequest = false;
688
689 if (params.m_coordPanId == 0xffff)
690 {
691 invalidRequest = true;
692 }
693
694 if (!invalidRequest && params.m_coordAddrMode == SHORT_ADDR)
695 {
696 if (params.m_coordShortAddr == Mac16Address("ff:ff") ||
697 params.m_coordShortAddr == Mac16Address("ff:fe"))
698 {
699 invalidRequest = true;
700 }
701 }
702 else if (!invalidRequest && params.m_coordAddrMode == EXT_ADDR)
703 {
704 if (params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ff") ||
705 params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed"))
706 {
707 invalidRequest = true;
708 }
709 }
710
711 if (invalidRequest)
712 {
715 NS_LOG_ERROR(this << " Invalid PAN id in Association request");
717 {
718 MlmeAssociateConfirmParams confirmParams;
719 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
721 m_mlmeAssociateConfirmCallback(confirmParams);
722 }
723 }
724 else
725 {
727 pibAttr->phyCurrentPage = params.m_chPage;
728 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
729 }
730}
731
732void
734{
735 // the primitive is no longer pending (channel & page are set)
737 // As described in IEEE 802.15.4-2011 (Section 5.1.3.1)
740 {
742 }
743 else
744 {
747 }
748
750}
751
752void
754{
755 // Associate Short Address (m_assocShortAddr)
756 // FF:FF = Association Request failed
757 // FF:FE = The association request is accepted, but the device should use its extended address
758 // Other = The assigned short address by the coordinator
759
760 NS_LOG_FUNCTION(this);
761
763 m_macDsn++;
764 LrWpanMacTrailer macTrailer;
765 Ptr<Packet> commandPacket = Create<Packet>();
766
767 // Mac header Assoc. Response Comm. See 802.15.4-2011 (Section 5.3.2.1)
770 macHdr.SetPanIdComp();
771 macHdr.SetDstAddrFields(m_macPanId, params.m_extDevAddr);
772 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
773
775 macPayload.SetShortAddr(params.m_assocShortAddr);
776 macPayload.SetAssociationStatus(static_cast<uint8_t>(params.m_status));
777
778 macHdr.SetSecDisable();
779 macHdr.SetAckReq();
780
781 commandPacket->AddHeader(macPayload);
782 commandPacket->AddHeader(macHdr);
783
784 // Calculate FCS if the global attribute ChecksumEnabled is set.
786 {
787 macTrailer.EnableFcs(true);
788 macTrailer.SetFcs(commandPacket);
789 }
790
791 commandPacket->AddTrailer(macTrailer);
792
793 // Save packet in the Pending Transaction list.
794 EnqueueInd(commandPacket);
795}
796
797void
799{
800 NS_LOG_FUNCTION(this);
801 // Mac header Coordinator realigment Command
802 // See 802.15.4-2011 (Section 6.2.7.2)
804 m_macDsn++;
805 LrWpanMacTrailer macTrailer;
806 Ptr<Packet> commandPacket = Create<Packet>();
807 macHdr.SetPanIdComp();
809 macHdr.SetDstAddrFields(0xffff, params.m_orphanAddr);
810
813 macHdr.SetSrcAddrFields(m_macPanId, Mac16Address("FF:FF"));
814
815 macHdr.SetFrameVer(0x01);
816 macHdr.SetSecDisable();
817 macHdr.SetAckReq();
818
820 macPayload.SetPanId(m_macPanId);
822 macPayload.SetChannel(m_phy->GetCurrentChannelNum());
823 macPayload.SetPage(m_phy->GetCurrentPage());
824
825 if (params.m_assocMember)
826 {
827 // The orphan device was associated with the coordinator
828
829 // Either FF:FE for extended address mode
830 // or the short address assigned by the coord.
831 macPayload.SetShortAddr(params.m_shortAddr);
832 }
833 else
834 {
835 // The orphan device was NOT associated with the coordinator
836 macPayload.SetShortAddr(Mac16Address("FF:FF"));
837 }
838
839 commandPacket->AddHeader(macPayload);
840 commandPacket->AddHeader(macHdr);
841
842 // Calculate FCS if the global attribute ChecksumEnabled is set.
844 {
845 macTrailer.EnableFcs(true);
846 macTrailer.SetFcs(commandPacket);
847 }
848
849 commandPacket->AddTrailer(macTrailer);
850
852 txQElement->txQPkt = commandPacket;
853 EnqueueTxQElement(txQElement);
854 CheckQueue();
855}
856
857void
859{
860 NS_LOG_FUNCTION(this);
861 NS_ASSERT(params.m_logCh <= 26 && m_macPanId != 0xffff);
862
863 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
864 // change phy current logical channel
866 pibAttr->phyCurrentChannel = params.m_logCh;
867 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
868
869 // Enable Phy receiver
870 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
871
872 uint64_t searchSymbols;
873 Time searchBeaconTime;
874
876 {
878 }
879
880 if (params.m_trackBcn)
881 {
883 // search for a beacon for a time = incomingSuperframe symbols + 960 symbols
884 searchSymbols =
886 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
887 m_beaconTrackingOn = true;
889 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
890 }
891 else
892 {
893 m_beaconTrackingOn = false;
894 }
895}
896
897void
899{
900 NS_LOG_FUNCTION(this);
901
903 m_macBsn++;
904
906
907 Ptr<Packet> beaconPacket = Create<Packet>();
908 // TODO: complete poll request (part of indirect transmissions)
909 NS_FATAL_ERROR(this << " Poll request currently not supported");
910}
911
912void
914{
915 MlmeSetConfirmParams confirmParams;
916 confirmParams.m_status = MacStatus::SUCCESS;
917
918 switch (id)
919 {
921 m_macAssociationPermit = attribute->macAssociationPermit;
922 break;
923 case macBeaconPayload:
924 if (attribute->macBeaconPayload.size() > aMaxBeaconPayloadLength)
925 {
927 }
928 else
929 {
930 m_macBeaconPayload = attribute->macBeaconPayload;
931 }
932 break;
934 if (attribute->macBeaconPayloadLength > aMaxBeaconPayloadLength)
935 {
937 }
938 else
939 {
940 m_macBeaconPayloadLength = attribute->macBeaconPayloadLength;
941 }
942 break;
943 case macShortAddress:
944 m_shortAddress = attribute->macShortAddress;
945 break;
947 confirmParams.m_status = MacStatus::READ_ONLY;
948 break;
949 case macPanId:
951 break;
953 m_macPromiscuousMode = attribute->macPromiscuousMode;
954 break;
955 case macRxOnWhenIdle:
956 m_macRxOnWhenIdle = attribute->macRxOnWhenIdle;
957 break;
958 case pCurrentChannel: {
960 pibAttr->phyCurrentChannel = attribute->pCurrentChannel;
961 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
962 break;
963 }
964 case pCurrentPage: {
966 pibAttr->phyCurrentPage = attribute->pCurrentPage;
967 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
968 break;
969 }
970 default:
971 // TODO: Add support for setting other attributes
973 break;
974 }
975
977 {
978 confirmParams.id = id;
979 m_mlmeSetConfirmCallback(confirmParams);
980 }
981}
982
983void
985{
988
989 switch (id)
990 {
992 attributes->macAssociationPermit = m_macAssociationPermit;
993 break;
994 case macBeaconPayload:
995 attributes->macBeaconPayload = m_macBeaconPayload;
996 break;
998 attributes->macBeaconPayloadLength = m_macBeaconPayloadLength;
999 break;
1000 case macPromiscuousMode:
1001 attributes->macPromiscuousMode = m_macPromiscuousMode;
1002 break;
1003 case macRxOnWhenIdle:
1004 attributes->macRxOnWhenIdle = m_macRxOnWhenIdle;
1005 break;
1006 case macShortAddress:
1007 attributes->macShortAddress = m_shortAddress;
1008 break;
1009 case macExtendedAddress:
1010 attributes->macExtendedAddress = m_macExtendedAddress;
1011 break;
1012 case macPanId:
1013 attributes->macPanId = m_macPanId;
1014 break;
1015 case pCurrentChannel:
1016 attributes->pCurrentChannel = m_phy->GetCurrentChannelNum();
1017 break;
1018 case pCurrentPage:
1019 attributes->pCurrentPage = m_phy->GetCurrentPage();
1020 break;
1021 default:
1023 break;
1024 }
1025
1027 {
1028 m_mlmeGetConfirmCallback(status, id, attributes);
1029 }
1030}
1031
1032void
1034{
1035 NS_LOG_FUNCTION(this);
1036
1037 // Strip the MAC header and MAC trailer
1038 LrWpanMacTrailer receivedMacTrailer;
1039 p->RemoveTrailer(receivedMacTrailer);
1040
1041 LrWpanMacHeader receivedMacHdr;
1042 p->RemoveHeader(receivedMacHdr);
1043
1045 params.m_dsn = receivedMacHdr.GetSeqNum();
1046 params.m_mpduLinkQuality = lqi;
1047 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
1048 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
1049
1050 switch (params.m_srcAddrMode)
1051 {
1052 case SHORT_ADDR:
1053 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
1054 break;
1055 case EXT_ADDR:
1056 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
1057 break;
1058 default:
1059 break;
1060 }
1061
1062 params.m_dstPanId = receivedMacHdr.GetDstPanId();
1063 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
1064
1065 switch (params.m_dstAddrMode)
1066 {
1067 case SHORT_ADDR:
1068 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
1069 break;
1070 case EXT_ADDR:
1071 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
1072 break;
1073 default:
1074 break;
1075 }
1076
1077 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
1078 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
1079 {
1080 NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstAddr << "]");
1081 }
1082 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
1083 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
1084 {
1085 NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to [" << params.m_dstExtAddr
1086 << "]");
1087 }
1088 else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
1089 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
1090 {
1091 NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstExtAddr << "]");
1092 }
1093 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
1094 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
1095 {
1096 NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to [" << params.m_dstAddr << "]");
1097 }
1098
1099 // TODO: Fix here, this should trigger different Indication Callbacks
1100 // depending the type of frame received (data,command, beacon)
1102 {
1103 NS_LOG_DEBUG("promiscuous mode, forwarding up");
1105 }
1106}
1107
1108void
1110{
1111 NS_LOG_FUNCTION(this);
1113
1114 m_macBsn++;
1115
1116 Ptr<Packet> beaconPacket;
1117 if (m_macBeaconPayload.empty())
1118 {
1119 beaconPacket = Create<Packet>();
1120 }
1121 else
1122 {
1123 // Extract the octets from m_macBeaconPayload and place them in a packet
1124 beaconPacket = Create<Packet>(m_macBeaconPayload.data(), m_macBeaconPayload.size());
1125 }
1126
1129 macHdr.SetDstAddrFields(GetPanId(), Mac16Address("ff:ff"));
1130
1131 // see IEEE 802.15.4-2011 Section 5.1.2.4
1132 if (GetShortAddress() == Mac16Address("ff:fe"))
1133 {
1136 }
1137 else
1138 {
1141 }
1142
1143 macHdr.SetSecDisable();
1144 macHdr.SetNoAckReq();
1145
1146 BeaconPayloadHeader macPayload;
1148 macPayload.SetGtsFields(GetGtsFields());
1150
1151 beaconPacket->AddHeader(macPayload);
1152 beaconPacket->AddHeader(macHdr);
1153
1154 // Calculate FCS if the global attribute ChecksumEnabled is set.
1155 LrWpanMacTrailer macTrailer;
1157 {
1158 macTrailer.EnableFcs(true);
1159 macTrailer.SetFcs(beaconPacket);
1160 }
1161
1162 beaconPacket->AddTrailer(macTrailer);
1163
1164 if (m_csmaCa->IsSlottedCsmaCa())
1165 {
1166 // Beacon in beacon-enabled mode
1167 // Transmit beacon immediately (i.e. Without CSMA/CA)
1168 m_txPkt = beaconPacket;
1170 NS_LOG_DEBUG("Outgoing superframe Active Portion (Beacon + CAP + CFP): "
1171 << m_superframeDuration << " symbols");
1172
1174 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
1175 }
1176 else
1177 {
1178 // Beacon as a result of a beacon request
1179 // The beacon shall be transmitted using CSMA/CA
1180 // IEEE 802.15.4-2011 (Section 5.1.2.1.2)
1182 txQElement->txQPkt = beaconPacket;
1183 EnqueueTxQElement(txQElement);
1184 CheckQueue();
1185 }
1186}
1187
1188void
1190{
1191 NS_LOG_FUNCTION(this);
1192
1194 m_macDsn++;
1195 LrWpanMacTrailer macTrailer;
1196 Ptr<Packet> commandPacket = Create<Packet>();
1197
1198 // Beacon Request Command Mac header values See IEEE 802.15.4-2011 (Section 5.3.7)
1199 macHdr.SetNoPanIdComp();
1202
1203 // Not associated PAN, broadcast dst address
1204 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1205
1206 macHdr.SetSecDisable();
1207 macHdr.SetNoAckReq();
1208
1209 CommandPayloadHeader macPayload;
1211
1212 commandPacket->AddHeader(macPayload);
1213 commandPacket->AddHeader(macHdr);
1214
1215 // Calculate FCS if the global attribute ChecksumEnabled is set.
1217 {
1218 macTrailer.EnableFcs(true);
1219 macTrailer.SetFcs(commandPacket);
1220 }
1221
1222 commandPacket->AddTrailer(macTrailer);
1223
1225 txQElement->txQPkt = commandPacket;
1226 EnqueueTxQElement(txQElement);
1227 CheckQueue();
1228}
1229
1230void
1232{
1234 m_macDsn++;
1235 LrWpanMacTrailer macTrailer;
1236 Ptr<Packet> commandPacket = Create<Packet>();
1237
1238 // See IEEE 802.15.4-2011 (5.3.6)
1239 macHdr.SetPanIdComp();
1240
1242 macHdr.SetSrcAddrFields(0xFFFF, GetExtendedAddress());
1243
1245 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1246
1247 macHdr.SetSecDisable();
1248 macHdr.SetNoAckReq();
1249
1250 CommandPayloadHeader macPayload;
1252
1253 commandPacket->AddHeader(macPayload);
1254 commandPacket->AddHeader(macHdr);
1255
1256 // Calculate FCS if the global attribute ChecksumEnabled is set.
1258 {
1259 macTrailer.EnableFcs(true);
1260 macTrailer.SetFcs(commandPacket);
1261 }
1262
1263 commandPacket->AddTrailer(macTrailer);
1264
1266 txQElement->txQPkt = commandPacket;
1267 EnqueueTxQElement(txQElement);
1268 CheckQueue();
1269}
1270
1271void
1273{
1274 NS_LOG_FUNCTION(this);
1275
1277 m_macDsn++;
1278 LrWpanMacTrailer macTrailer;
1279 Ptr<Packet> commandPacket = Create<Packet>();
1280
1281 // Assoc. Req. Comm. Mac header values See IEEE 802.15.4-2011 (Section 5.3.1.1)
1283 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
1284
1286 {
1289 }
1290 else
1291 {
1294 }
1295
1296 macHdr.SetSecDisable();
1297 macHdr.SetAckReq();
1298
1301
1302 commandPacket->AddHeader(macPayload);
1303 commandPacket->AddHeader(macHdr);
1304
1305 // Calculate FCS if the global attribute ChecksumEnabled is set.
1307 {
1308 macTrailer.EnableFcs(true);
1309 macTrailer.SetFcs(commandPacket);
1310 }
1311
1312 commandPacket->AddTrailer(macTrailer);
1313
1315 txQElement->txQPkt = commandPacket;
1316 EnqueueTxQElement(txQElement);
1317 CheckQueue();
1318}
1319
1320void
1322{
1323 // See IEEE 802.15.4-2011 (Section 5.3.5)
1324 // This command can be sent for 3 different situations:
1325 // a) In response to a beacon indicating that there is data for the device.
1326 // b) Triggered by MLME-POLL.request.
1327 // c) To follow an ACK of an Association Request command and continue the associate process.
1328
1329 // TODO: Implementation of a) and b) will be done when Indirect transmissions are fully
1330 // supported.
1331 // for now, only case c) is considered.
1332
1333 NS_LOG_FUNCTION(this);
1334
1336 m_macDsn++;
1337 LrWpanMacTrailer macTrailer;
1338 Ptr<Packet> commandPacket = Create<Packet>();
1339
1340 // Mac Header values (Section 5.3.5)
1342 macHdr.SetSrcAddrFields(0xffff, m_macExtendedAddress);
1343
1344 if (m_macCoordShortAddress == Mac16Address("ff:fe"))
1345 {
1348 }
1349 else
1350 {
1353 }
1354
1355 macHdr.SetSecDisable();
1356 macHdr.SetAckReq();
1357
1359
1360 commandPacket->AddHeader(macPayload);
1361 commandPacket->AddHeader(macHdr);
1362
1363 // Calculate FCS if the global attribute ChecksumEnabled is set.
1365 {
1366 macTrailer.EnableFcs(true);
1367 macTrailer.SetFcs(commandPacket);
1368 }
1369
1370 commandPacket->AddTrailer(macTrailer);
1371
1372 // Set the Command packet to be transmitted
1374 txQElement->txQPkt = commandPacket;
1375 EnqueueTxQElement(txQElement);
1376 CheckQueue();
1377}
1378
1379void
1381{
1382 LrWpanMacHeader receivedMacHdr;
1383 rxDataReqPkt->RemoveHeader(receivedMacHdr);
1384 CommandPayloadHeader receivedMacPayload;
1385 rxDataReqPkt->RemoveHeader(receivedMacPayload);
1386
1388
1390 bool elementFound;
1391 elementFound = DequeueInd(receivedMacHdr.GetExtSrcAddr(), indTxQElement);
1392 if (elementFound)
1393 {
1395 txQElement->txQPkt = indTxQElement->txQPkt;
1396 m_txQueue.emplace_back(txQElement);
1397 }
1398 else
1399 {
1400 NS_LOG_DEBUG("Requested element not found in pending list");
1401 }
1402}
1403
1404void
1406{
1407 // Association response command was not received, return to default values.
1408 m_macPanId = 0xffff;
1410 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1411
1413 {
1414 MlmeAssociateConfirmParams confirmParams;
1415 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
1416 confirmParams.m_status = MacStatus::NO_DATA;
1417 m_mlmeAssociateConfirmCallback(confirmParams);
1418 }
1419}
1420
1421void
1423{
1424 NS_LOG_FUNCTION(this);
1425 // The primitive is no longer pending (Channel & Page have been set)
1427
1428 if (m_startParams.m_coorRealgn) // Coordinator Realignment
1429 {
1430 // TODO: Send realignment request command frame in CSMA/CA
1431 NS_LOG_ERROR(this << " Coordinator realignment request not supported");
1432 return;
1433 }
1434 else
1435 {
1437 {
1438 m_panCoor = true;
1439 }
1440
1441 m_coor = true;
1443
1444 NS_ASSERT(m_startParams.m_PanId != 0xffff);
1445
1447 if (m_macBeaconOrder == 15)
1448 {
1449 // Non-beacon enabled PAN
1450 // Cancel any ongoing events and CSMA-CA process
1452 m_fnlCapSlot = 15;
1453 m_beaconInterval = 0;
1454
1455 m_csmaCa->Cancel();
1464
1465 m_csmaCa->SetUnSlottedCsmaCa();
1466
1468 {
1469 MlmeStartConfirmParams confirmParams;
1470 confirmParams.m_status = MacStatus::SUCCESS;
1471 m_mlmeStartConfirmCallback(confirmParams);
1472 }
1473
1474 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
1475 }
1476 else
1477 {
1479 m_csmaCa->SetBatteryLifeExtension(m_startParams.m_battLifeExt);
1480
1481 m_csmaCa->SetSlottedCsmaCa();
1482
1483 // TODO: Calculate the real Final CAP slot (requires GTS implementation)
1484 // FinalCapSlot = Superframe duration slots - CFP slots.
1485 // In the current implementation the value of the final cap slot is equal to
1486 // the total number of possible slots in the superframe (15).
1487 m_fnlCapSlot = 15;
1488
1491 m_superframeDuration = (static_cast<uint32_t>(1 << m_macSuperframeOrder)) *
1493
1494 // TODO: change the beacon sending according to the startTime parameter (if not PAN
1495 // coordinator)
1496
1498 }
1499 }
1500}
1501
1502void
1504{
1505 NS_LOG_FUNCTION(this);
1506
1508
1509 bool channelFound = false;
1510
1511 for (int i = m_channelScanIndex; i <= 26; i++)
1512 {
1514 {
1515 channelFound = true;
1516 break;
1517 }
1519 }
1520
1521 if (channelFound)
1522 {
1523 // Switch to the next channel in the list and restart scan
1525 pibAttr->phyCurrentChannel = m_channelScanIndex;
1526 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1527 }
1528 else
1529 {
1530 // All channels in the list scan completed.
1531 // Return variables to the values before the scan and return the status to the next layer.
1533 m_macPanIdScan = 0;
1534
1535 // TODO: restart beacon transmissions that were active before the beginning of the scan
1536 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1537 MlmeScanConfirmParams confirmParams;
1538 confirmParams.m_chPage = m_scanParams.m_chPage;
1539 confirmParams.m_scanType = m_scanParams.m_scanType;
1540 confirmParams.m_energyDetList = {};
1541 confirmParams.m_unscannedCh = m_unscannedChannels;
1542 confirmParams.m_resultListSize = m_panDescriptorList.size();
1543
1544 // See IEEE 802.15.4-2011, Table 31 (panDescriptorList value on macAutoRequest)
1545 // and Section 6.2.10.2
1546 switch (confirmParams.m_scanType)
1547 {
1548 case MLMESCAN_PASSIVE:
1549 if (m_macAutoRequest)
1550 {
1551 confirmParams.m_panDescList = m_panDescriptorList;
1552 }
1553 confirmParams.m_status = MacStatus::SUCCESS;
1554 break;
1555 case MLMESCAN_ACTIVE:
1556 if (m_panDescriptorList.empty())
1557 {
1558 confirmParams.m_status = MacStatus::NO_BEACON;
1559 }
1560 else
1561 {
1562 if (m_macAutoRequest)
1563 {
1564 confirmParams.m_panDescList = m_panDescriptorList;
1565 }
1566 confirmParams.m_status = MacStatus::SUCCESS;
1567 }
1568 break;
1569 case MLMESCAN_ORPHAN:
1570 confirmParams.m_panDescList = {};
1571 confirmParams.m_status = MacStatus::NO_BEACON;
1572 confirmParams.m_resultListSize = 0;
1573 // The device lost track of the coordinator and was unable
1574 // to locate it, disassociate from the network.
1575 m_macPanId = 0xffff;
1576 m_shortAddress = Mac16Address("FF:FF");
1578 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1579 break;
1580 default:
1581 NS_LOG_ERROR(this << " Invalid scan type");
1582 }
1583
1586 m_scanParams = {};
1587
1589 {
1590 m_mlmeScanConfirmCallback(confirmParams);
1591 }
1592 }
1593}
1594
1595void
1597{
1598 NS_LOG_FUNCTION(this);
1599 // Add the results of channel energy scan to the detectList
1601 m_maxEnergyLevel = 0;
1602
1604
1605 bool channelFound = false;
1606 for (int i = m_channelScanIndex; i <= 26; i++)
1607 {
1609 {
1610 channelFound = true;
1611 break;
1612 }
1614 }
1615
1616 if (channelFound)
1617 {
1618 // switch to the next channel in the list and restart scan
1620 pibAttr->phyCurrentChannel = m_channelScanIndex;
1621 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1622 }
1623 else
1624 {
1625 // Scan on all channels on the list completed
1626 // Return to the MAC values previous to start of the first scan.
1628 m_macPanIdScan = 0;
1629
1630 // TODO: restart beacon transmissions that were active before the beginning of the scan
1631 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1632
1633 // All channels scanned, report success
1634 MlmeScanConfirmParams confirmParams;
1635 confirmParams.m_status = MacStatus::SUCCESS;
1636 confirmParams.m_chPage = m_phy->GetCurrentPage();
1637 confirmParams.m_scanType = m_scanParams.m_scanType;
1638 confirmParams.m_energyDetList = m_energyDetectList;
1639 confirmParams.m_resultListSize = m_energyDetectList.size();
1640
1643 m_scanParams = {};
1644
1646 {
1647 m_mlmeScanConfirmCallback(confirmParams);
1648 }
1649 }
1650}
1651
1652void
1654{
1655 uint32_t activeSlot;
1656 uint64_t capDuration;
1657 Time endCapTime;
1658 uint64_t symbolRate;
1659
1660 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1661
1662 if (superframeType == OUTGOING)
1663 {
1665 activeSlot = m_superframeDuration / 16;
1666 capDuration = activeSlot * (m_fnlCapSlot + 1);
1667 endCapTime = Seconds((double)capDuration / symbolRate);
1668 // Obtain the end of the CAP by adjust the time it took to send the beacon
1669 endCapTime -= (Simulator::Now() - m_macBeaconTxTime);
1670
1671 NS_LOG_DEBUG("Outgoing superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1672 << " symbols (" << endCapTime.As(Time::S)
1673 << ")");
1674 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1675
1676 m_capEvent =
1678 }
1679 else
1680 {
1682 activeSlot = m_incomingSuperframeDuration / 16;
1683 capDuration = activeSlot * (m_incomingFnlCapSlot + 1);
1684 endCapTime = Seconds((double)capDuration / symbolRate);
1685 // Obtain the end of the CAP by adjust the time it took to receive the beacon
1686 endCapTime -= (Simulator::Now() - m_macBeaconRxTime);
1687
1688 NS_LOG_DEBUG("Incoming superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1689 << " symbols (" << endCapTime.As(Time::S)
1690 << ")");
1691 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1692
1693 m_capEvent =
1695 }
1696
1697 CheckQueue();
1698}
1699
1700void
1702{
1703 uint32_t activeSlot;
1704 uint64_t cfpDuration;
1705 Time endCfpTime;
1706 uint64_t symbolRate;
1707
1708 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1709
1710 if (superframeType == INCOMING)
1711 {
1712 activeSlot = m_incomingSuperframeDuration / 16;
1713 cfpDuration = activeSlot * (15 - m_incomingFnlCapSlot);
1714 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1715 if (cfpDuration > 0)
1716 {
1718 }
1719
1720 NS_LOG_DEBUG("Incoming superframe CFP duration " << cfpDuration << " symbols ("
1721 << endCfpTime.As(Time::S) << ")");
1722
1725 this,
1727 }
1728 else
1729 {
1730 activeSlot = m_superframeDuration / 16;
1731 cfpDuration = activeSlot * (15 - m_fnlCapSlot);
1732 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1733
1734 if (cfpDuration > 0)
1735 {
1737 }
1738
1739 NS_LOG_DEBUG("Outgoing superframe CFP duration " << cfpDuration << " symbols ("
1740 << endCfpTime.As(Time::S) << ")");
1741
1742 m_cfpEvent = Simulator::Schedule(endCfpTime,
1744 this,
1746 }
1747 // TODO: Start transmit or receive GTS here.
1748}
1749
1750void
1752{
1753 uint64_t inactiveDuration;
1754 Time endInactiveTime;
1755 uint64_t symbolRate;
1756
1757 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1758
1759 if (superframeType == INCOMING)
1760 {
1762 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1763
1764 if (inactiveDuration > 0)
1765 {
1767 }
1768
1769 NS_LOG_DEBUG("Incoming superframe Inactive Portion duration "
1770 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1771 m_beaconEvent = Simulator::Schedule(endInactiveTime, &LrWpanMac::AwaitBeacon, this);
1772 }
1773 else
1774 {
1775 inactiveDuration = m_beaconInterval - m_superframeDuration;
1776 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1777
1778 if (inactiveDuration > 0)
1779 {
1781 }
1782
1783 NS_LOG_DEBUG("Outgoing superframe Inactive Portion duration "
1784 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1786 }
1787}
1788
1789void
1791{
1793
1794 // TODO: If the device waits more than the expected time to receive the beacon (wait = 46
1795 // symbols for default beacon size)
1796 // it should continue with the start of the incoming CAP even if it did not receive the
1797 // beacon. At the moment, the start of the incoming CAP is only triggered if the beacon is
1798 // received. See MLME-SyncLoss for details.
1799}
1800
1801void
1803{
1804 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1805
1807 {
1808 MlmeSyncLossIndicationParams syncLossParams;
1809 // syncLossParams.m_logCh =
1810 syncLossParams.m_lossReason = MacStatus::BEACON_LOSS;
1811 syncLossParams.m_panId = m_macPanId;
1812 m_mlmeSyncLossIndicationCallback(syncLossParams);
1813
1814 m_beaconTrackingOn = false;
1815 m_numLostBeacons = 0;
1816 }
1817 else
1818 {
1820
1821 // Search for one more beacon
1822 uint64_t searchSymbols;
1823 Time searchBeaconTime;
1824 searchSymbols =
1826 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
1828 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
1829 }
1830}
1831
1832void
1834{
1835 NS_LOG_FUNCTION(this << lqi << p);
1836 // The received beacon size in symbols
1837 // Beacon = Sync Header (SHR)[5 bytes] +
1838 // PHY header (PHR) [1 byte] +
1839 // PSDU (MAC header + beacon payload) [default 17 bytes]
1840 m_rxBeaconSymbols = m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
1841 (p->GetSize() * m_phy->GetPhySymbolsPerOctet());
1842
1843 // The start of Rx beacon time and start of the Incoming superframe Active Period
1844 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1845 m_macBeaconRxTime = Simulator::Now() - Seconds(double(m_rxBeaconSymbols) / symbolRate);
1846
1847 NS_LOG_DEBUG("Beacon Received; forwarding up (m_macBeaconRxTime: "
1848 << m_macBeaconRxTime.As(Time::S) << ")");
1849
1850 // Strip the MAC header, the trailer and the Beacon Payload
1851 LrWpanMacTrailer receivedMacTrailer;
1852 p->RemoveTrailer(receivedMacTrailer);
1853
1854 LrWpanMacHeader receivedMacHdr;
1855 p->RemoveHeader(receivedMacHdr);
1856
1857 BeaconPayloadHeader receivedMacPayload;
1858 p->RemoveHeader(receivedMacPayload);
1859
1860 // Fill the PAN descriptor
1861 PanDescriptor panDescriptor;
1862
1863 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR)
1864 {
1865 panDescriptor.m_coorAddrMode = SHORT_ADDR;
1866 panDescriptor.m_coorShortAddr = receivedMacHdr.GetShortSrcAddr();
1867 }
1868 else
1869 {
1870 panDescriptor.m_coorAddrMode = EXT_ADDR;
1871 panDescriptor.m_coorExtAddr = receivedMacHdr.GetExtSrcAddr();
1872 }
1873
1874 panDescriptor.m_coorPanId = receivedMacHdr.GetSrcPanId();
1875 panDescriptor.m_gtsPermit = receivedMacPayload.GetGtsFields().GetGtsPermit();
1876 panDescriptor.m_linkQuality = lqi;
1877 panDescriptor.m_logChPage = m_phy->GetCurrentPage();
1878 panDescriptor.m_logCh = m_phy->GetCurrentChannelNum();
1879 panDescriptor.m_superframeSpec = receivedMacPayload.GetSuperframeSpecField();
1880 panDescriptor.m_timeStamp = m_macBeaconRxTime;
1881
1882 // Process beacon when device belongs to a PAN (associated device)
1883 if (!m_scanEvent.IsPending() && m_macPanId == receivedMacHdr.GetDstPanId())
1884 {
1885 // We need to make sure to cancel any possible ongoing unslotted CSMA/CA
1886 // operations when receiving a beacon (e.g. Those taking place at the
1887 // beginning of an Association).
1888 m_csmaCa->Cancel();
1889
1890 SuperframeField incomingSuperframe(receivedMacPayload.GetSuperframeSpecField());
1891
1892 m_incomingBeaconOrder = incomingSuperframe.GetBeaconOrder();
1893 m_incomingSuperframeOrder = incomingSuperframe.GetFrameOrder();
1894 m_incomingFnlCapSlot = incomingSuperframe.GetFinalCapSlot();
1895
1896 if (m_incomingBeaconOrder < 15)
1897 {
1898 // Start Beacon-enabled mode
1899 m_csmaCa->SetSlottedCsmaCa();
1903 (static_cast<uint32_t>(1 << m_incomingSuperframeOrder));
1904
1905 if (incomingSuperframe.IsBattLifeExt())
1906 {
1907 m_csmaCa->SetBatteryLifeExtension(true);
1908 }
1909 else
1910 {
1911 m_csmaCa->SetBatteryLifeExtension(false);
1912 }
1913
1914 // TODO: get Incoming frame GTS Fields here
1915
1916 // Begin CAP on the current device using info from
1917 // the Incoming superframe
1918 NS_LOG_DEBUG("Incoming superframe Active Portion "
1919 << "(Beacon + CAP + CFP): " << m_incomingSuperframeDuration << " symbols");
1920
1923 }
1924 else
1925 {
1926 // Start non-beacon enabled mode
1927 m_csmaCa->SetUnSlottedCsmaCa();
1928 }
1929
1931 }
1932 else if (!m_scanEvent.IsPending() && m_macPanId == 0xFFFF)
1933 {
1934 NS_LOG_DEBUG(this << " Device not associated, cannot process beacon");
1935 }
1936
1937 if (m_macAutoRequest)
1938 {
1939 if (p->GetSize() > 0)
1940 {
1942 {
1943 // The beacon contains payload, send the beacon notification.
1945 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
1946 beaconParams.m_panDescriptor = panDescriptor;
1947 beaconParams.m_sduLength = p->GetSize();
1948 beaconParams.m_sdu = p;
1950 }
1951 }
1952
1953 if (m_scanEvent.IsPending())
1954 {
1955 // Channel scanning is taking place, save only unique PAN descriptors
1956 bool descriptorExists = false;
1957
1958 for (const auto& descriptor : m_panDescriptorList)
1959 {
1960 if (descriptor.m_coorAddrMode == SHORT_ADDR)
1961 {
1962 // Found a coordinator in PAN descriptor list with the same
1963 // registered short address
1964 descriptorExists =
1965 (descriptor.m_coorShortAddr == panDescriptor.m_coorShortAddr &&
1966 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
1967 }
1968 else
1969 {
1970 // Found a coordinator in PAN descriptor list with the same
1971 // registered extended address
1972 descriptorExists = (descriptor.m_coorExtAddr == panDescriptor.m_coorExtAddr &&
1973 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
1974 }
1975
1976 if (descriptorExists)
1977 {
1978 break;
1979 }
1980 }
1981
1982 if (!descriptorExists)
1983 {
1984 m_panDescriptorList.emplace_back(panDescriptor);
1985 }
1986 return;
1987 }
1988 else if (m_trackingEvent.IsPending())
1989 {
1990 // check if MLME-SYNC.request was previously issued and running
1991 // Sync. is necessary to handle pending messages (indirect
1992 // transmissions)
1994 m_numLostBeacons = 0;
1995
1997 {
1998 // if tracking option is on keep tracking the next beacon
1999 uint64_t searchSymbols;
2000 Time searchBeaconTime;
2001
2002 searchSymbols = (static_cast<uint64_t>(1 << m_incomingBeaconOrder)) +
2004 searchBeaconTime = Seconds(static_cast<double>(searchSymbols / symbolRate));
2006 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
2007 }
2008
2009 PendingAddrFields pndAddrFields;
2010 pndAddrFields = receivedMacPayload.GetPndAddrFields();
2011
2012 // TODO: Ignore pending data, and do not send data command request if
2013 // the address is in the GTS list.
2014 // If the address is not in the GTS list, then check if the
2015 // address is in the short address pending list or in the extended
2016 // address pending list and send a data command request.
2017 }
2018 }
2019 else
2020 {
2021 // m_macAutoRequest is FALSE
2022 // Data command request are not send, only the beacon notification.
2023 // see IEEE 802.15.4-2011 Section 6.2.4.1
2025 {
2027 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2028 beaconParams.m_panDescriptor = panDescriptor;
2029 beaconParams.m_sduLength = p->GetSize();
2030 beaconParams.m_sdu = p;
2032 }
2033 }
2034}
2035
2036void
2038{
2039 NS_LOG_FUNCTION(this);
2040 // Pull a packet from the queue and start sending if we are not already sending.
2041 if (m_macState == MAC_IDLE && !m_txQueue.empty() && !m_setMacState.IsPending())
2042 {
2043 if (m_csmaCa->IsUnSlottedCsmaCa() || (m_outSuperframeStatus == CAP && m_coor) ||
2045 {
2046 // check MAC is not in a IFS
2047 if (!m_ifsEvent.IsPending())
2048 {
2049 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2050 m_txPkt = txQElement->txQPkt;
2051
2054 }
2055 }
2056 }
2057}
2058
2059uint16_t
2061{
2062 SuperframeField sfrmSpec;
2063
2066 sfrmSpec.SetFinalCapSlot(m_fnlCapSlot);
2067
2068 if (m_csmaCa->GetBatteryLifeExtension())
2069 {
2070 sfrmSpec.SetBattLifeExt(true);
2071 }
2072
2073 if (m_panCoor)
2074 {
2075 sfrmSpec.SetPanCoor(true);
2076 }
2077
2078 // used to associate devices via Beacons
2080 {
2081 sfrmSpec.SetAssocPermit(true);
2082 }
2083
2084 return sfrmSpec.GetSuperframe();
2085}
2086
2089{
2090 GtsFields gtsFields;
2091
2092 // TODO: Logic to populate the GTS Fields from local information here
2093
2094 return gtsFields;
2095}
2096
2099{
2100 PendingAddrFields pndAddrFields;
2101
2102 // TODO: Logic to populate the Pending Address Fields from local information here
2103 return pndAddrFields;
2104}
2105
2106void
2108{
2109 m_csmaCa = csmaCa;
2110}
2111
2112void
2114{
2115 m_phy = phy;
2116}
2117
2120{
2121 return m_phy;
2122}
2123
2124void
2126{
2128 NS_LOG_FUNCTION(this << psduLength << p << (uint16_t)lqi);
2129
2130 bool acceptFrame;
2131
2132 Ptr<Packet> originalPkt = p->Copy(); // because we will strip headers
2133 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
2134
2135 m_promiscSnifferTrace(originalPkt);
2136 m_macPromiscRxTrace(originalPkt);
2137 // XXX no rejection tracing (to macRxDropTrace) being performed below
2138
2139 LrWpanMacTrailer receivedMacTrailer;
2140 p->RemoveTrailer(receivedMacTrailer);
2141
2143 {
2144 receivedMacTrailer.EnableFcs(true);
2145 }
2146
2147 LrWpanMacHeader receivedMacHdr;
2148 p->RemoveHeader(receivedMacHdr);
2149
2150 // From section 7.5.6.2 Reception and rejection, IEEE 802.15.4-2006
2151 // - Level 1 filtering: Test FCS field and reject if frame fails.
2152 // - Level 2 filtering: If promiscuous mode pass frame to higher layer
2153 // otherwise perform Level 3 filtering.
2154 // - Level 3 filtering: Accept frame if Frame type and version is not reserved, and if
2155 // there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
2156 // shortDstAddr then shortDstAddr=shortMacAddr or broadcastAddr, and if beacon frame then
2157 // srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
2158 // srcPanId=m_macPanId.
2159
2160 // Level 1 filtering
2161 if (!receivedMacTrailer.CheckFcs(p))
2162 {
2163 m_macRxDropTrace(originalPkt);
2164 return;
2165 }
2166
2167 // Level 2 filtering
2169 {
2170 ReceiveInPromiscuousMode(lqi, originalPkt);
2171 return;
2172 }
2173
2174 // Level 3 frame filtering
2175 acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
2176
2177 if (acceptFrame)
2178 {
2179 acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
2180 }
2181
2182 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
2183 {
2184 // Accept frame if one of the following is true:
2185
2186 // 1) Have the same macPanId
2187 // 2) Is Message to all PANs
2188 // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
2189 acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
2190 receivedMacHdr.GetDstPanId() == 0xffff) ||
2191 (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
2192 (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
2193 }
2194
2195 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
2196 {
2197 if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
2198 {
2199 // unicast, for me
2200 acceptFrame = true;
2201 }
2202 else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2203 receivedMacHdr.GetShortDstAddr().IsMulticast())
2204 {
2205 // Broadcast or multicast.
2206 // Discard broadcast/multicast with the ACK bit set.
2207 acceptFrame = !receivedMacHdr.IsAckReq();
2208 }
2209 else
2210 {
2211 acceptFrame = false;
2212 }
2213 }
2214
2215 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
2216 {
2217 acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_macExtendedAddress);
2218 }
2219
2220 if (acceptFrame && m_scanEvent.IsPending())
2221 {
2222 if (!receivedMacHdr.IsBeacon())
2223 {
2224 acceptFrame = false;
2225 }
2226 }
2227 else if (acceptFrame && m_scanOrphanEvent.IsPending())
2228 {
2229 if (!receivedMacHdr.IsCommand())
2230 {
2231 acceptFrame = false;
2232 }
2233 }
2234 else if (m_scanEnergyEvent.IsPending())
2235 {
2236 // Reject any frames if energy scan is running
2237 acceptFrame = false;
2238 }
2239
2240 // Check device is panCoor with association permit when receiving Association Request
2241 // Commands.
2242 if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
2243 {
2244 CommandPayloadHeader receivedMacPayload;
2245 p->PeekHeader(receivedMacPayload);
2246
2247 if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::ASSOCIATION_REQ &&
2249 {
2250 acceptFrame = false;
2251 }
2252
2253 // Although ACKs do not use CSMA to to be transmitted, we need to make sure
2254 // that the transmitted ACK will not collide with the transmission of a beacon
2255 // when beacon-enabled mode is running in the coordinator.
2256 if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsPending()))
2257 {
2258 Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
2259 uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
2260 ceil(6 * m_phy->GetPhySymbolsPerOctet());
2261 Time ackTime = Seconds((double)ackSymbols / symbolRate);
2262
2263 if (ackTime >= timeLeftInCap)
2264 {
2265 NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
2266 "before the end of CAP ");
2267 acceptFrame = false;
2268 }
2269 }
2270 }
2271
2272 if (!acceptFrame)
2273 {
2274 m_macRxDropTrace(originalPkt);
2275 return;
2276 }
2277
2279 params.m_dsn = receivedMacHdr.GetSeqNum();
2280 params.m_mpduLinkQuality = lqi;
2281 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
2282 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
2283
2284 switch (params.m_srcAddrMode)
2285 {
2286 case SHORT_ADDR:
2287 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
2288 break;
2289 case EXT_ADDR:
2290 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
2291 break;
2292 default:
2293 break;
2294 }
2295
2296 params.m_dstPanId = receivedMacHdr.GetDstPanId();
2297 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
2298
2299 switch (params.m_dstAddrMode)
2300 {
2301 case SHORT_ADDR:
2302 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
2303 break;
2304 case EXT_ADDR:
2305 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
2306 break;
2307 default:
2308 break;
2309 }
2310
2311 m_macRxTrace(originalPkt);
2312 // \todo: What should we do if we receive a frame while waiting for an ACK?
2313 // Especially if this frame has the ACK request bit set, should we reply with
2314 // an ACK, possibly missing the pending ACK?
2315
2316 // If the received frame is a frame with the ACK request bit set, we immediately
2317 // send back an ACK. If we are currently waiting for a pending ACK, we assume the
2318 // ACK was lost and trigger a retransmission after sending the ACK.
2319 if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) && receivedMacHdr.IsAckReq() &&
2320 !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
2321 (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2322 receivedMacHdr.GetShortDstAddr().IsMulticast())))
2323 {
2324 // If this is a data or mac command frame, which is not a broadcast or
2325 // multicast, with ack req set, generate and send an ack frame. If there is a
2326 // CSMA medium access in progress we cancel the medium access for sending the
2327 // ACK frame. A new transmission attempt will be started after the ACK was send.
2329 {
2332 }
2333 else if (m_macState == MAC_CSMA)
2334 {
2335 // \todo: If we receive a packet while doing CSMA/CA, should we drop the
2336 // packet because of channel busy,
2337 // or should we restart CSMA/CA for the packet after sending the ACK?
2338 // Currently we simply restart CSMA/CA after sending the ACK.
2339 NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
2340 "current CSMA-CA");
2341 m_csmaCa->Cancel();
2342 }
2343 // Cancel any pending MAC state change, ACKs have higher priority.
2346
2347 // save received packet and LQI to process the appropriate indication/response
2348 // after sending ACK (PD-DATA.confirm)
2349 m_rxPkt = originalPkt->Copy();
2350 m_lastRxFrameLqi = lqi;
2351
2352 // LOG Commands with ACK required.
2353 CommandPayloadHeader receivedMacPayload;
2354 p->PeekHeader(receivedMacPayload);
2355 switch (receivedMacPayload.GetCommandFrameType())
2356 {
2358 NS_LOG_DEBUG("Data Request Command Received; processing ACK");
2359 break;
2361 NS_LOG_DEBUG("Association Request Command Received; processing ACK");
2362 break;
2365 {
2366 m_assocResCmdWaitTimeout.Cancel(); // cancel event to a lost assoc resp cmd.
2367 NS_LOG_DEBUG("Association Response Command Received; processing ACK");
2368 }
2369 else
2370 {
2371 // Association response command was received before (or never received)
2372 // a Data request command ACK. This is an extreme case and it is
2373 // essentially caused by saturation in the network.
2374 // We turn a flag ON to not react once
2375 // we finally receive the Data request command ACK. This behavior is not
2376 // standard, but necessary to address this flaw in design of the
2377 // original association process.
2378 m_ignoreDataCmdAck = true;
2379 NS_LOG_DEBUG("Assoc. Resp Cmd received before Data Req. Cmd. in "
2380 "Association request");
2381 }
2382 break;
2383 }
2384 default:
2385 break;
2386 }
2387
2389 Simulator::ScheduleNow(&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum());
2390 }
2391
2392 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
2393 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2394 {
2395 NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstAddr << "]");
2396 }
2397 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
2398 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2399 {
2400 NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to [" << params.m_dstExtAddr
2401 << "]");
2402 }
2403 else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
2404 receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2405 {
2406 NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstExtAddr << "]");
2407 }
2408 else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
2409 receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2410 {
2411 NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to [" << params.m_dstAddr << "]");
2412 }
2413
2414 if (receivedMacHdr.IsBeacon())
2415 {
2416 ReceiveBeacon(lqi, originalPkt);
2417 }
2418 else if (receivedMacHdr.IsCommand())
2419 {
2420 // Handle the reception of frame commands that do not require ACK
2421 // (i.e. Beacon Request, Orphan notification, Coordinator Realigment)
2422 CommandPayloadHeader receivedMacPayload;
2423 p->PeekHeader(receivedMacPayload);
2424
2425 switch (receivedMacPayload.GetCommandFrameType())
2426 {
2428 if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
2429 {
2430 // Jitter = Between 0 and 2 aUnitBackoffPeriods
2431 // (0, 320us or 640us in 2.4Ghz O-QPSK)
2432 // While this jitter is not described by the standard,
2433 // it reduces the probability of collisions in beacons
2434 // transmitted as a result of a beacon request
2435 Time jitter = Seconds(
2436 static_cast<double>(m_uniformVar->GetInteger(0, 3) * aUnitBackoffPeriod) /
2437 symbolRate);
2438
2440 }
2441 else
2442 {
2443 m_macRxDropTrace(originalPkt);
2444 }
2445 break;
2448 {
2449 if (m_coor)
2450 {
2451 MlmeOrphanIndicationParams orphanParams;
2452 orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
2453 m_mlmeOrphanIndicationCallback(orphanParams);
2454 }
2455 }
2456 break;
2459 {
2460 // Coordinator located, no need to keep scanning other channels
2462
2463 m_macPanIdScan = 0;
2466
2467 // Update the device information with the received information
2468 // from the Coordinator Realigment command.
2469 m_macPanId = receivedMacPayload.GetPanId();
2470 m_shortAddress = receivedMacPayload.GetShortAddr();
2471 m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
2472 m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
2473
2475 {
2476 MlmeScanConfirmParams confirmParams;
2477 confirmParams.m_scanType = m_scanParams.m_scanType;
2478 confirmParams.m_chPage = m_scanParams.m_chPage;
2479 confirmParams.m_status = MacStatus::SUCCESS;
2480 m_mlmeScanConfirmCallback(confirmParams);
2481 }
2482 m_scanParams = {};
2483 }
2484 // TODO: handle Coordinator realignment when not
2485 // used during an orphan scan.
2486 break;
2487 default:
2488 m_macRxDropTrace(originalPkt);
2489 break;
2490 }
2491 }
2492 else if (receivedMacHdr.IsData() && !m_mcpsDataIndicationCallback.IsNull())
2493 {
2494 // If it is a data frame, push it up the stack.
2495 NS_LOG_DEBUG("Data Packet is for me; forwarding up");
2497 }
2498 else if (receivedMacHdr.IsAcknowledgment() && m_txPkt && m_macState == MAC_ACK_PENDING)
2499 {
2500 LrWpanMacHeader peekedMacHdr;
2501 m_txPkt->PeekHeader(peekedMacHdr);
2502 // If it is an ACK with the expected sequence number, finish the transmission
2503 if (receivedMacHdr.GetSeqNum() == peekedMacHdr.GetSeqNum())
2504 {
2507
2508 // TODO: check if the IFS is the correct size after ACK.
2509 Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
2510
2511 // We received an ACK to a command
2512 if (peekedMacHdr.IsCommand())
2513 {
2514 // check the original sent command frame which belongs to this received
2515 // ACK
2516 Ptr<Packet> pkt = m_txPkt->Copy();
2517 LrWpanMacHeader macHdr;
2518 CommandPayloadHeader cmdPayload;
2519 pkt->RemoveHeader(macHdr);
2520 pkt->RemoveHeader(cmdPayload);
2521
2522 switch (cmdPayload.GetCommandFrameType())
2523 {
2525 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2526 Time waitTime =
2527 Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
2528 if (!m_beaconTrackingOn)
2529 {
2532 }
2533 else
2534 {
2535 // TODO: The data must be extracted by the coordinator within
2536 // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
2537 // with status NO_DATA, and this should trigger the cancellation
2538 // of the beacon tracking (MLME-SYNC.request trackBeacon
2539 // =FALSE)
2540 }
2541 break;
2542 }
2543
2545 // MLME-comm-status.Indication generated as a result of an
2546 // association response command, therefore src and dst address use
2547 // extended mode (see 5.3.2.1)
2549 {
2550 MlmeCommStatusIndicationParams commStatusParams;
2551 commStatusParams.m_panId = m_macPanId;
2552 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2553 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2554 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2555 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2556 commStatusParams.m_status = MacStatus::SUCCESS;
2557 m_mlmeCommStatusIndicationCallback(commStatusParams);
2558 }
2559 // Remove element from Pending Transaction List
2561 break;
2562 }
2563
2565 if (!m_ignoreDataCmdAck)
2566 {
2567 // Schedule an event in case the Association Response Command
2568 // never reached this device during an association process.
2569 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2570 Time waitTime =
2571 Seconds(static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
2574 }
2575
2577 {
2578 MlmePollConfirmParams pollConfirmParams;
2579 pollConfirmParams.m_status = MacStatus::SUCCESS;
2580 m_mlmePollConfirmCallback(pollConfirmParams);
2581 }
2582 break;
2583 }
2584
2586 // ACK of coordinator realigment commands is not specified in the
2587 // standard, in here, we assume they are required as in other
2588 // commands.
2590 {
2591 MlmeCommStatusIndicationParams commStatusParams;
2592 commStatusParams.m_panId = m_macPanId;
2593 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2594 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2595 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2596 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2597 commStatusParams.m_status = MacStatus::SUCCESS;
2598 m_mlmeCommStatusIndicationCallback(commStatusParams);
2599 }
2600 }
2601
2602 default: {
2603 // TODO: add response to other request commands (e.g. Orphan)
2604 break;
2605 }
2606 }
2607 }
2608 else
2609 {
2611 {
2612 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2613 McpsDataConfirmParams confirmParams;
2614 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2615 confirmParams.m_status = MacStatus::SUCCESS;
2616 m_mcpsDataConfirmCallback(confirmParams);
2617 }
2618 }
2619
2620 // Ack was successfully received, wait for the Interframe Space (IFS) and
2621 // then proceed
2625 m_ifsEvent =
2626 Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
2627 }
2628 else
2629 {
2630 // If it is an ACK with an unexpected sequence number, mark the current
2631 // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
2633 if (!PrepareRetransmission())
2634 {
2638 }
2639 else
2640 {
2644 }
2645 }
2646 }
2647}
2648
2649void
2651{
2652 NS_LOG_FUNCTION(this << static_cast<uint32_t>(seqno));
2653
2655
2656 // Generate a corresponding ACK Frame.
2658 LrWpanMacTrailer macTrailer;
2659 Ptr<Packet> ackPacket = Create<Packet>(0);
2660 ackPacket->AddHeader(macHdr);
2661 // Calculate FCS if the global attribute ChecksumEnabled is set.
2663 {
2664 macTrailer.EnableFcs(true);
2665 macTrailer.SetFcs(ackPacket);
2666 }
2667 ackPacket->AddTrailer(macTrailer);
2668
2669 // Enqueue the ACK packet for further processing
2670 // when the transmitter is activated.
2671 m_txPkt = ackPacket;
2672
2673 // Switch transceiver to TX mode. Proceed sending the Ack on confirm.
2675 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
2676}
2677
2678void
2680{
2681 if (m_txQueue.size() < m_maxTxQueueSize)
2682 {
2683 m_txQueue.emplace_back(txQElement);
2684 m_macTxEnqueueTrace(txQElement->txQPkt);
2685 }
2686 else
2687 {
2689 {
2690 McpsDataConfirmParams confirmParams;
2691 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2693 m_mcpsDataConfirmCallback(confirmParams);
2694 }
2695 NS_LOG_DEBUG("TX Queue with size " << m_txQueue.size() << " is full, dropping packet");
2696 m_macTxDropTrace(txQElement->txQPkt);
2697 }
2698}
2699
2700void
2702{
2703 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2704 Ptr<const Packet> p = txQElement->txQPkt;
2705 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2706
2707 Ptr<Packet> pkt = p->Copy();
2708 LrWpanMacHeader hdr;
2709 pkt->RemoveHeader(hdr);
2710 if (!hdr.GetShortDstAddr().IsBroadcast() && !hdr.GetShortDstAddr().IsMulticast())
2711 {
2713 }
2714
2715 txQElement->txQPkt = nullptr;
2716 txQElement = nullptr;
2717 m_txQueue.pop_front();
2718 m_txPkt = nullptr;
2719 m_retransmission = 0;
2720 m_numCsmacaRetry = 0;
2722}
2723
2724void
2726{
2727 NS_LOG_FUNCTION(this);
2728
2729 // TODO: If we are a PAN coordinator and this was an indirect transmission,
2730 // we will not initiate a retransmission. Instead we wait for the data
2731 // being extracted after a new data request command.
2732 if (!PrepareRetransmission())
2733 {
2735 }
2736 else
2737 {
2739 }
2740}
2741
2742void
2744{
2745 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false);
2746 Time lifsTime = Seconds((double)m_macLIFSPeriod / symbolRate);
2747 Time sifsTime = Seconds((double)m_macSIFSPeriod / symbolRate);
2748
2749 if (ifsTime == lifsTime)
2750 {
2751 NS_LOG_DEBUG("LIFS of " << m_macLIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2752 << ") completed ");
2753 }
2754 else if (ifsTime == sifsTime)
2755 {
2756 NS_LOG_DEBUG("SIFS of " << m_macSIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2757 << ") completed ");
2758 }
2759 else
2760 {
2761 NS_LOG_DEBUG("Unknown IFS size (" << ifsTime.As(Time::S) << ") completed ");
2762 }
2763
2764 m_macIfsEndTrace(ifsTime);
2765 CheckQueue();
2766}
2767
2768bool
2770{
2771 NS_LOG_FUNCTION(this);
2772
2773 // Max retransmissions reached without receiving ACK,
2774 // send the proper indication/confirmation
2775 // according to the frame type and call drop trace.
2777 {
2778 LrWpanMacHeader peekedMacHdr;
2779 m_txPkt->PeekHeader(peekedMacHdr);
2780
2781 if (peekedMacHdr.IsCommand())
2782 {
2784
2785 Ptr<Packet> pkt = m_txPkt->Copy();
2786 LrWpanMacHeader macHdr;
2787 CommandPayloadHeader cmdPayload;
2788 pkt->RemoveHeader(macHdr);
2789 pkt->RemoveHeader(cmdPayload);
2790
2791 switch (cmdPayload.GetCommandFrameType())
2792 {
2794 m_macPanId = 0xffff;
2796 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2799 m_csmaCa->SetUnSlottedCsmaCa();
2802
2804 {
2805 MlmeAssociateConfirmParams confirmParams;
2806 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
2807 confirmParams.m_status = MacStatus::NO_ACK;
2808 m_mlmeAssociateConfirmCallback(confirmParams);
2809 }
2810 break;
2811 }
2813 // IEEE 802.15.4-2006 (Section 7.1.3.3.3 and 7.1.8.2.3)
2815 {
2816 MlmeCommStatusIndicationParams commStatusParams;
2817 commStatusParams.m_panId = m_macPanId;
2818 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2819 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2820 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2821 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2822 commStatusParams.m_status = MacStatus::NO_ACK;
2823 m_mlmeCommStatusIndicationCallback(commStatusParams);
2824 }
2826 break;
2827 }
2829 // IEEE 802.15.4-2006 (Section 7.1.16.1.3)
2830 m_macPanId = 0xffff;
2832 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2835 m_csmaCa->SetUnSlottedCsmaCa();
2838
2840 {
2841 MlmePollConfirmParams pollConfirmParams;
2842 pollConfirmParams.m_status = MacStatus::NO_ACK;
2843 m_mlmePollConfirmCallback(pollConfirmParams);
2844 }
2845 break;
2846 }
2847 default: {
2848 // TODO: Specify other indications according to other commands
2849 break;
2850 }
2851 }
2852 }
2853 else
2854 {
2855 // Maximum number of retransmissions has been reached.
2856 // remove the copy of the DATA packet that was just sent
2857 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2858 m_macTxDropTrace(txQElement->txQPkt);
2860 {
2861 McpsDataConfirmParams confirmParams;
2862 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2863 confirmParams.m_status = MacStatus::NO_ACK;
2864 m_mcpsDataConfirmCallback(confirmParams);
2865 }
2866 }
2867
2869 return false;
2870 }
2871 else
2872 {
2874 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2875 // Start next CCA process for this packet.
2876 return true;
2877 }
2878}
2879
2880void
2882{
2884 LrWpanMacHeader peekedMacHdr;
2885 p->PeekHeader(peekedMacHdr);
2886
2887 PurgeInd();
2888
2889 NS_ASSERT(peekedMacHdr.GetDstAddrMode() == SHORT_ADDR ||
2890 peekedMacHdr.GetDstAddrMode() == EXT_ADDR);
2891
2892 if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2893 {
2894 indTxQElement->dstShortAddress = peekedMacHdr.GetShortDstAddr();
2895 }
2896 else
2897 {
2898 indTxQElement->dstExtAddress = peekedMacHdr.GetExtDstAddr();
2899 }
2900
2901 indTxQElement->seqNum = peekedMacHdr.GetSeqNum();
2902
2903 // See IEEE 802.15.4-2006, Table 86
2904 uint32_t unit = 0; // The persistence time in symbols
2905 if (m_macBeaconOrder == 15)
2906 {
2907 // Non-beacon enabled mode
2909 }
2910 else
2911 {
2912 // Beacon-enabled mode
2913 unit = ((static_cast<uint32_t>(1) << m_macBeaconOrder) * lrwpan::aBaseSuperframeDuration) *
2915 }
2916
2917 if (m_indTxQueue.size() < m_maxIndTxQueueSize)
2918 {
2919 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2920 Time expireTime = Seconds(unit / symbolRate);
2921 expireTime += Simulator::Now();
2922 indTxQElement->expireTime = expireTime;
2923 indTxQElement->txQPkt = p;
2924 m_indTxQueue.emplace_back(indTxQElement);
2926 }
2927 else
2928 {
2930 {
2931 LrWpanMacHeader peekedMacHdr;
2932 indTxQElement->txQPkt->PeekHeader(peekedMacHdr);
2933 MlmeCommStatusIndicationParams commStatusParams;
2934 commStatusParams.m_panId = m_macPanId;
2935 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2936 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2937 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2938 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2939 commStatusParams.m_status = MacStatus::TRANSACTION_OVERFLOW;
2940 m_mlmeCommStatusIndicationCallback(commStatusParams);
2941 }
2943 }
2944}
2945
2946bool
2948{
2949 PurgeInd();
2950
2951 for (auto iter = m_indTxQueue.begin(); iter != m_indTxQueue.end(); iter++)
2952 {
2953 if ((*iter)->dstExtAddress == dst)
2954 {
2955 *entry = **iter;
2956 m_macIndTxDequeueTrace((*iter)->txQPkt->Copy());
2957 m_indTxQueue.erase(iter);
2958 return true;
2959 }
2960 }
2961 return false;
2962}
2963
2964void
2966{
2967 for (uint32_t i = 0; i < m_indTxQueue.size();)
2968 {
2969 if (Simulator::Now() > m_indTxQueue[i]->expireTime)
2970 {
2971 // Transaction expired, remove and send proper confirmation/indication to a higher layer
2972 LrWpanMacHeader peekedMacHdr;
2973 m_indTxQueue[i]->txQPkt->PeekHeader(peekedMacHdr);
2974
2975 if (peekedMacHdr.IsCommand())
2976 {
2977 // IEEE 802.15.4-2006 (Section 7.1.3.3.3)
2979 {
2980 MlmeCommStatusIndicationParams commStatusParams;
2981 commStatusParams.m_panId = m_macPanId;
2982 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2983 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2984 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2985 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2986 commStatusParams.m_status = MacStatus::TRANSACTION_EXPIRED;
2987 m_mlmeCommStatusIndicationCallback(commStatusParams);
2988 }
2989 }
2990 else if (peekedMacHdr.IsData())
2991 {
2992 // IEEE 802.15.4-2006 (Section 7.1.1.1.3)
2994 {
2995 McpsDataConfirmParams confParams;
2997 m_mcpsDataConfirmCallback(confParams);
2998 }
2999 }
3000 m_macIndTxDropTrace(m_indTxQueue[i]->txQPkt->Copy());
3001 m_indTxQueue.erase(m_indTxQueue.begin() + i);
3002 }
3003 else
3004 {
3005 i++;
3006 }
3007 }
3008}
3009
3010void
3011LrWpanMac::PrintPendingTxQueue(std::ostream& os) const
3012{
3013 LrWpanMacHeader peekedMacHdr;
3014
3015 os << "Pending Transaction List [" << GetShortAddress() << " | " << GetExtendedAddress()
3016 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
3017 << " Destination |"
3018 << " Sequence Number |"
3019 << " Frame type |"
3020 << " Expire time\n";
3021
3022 for (auto transaction : m_indTxQueue)
3023 {
3024 transaction->txQPkt->PeekHeader(peekedMacHdr);
3025 os << transaction->dstExtAddress << " "
3026 << static_cast<uint32_t>(transaction->seqNum) << " ";
3027
3028 if (peekedMacHdr.IsCommand())
3029 {
3030 os << " Command Frame ";
3031 }
3032 else if (peekedMacHdr.IsData())
3033 {
3034 os << " Data Frame ";
3035 }
3036 else
3037 {
3038 os << " Unknown Frame ";
3039 }
3040
3041 os << transaction->expireTime.As(Time::S) << "\n";
3042 }
3043}
3044
3045void
3046LrWpanMac::PrintTxQueue(std::ostream& os) const
3047{
3048 LrWpanMacHeader peekedMacHdr;
3049
3050 os << "\nTx Queue [" << GetShortAddress() << " | " << GetExtendedAddress()
3051 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
3052 << " Destination |"
3053 << " Sequence Number |"
3054 << " Dst PAN id |"
3055 << " Frame type |\n";
3056
3057 for (auto transaction : m_txQueue)
3058 {
3059 transaction->txQPkt->PeekHeader(peekedMacHdr);
3060
3061 os << "[" << peekedMacHdr.GetShortDstAddr() << "]"
3062 << ", [" << peekedMacHdr.GetExtDstAddr() << "] "
3063 << static_cast<uint32_t>(peekedMacHdr.GetSeqNum()) << " "
3064 << peekedMacHdr.GetDstPanId() << " ";
3065
3066 if (peekedMacHdr.IsCommand())
3067 {
3068 os << " Command Frame ";
3069 }
3070 else if (peekedMacHdr.IsData())
3071 {
3072 os << " Data Frame ";
3073 }
3074 else
3075 {
3076 os << " Unknown Frame ";
3077 }
3078
3079 os << "\n";
3080 }
3081 os << "\n";
3082}
3083
3084int64_t
3086{
3087 NS_LOG_FUNCTION(this);
3088 m_uniformVar->SetStream(stream);
3089 m_csmaCa->AssignStreams(stream + 1);
3090 return 2;
3091}
3092
3093void
3095{
3096 LrWpanMacHeader peekedMacHdr;
3097 p->PeekHeader(peekedMacHdr);
3098
3099 for (auto it = m_indTxQueue.begin(); it != m_indTxQueue.end(); it++)
3100 {
3101 if (peekedMacHdr.GetDstAddrMode() == EXT_ADDR)
3102 {
3103 if (((*it)->dstExtAddress == peekedMacHdr.GetExtDstAddr()) &&
3104 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
3105 {
3107 m_indTxQueue.erase(it);
3108 break;
3109 }
3110 }
3111 else if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
3112 {
3113 if (((*it)->dstShortAddress == peekedMacHdr.GetShortDstAddr()) &&
3114 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
3115 {
3117 m_indTxQueue.erase(it);
3118 break;
3119 }
3120 }
3121 }
3122
3123 p = nullptr;
3124}
3125
3126void
3128{
3130 NS_LOG_FUNCTION(this << status << m_txQueue.size());
3131
3132 LrWpanMacHeader macHdr;
3133 Time ifsWaitTime;
3134 double symbolRate;
3135
3136 symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
3137
3138 m_txPkt->PeekHeader(macHdr);
3139
3140 if (status == IEEE_802_15_4_PHY_SUCCESS)
3141 {
3142 if (!macHdr.IsAcknowledgment())
3143 {
3144 if (macHdr.IsBeacon())
3145 {
3146 // Start CAP only if we are in beacon mode (i.e. if slotted csma-ca is running)
3147 if (m_csmaCa->IsSlottedCsmaCa())
3148 {
3149 // The Tx Beacon in symbols
3150 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
3151 // 17 bytes)
3152 uint64_t beaconSymbols = m_phy->GetPhySHRDuration() +
3153 1 * m_phy->GetPhySymbolsPerOctet() +
3154 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
3155
3156 // The beacon Tx time and start of the Outgoing superframe Active Period
3158 Simulator::Now() - Seconds(static_cast<double>(beaconSymbols) / symbolRate);
3159
3161 this,
3163 NS_LOG_DEBUG("Beacon Sent (m_macBeaconTxTime: " << m_macBeaconTxTime.As(Time::S)
3164 << ")");
3165
3167 {
3168 MlmeStartConfirmParams mlmeConfirmParams;
3169 mlmeConfirmParams.m_status = MacStatus::SUCCESS;
3170 m_mlmeStartConfirmCallback(mlmeConfirmParams);
3171 }
3172 }
3173
3174 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3175
3176 if (m_csmaCa->IsSlottedCsmaCa())
3177 {
3178 // The beacon was sent immediately in beacon-enabled mode
3179 m_txPkt = nullptr;
3180 }
3181 else
3182 {
3183 // The beacon was sent using CSMA/CA as a result of a beacon request
3184 // therefore, remove it from TX Queue
3186 }
3187 }
3188 else if (macHdr.IsAckReq()) // We have sent a regular data packet, check if we have to
3189 // wait for an ACK.
3190 {
3191 // we sent a regular data frame or command frame (e.g. AssocReq command) that
3192 // require ACK wait for the ack or the next retransmission timeout start
3193 // retransmission timer
3194 Time waitTime = Seconds(static_cast<double>(GetMacAckWaitDuration()) / symbolRate);
3200 return;
3201 }
3202 else if (macHdr.IsCommand())
3203 {
3204 // We handle commands that do not require ACK
3205 // (e.g. Coordinator realigment command in an orphan response)
3206 // Other command with ACK required are handle by the previous if statement.
3207
3208 // Check the transmitted packet command type and issue the appropriate indication.
3209 Ptr<Packet> txOriginalPkt = m_txPkt->Copy();
3210 LrWpanMacHeader txMacHdr;
3211 txOriginalPkt->RemoveHeader(txMacHdr);
3212 CommandPayloadHeader txMacPayload;
3213 txOriginalPkt->RemoveHeader(txMacPayload);
3214
3216 {
3218 {
3219 MlmeCommStatusIndicationParams commStatusParams;
3220 commStatusParams.m_panId = m_macPanId;
3221
3222 commStatusParams.m_srcAddrMode = macHdr.GetSrcAddrMode();
3223 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3224 commStatusParams.m_srcShortAddr = macHdr.GetShortSrcAddr();
3225
3226 commStatusParams.m_dstAddrMode = macHdr.GetDstAddrMode();
3227 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3228 commStatusParams.m_dstShortAddr = macHdr.GetShortDstAddr();
3229
3230 commStatusParams.m_status = MacStatus::SUCCESS;
3231 m_mlmeCommStatusIndicationCallback(commStatusParams);
3232 }
3233 }
3234
3235 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3237 }
3238 else
3239 {
3241 // remove the copy of the packet that was just sent
3243 {
3244 McpsDataConfirmParams confirmParams;
3245 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3246 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3247 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3248 confirmParams.m_status = MacStatus::SUCCESS;
3249 m_mcpsDataConfirmCallback(confirmParams);
3250 }
3251 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3253 }
3254 }
3255 else
3256 {
3257 // The packet sent was a successful ACK
3258
3259 // Check the received frame before the transmission of the ACK,
3260 // and send the appropriate Indication or Confirmation
3261 Ptr<Packet> recvOriginalPkt = m_rxPkt->Copy();
3262 LrWpanMacHeader receivedMacHdr;
3263 recvOriginalPkt->RemoveHeader(receivedMacHdr);
3264
3265 if (receivedMacHdr.IsCommand())
3266 {
3267 CommandPayloadHeader receivedMacPayload;
3268 recvOriginalPkt->RemoveHeader(receivedMacPayload);
3269
3270 if (receivedMacPayload.GetCommandFrameType() ==
3272 {
3274 {
3275 // NOTE: The LQI parameter is not part of the standard but found
3276 // in some implementations as is required for higher layers (See Zboss
3277 // implementation).
3278 MlmeAssociateIndicationParams associateParams;
3279 associateParams.capabilityInfo = receivedMacPayload.GetCapabilityField();
3280 associateParams.m_extDevAddr = receivedMacHdr.GetExtSrcAddr();
3281 associateParams.lqi = m_lastRxFrameLqi;
3282 m_mlmeAssociateIndicationCallback(associateParams);
3283 }
3284
3285 // Clear the packet buffer for the packet request received.
3286 m_rxPkt = nullptr;
3287 }
3288 else if (receivedMacPayload.GetCommandFrameType() ==
3290 {
3291 MlmeAssociateConfirmParams confirmParams;
3292
3293 switch (static_cast<MacStatus>(receivedMacPayload.GetAssociationStatus()))
3294 {
3295 case MacStatus::SUCCESS:
3296 // The assigned short address by the coordinator
3297 SetShortAddress(receivedMacPayload.GetShortAddr());
3298 m_macPanId = receivedMacHdr.GetSrcPanId();
3299
3300 confirmParams.m_status = MacStatus::SUCCESS;
3301 confirmParams.m_assocShortAddr = GetShortAddress();
3302 break;
3304 confirmParams.m_status = MacStatus::FULL_CAPACITY;
3305 m_macPanId = 0xffff;
3307 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3310 m_csmaCa->SetUnSlottedCsmaCa();
3313 break;
3315 default:
3316 confirmParams.m_status = MacStatus::ACCESS_DENIED;
3317 m_macPanId = 0xffff;
3319 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3322 m_csmaCa->SetUnSlottedCsmaCa();
3325 break;
3326 }
3327
3329 {
3330 m_mlmeAssociateConfirmCallback(confirmParams);
3331 }
3332 }
3333 else if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::DATA_REQ)
3334 {
3335 // We enqueue the the Assoc Response command frame in the Tx queue
3336 // and the packet is transmitted as soon as the PHY is free and the IFS have
3337 // taken place.
3339 }
3340 }
3341
3342 // Clear the packet buffer for the ACK packet sent.
3343 m_txPkt = nullptr;
3344 }
3345 }
3346 else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
3347 {
3348 if (!macHdr.IsAcknowledgment())
3349 {
3350 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3351 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3352 m_macTxDropTrace(txQElement->txQPkt);
3354 {
3355 McpsDataConfirmParams confirmParams;
3356 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3357 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
3358 m_mcpsDataConfirmCallback(confirmParams);
3359 }
3361 }
3362 else
3363 {
3364 NS_LOG_ERROR("Unable to send ACK");
3365 }
3366 }
3367 else
3368 {
3369 // Something went really wrong. The PHY is not in the correct state for
3370 // data transmission.
3371 NS_FATAL_ERROR("Transmission attempt failed with PHY status " << status);
3372 }
3373
3374 if (!ifsWaitTime.IsZero())
3375 {
3376 m_ifsEvent =
3377 Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
3378 }
3379
3382}
3383
3384void
3386{
3387 NS_LOG_FUNCTION(this << status);
3388 // Direct this call through the csmaCa object
3389 m_csmaCa->PlmeCcaConfirm(status);
3390}
3391
3392void
3393LrWpanMac::PlmeEdConfirm(PhyEnumeration status, uint8_t energyLevel)
3394{
3395 NS_LOG_FUNCTION(this << status << energyLevel);
3396
3397 if (energyLevel > m_maxEnergyLevel)
3398 {
3399 m_maxEnergyLevel = energyLevel;
3400 }
3401
3403 Seconds(8.0 / m_phy->GetDataOrSymbolRate(false)))
3404 {
3405 m_phy->PlmeEdRequest();
3406 }
3407}
3408
3409void
3412 Ptr<PhyPibAttributes> attribute)
3413{
3414 NS_LOG_FUNCTION(this << status << id << attribute);
3415}
3416
3417void
3419{
3420 NS_LOG_FUNCTION(this << status);
3421
3422 if (m_macState == MAC_SENDING &&
3423 (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3424 {
3426
3427 // Start sending if we are in state SENDING and the PHY transmitter was enabled.
3431 m_phy->PdDataRequest(m_txPkt->GetSize(), m_txPkt);
3432 }
3433 else if (m_macState == MAC_CSMA &&
3434 (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3435 {
3436 // Start the CSMA algorithm as soon as the receiver is enabled.
3437 m_csmaCa->Start();
3438 }
3439 else if (m_macState == MAC_IDLE)
3440 {
3442 status == IEEE_802_15_4_PHY_TRX_OFF);
3443
3445 {
3446 // Kick start Energy Detection Scan
3447 m_phy->PlmeEdRequest();
3448 }
3449 else if (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS)
3450 {
3451 // Check if there is not messages to transmit when going idle
3452 CheckQueue();
3453 }
3454 }
3455 else if (m_macState == MAC_ACK_PENDING)
3456 {
3458 }
3459 else
3460 {
3461 // TODO: What to do when we receive an error?
3462 // If we want to transmit a packet, but switching the transceiver on results
3463 // in an error, we have to recover somehow (and start sending again).
3464 NS_FATAL_ERROR("Error changing transceiver state");
3465 }
3466}
3467
3468void
3470{
3471 NS_LOG_FUNCTION(this << status << id);
3473 {
3475 {
3476 // get the first channel to scan from scan channel list
3477 bool channelFound = false;
3478 for (int i = m_channelScanIndex; i <= 26; i++)
3479 {
3481 {
3482 channelFound = true;
3483 break;
3484 }
3486 }
3487
3488 if (channelFound)
3489 {
3491 pibAttr->phyCurrentChannel = m_channelScanIndex;
3492 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel,
3493 pibAttr);
3494 }
3495 }
3496 else
3497 {
3499 {
3500 MlmeScanConfirmParams confirmParams;
3501 confirmParams.m_scanType = m_scanParams.m_scanType;
3502 confirmParams.m_chPage = m_scanParams.m_chPage;
3503 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3504 m_mlmeScanConfirmCallback(confirmParams);
3505 }
3506 NS_LOG_ERROR(this << "Channel Scan: Invalid channel page");
3507 }
3508 }
3510 {
3512 {
3513 auto symbolRate = static_cast<uint64_t>(m_phy->GetDataOrSymbolRate(false));
3514 Time nextScanTime;
3515
3517 {
3518 nextScanTime = Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
3519 }
3520 else
3521 {
3522 uint64_t scanDurationSym =
3524
3525 nextScanTime = Seconds(static_cast<double>(scanDurationSym) / symbolRate);
3526 }
3527
3528 switch (m_scanParams.m_scanType)
3529 {
3530 case MLMESCAN_ED:
3531 m_maxEnergyLevel = 0;
3534 // set phy to RX_ON and kick start the first PLME-ED.request
3535 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3536 break;
3537 case MLMESCAN_ACTIVE:
3540 break;
3541 case MLMESCAN_PASSIVE:
3543 // turn back the phy to RX_ON after setting Page/channel
3544 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3545 break;
3546 case MLMESCAN_ORPHAN:
3548 Simulator::Schedule(nextScanTime, &LrWpanMac::EndChannelScan, this);
3550 break;
3551
3552 default:
3553 MlmeScanConfirmParams confirmParams;
3554 confirmParams.m_scanType = m_scanParams.m_scanType;
3555 confirmParams.m_chPage = m_scanParams.m_chPage;
3556 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3558 {
3559 m_mlmeScanConfirmCallback(confirmParams);
3560 }
3561 NS_LOG_ERROR("Scan Type currently not supported");
3562 return;
3563 }
3564 }
3565 else
3566 {
3568 {
3569 MlmeScanConfirmParams confirmParams;
3570 confirmParams.m_scanType = m_scanParams.m_scanType;
3571 confirmParams.m_chPage = m_scanParams.m_chPage;
3572 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3573 m_mlmeScanConfirmCallback(confirmParams);
3574 }
3575 NS_LOG_ERROR("Channel " << m_channelScanIndex
3576 << " could not be set in the current page");
3577 }
3578 }
3580 {
3582 {
3584 pibAttr->phyCurrentChannel = m_startParams.m_logCh;
3585 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3586 }
3587 else
3588 {
3590 {
3591 MlmeStartConfirmParams confirmParams;
3592 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3593 m_mlmeStartConfirmCallback(confirmParams);
3594 }
3595 NS_LOG_ERROR("Invalid page parameter in MLME-start");
3596 }
3597 }
3600 {
3602 {
3604 }
3605 else
3606 {
3608 {
3609 MlmeStartConfirmParams confirmParams;
3610 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3611 m_mlmeStartConfirmCallback(confirmParams);
3612 }
3613 NS_LOG_ERROR("Invalid channel parameter in MLME-start");
3614 }
3615 }
3617 {
3619 {
3621 pibAttr->phyCurrentChannel = m_associateParams.m_chNum;
3622 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3623 }
3624 else
3625 {
3626 m_macPanId = 0xffff;
3628 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3631 m_csmaCa->SetUnSlottedCsmaCa();
3634
3636 {
3637 MlmeAssociateConfirmParams confirmParams;
3638 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3639 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3640 m_mlmeAssociateConfirmCallback(confirmParams);
3641 }
3642 NS_LOG_ERROR("Invalid page parameter in MLME-associate");
3643 }
3644 }
3647 {
3649 {
3651 }
3652 else
3653 {
3654 m_macPanId = 0xffff;
3656 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3659 m_csmaCa->SetUnSlottedCsmaCa();
3662
3664 {
3665 MlmeAssociateConfirmParams confirmParams;
3666 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3667 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3668 m_mlmeAssociateConfirmCallback(confirmParams);
3669 }
3670 NS_LOG_ERROR("Invalid channel parameter in MLME-associate");
3671 }
3672 }
3673 else
3674 {
3676 {
3677 MlmeSetConfirmParams confirmParams;
3679 {
3680 confirmParams.m_status = MacStatus::SUCCESS;
3681 }
3682 else
3683 {
3685 }
3686
3688 {
3690 }
3692 {
3694 }
3695
3696 m_mlmeSetConfirmCallback(confirmParams);
3697 }
3698 }
3699}
3700
3701void
3703{
3704 NS_LOG_FUNCTION(this << "mac state = " << macState);
3705
3706 if (macState == MAC_IDLE)
3707 {
3710 {
3711 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3712 }
3713 else
3714 {
3715 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3716 }
3717 }
3718 else if (macState == MAC_ACK_PENDING)
3719 {
3721 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3722 }
3723 else if (macState == MAC_CSMA)
3724 {
3727 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3728 }
3729 else if (m_macState == MAC_CSMA && macState == CHANNEL_IDLE)
3730 {
3731 // Channel is idle, set transmitter to TX_ON
3733 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
3734 }
3735 else if (m_macState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
3736 {
3738
3739 // Cannot find a clear channel, drop the current packet
3740 // and send the proper confirm/indication according to the packet type
3741 NS_LOG_DEBUG(this << " cannot find clear channel");
3742
3744
3745 Ptr<Packet> pkt = m_txPkt->Copy();
3746 LrWpanMacHeader macHdr;
3747 pkt->RemoveHeader(macHdr);
3748
3749 if (macHdr.IsCommand())
3750 {
3751 CommandPayloadHeader cmdPayload;
3752 pkt->RemoveHeader(cmdPayload);
3753
3754 switch (cmdPayload.GetCommandFrameType())
3755 {
3757 m_macPanId = 0xffff;
3759 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3762 m_csmaCa->SetUnSlottedCsmaCa();
3765
3767 {
3768 MlmeAssociateConfirmParams confirmParams;
3769 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3771 m_mlmeAssociateConfirmCallback(confirmParams);
3772 }
3773 break;
3774 }
3777 {
3778 MlmeCommStatusIndicationParams commStatusParams;
3779 commStatusParams.m_panId = m_macPanId;
3780 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3781 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3782 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3783 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3785 m_mlmeCommStatusIndicationCallback(commStatusParams);
3786 }
3788 break;
3789 }
3791 m_macPanId = 0xffff;
3793 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3796 m_csmaCa->SetUnSlottedCsmaCa();
3799
3801 {
3802 MlmePollConfirmParams pollConfirmParams;
3803 pollConfirmParams.m_status = MacStatus::CHANNEL_ACCESS_FAILURE;
3804 m_mlmePollConfirmCallback(pollConfirmParams);
3805 }
3806 break;
3807 }
3810 {
3811 MlmeCommStatusIndicationParams commStatusParams;
3812 commStatusParams.m_panId = m_macPanId;
3813 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3814 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3815 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3816 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3818 m_mlmeCommStatusIndicationCallback(commStatusParams);
3819 }
3820 break;
3821 }
3824 {
3825 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3826 }
3827 // TODO: Handle orphan notification command during a
3828 // channel access failure when not is not scanning.
3829 break;
3830 }
3832 if (m_scanEvent.IsPending())
3833 {
3834 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3835 }
3836 // TODO: Handle beacon request command during a
3837 // channel access failure when not scanning.
3838 break;
3839 }
3840 default: {
3841 // TODO: Other commands(e.g. Disassociation notification, etc)
3842 break;
3843 }
3844 }
3846 }
3847 else if (macHdr.IsData())
3848 {
3850 {
3851 McpsDataConfirmParams confirmParams;
3852 confirmParams.m_msduHandle = m_txQueue.front()->txQMsduHandle;
3854 m_mcpsDataConfirmCallback(confirmParams);
3855 }
3856 // remove the copy of the packet that was just sent
3858 }
3859 else
3860 {
3861 // TODO:: specify behavior for other packets
3862 m_txPkt = nullptr;
3863 m_retransmission = 0;
3864 m_numCsmacaRetry = 0;
3865 }
3866
3869 {
3870 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3871 }
3872 else
3873 {
3874 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3875 }
3876 }
3877 else if (m_macState == MAC_CSMA && macState == MAC_CSMA_DEFERRED)
3878 {
3880 m_txPkt = nullptr;
3881 // The MAC is running on beacon mode and the current packet could not be sent in the
3882 // current CAP. The packet will be send on the next CAP after receiving the beacon.
3883 // The PHY state does not change from its current form. The PHY change (RX_ON) will be
3884 // triggered by the scheduled beacon event.
3885
3886 NS_LOG_DEBUG("****** PACKET DEFERRED to the next superframe *****");
3887 }
3888}
3889
3890void
3895
3896void
3901
3902uint16_t
3904{
3905 return m_macPanId;
3906}
3907
3913
3919
3920void
3921LrWpanMac::SetPanId(uint16_t panId)
3922{
3923 m_macPanId = panId;
3924}
3925
3926void
3928{
3929 NS_LOG_LOGIC(this << " change lrwpan mac state from " << m_macState << " to " << newState);
3930 m_macStateLogger(m_macState, newState);
3931 m_macState = newState;
3932}
3933
3934uint64_t
3936{
3937 return lrwpan::aUnitBackoffPeriod + lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
3938 ceil(6 * m_phy->GetPhySymbolsPerOctet());
3939}
3940
3941uint8_t
3946
3947void
3949{
3950 NS_LOG_DEBUG("Transmit Queue Size: " << m_txQueue.size());
3951}
3952
3953void
3955{
3956 m_macMaxFrameRetries = retries;
3957}
3958
3959bool
3961{
3963 LrWpanMacHeader macHdr;
3964 m_txPkt->PeekHeader(macHdr);
3965
3966 if (m_coor)
3967 {
3968 // The device is its coordinator and the packet is not to itself
3969 return false;
3970 }
3971 else if (m_macCoordShortAddress == macHdr.GetShortDstAddr() ||
3973 {
3974 return true;
3975 }
3976 else
3977 {
3978 NS_LOG_DEBUG("ERROR: Packet not for the coordinator!");
3979 return false;
3980 }
3981}
3982
3985{
3987
3989 {
3990 return m_macSIFSPeriod;
3991 }
3992 else
3993 {
3994 return m_macLIFSPeriod;
3995 }
3996}
3997
3998void
4003
4004void
4009
4010uint64_t
4012{
4014 // Sync Header (SHR) + 8 bits PHY header (PHR) + PSDU
4015 return (m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
4016 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet()));
4017}
4018
4019bool
4021{
4023 LrWpanMacHeader macHdr;
4024 m_txPkt->PeekHeader(macHdr);
4025
4026 return macHdr.IsAckReq();
4027}
4028
4029} // namespace lrwpan
4030} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition callback.h:555
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition event-id.cc:58
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:440
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition packet.h:850
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition packet.cc:120
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition packet.cc:294
Smart pointer class similar to boost::intrusive_ptr.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:206
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
@ S
second
Definition nstime.h:105
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:304
a unique identifier for an interface.
Definition type-id.h:49
TypeId AddDeprecatedName(const std::string &name)
Add an deprecated name for a TypeId.
Definition type-id.cc:862
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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.
Class that implements the LR-WPAN MAC state machine.
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.
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 ...
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)
std::deque< Ptr< IndTxQueueElement > > m_indTxQueue
The indirect transmit queue used by the MAC pending messages (The 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.
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.
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.
std::deque< Ptr< TxQueueElement > > m_txQueue
The transmit queue used by the MAC.
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.
void ReceiveInPromiscuousMode(uint8_t lqi, Ptr< Packet > p)
Process a frame when promiscuous mode is active.
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.
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 ReceiveBeacon(uint8_t lqi, Ptr< Packet > p)
Used to process the reception of a beacon packet.
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.
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 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 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.
void PdDataIndication(uint32_t psduLength, Ptr< Packet > p, uint8_t lqi)
IEEE 802.15.4-2006 section 6.2.1.3 PD-DATA.indication Indicates the transfer of an MPDU from PHY to M...
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.
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.
void SendDataRequestCommand()
Used to send a data request command (i.e.
bool DequeueInd(Mac64Address dst, Ptr< IndTxQueueElement > entry)
Extracts a packet from pending transactions list (Indirect transmissions).
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 EnqueueTxQElement(Ptr< TxQueueElement > txQElement)
Add an element to the transmission queue.
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()
Definition callback.h:727
#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:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:64
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.
@ 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.
@ macBeaconPayload
The contents of the beacon payload.
@ MAC_CSMA
MAC_CSMA.
Definition lr-wpan-mac.h:66
@ MAC_GTS
MAC_GTS.
Definition lr-wpan-mac.h:72
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition lr-wpan-mac.h:69
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition lr-wpan-mac.h:70
@ SET_PHY_TX_ON
SET_PHY_TX_ON.
Definition lr-wpan-mac.h:71
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition lr-wpan-mac.h:74
@ MAC_IDLE
MAC_IDLE.
Definition lr-wpan-mac.h:65
@ MAC_INACTIVE
MAC_INACTIVE.
Definition lr-wpan-mac.h:73
@ MAC_SENDING
MAC_SENDING.
Definition lr-wpan-mac.h:67
@ MAC_ACK_PENDING
MAC_ACK_PENDING.
Definition lr-wpan-mac.h:68
@ BEACON
The Beacon transmission or reception Period.
Definition lr-wpan-mac.h:93
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition lr-wpan-mac.h:96
@ CAP
Contention Access Period.
Definition lr-wpan-mac.h:94
@ CFP
Contention Free Period.
Definition lr-wpan-mac.h:95
@ 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:54
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition lr-wpan-mac.h:53
@ TX_OPTION_INDIRECT
TX_OPTION_INDIRECT.
Definition lr-wpan-mac.h:55
@ 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:619
#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:436
SequenceNumber< uint8_t, int8_t > SequenceNumber8
8 bit Sequence number.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
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.
Mac64Address m_coordExtAddr
The extended address of the coordinator with which to associate.
uint8_t m_coordAddrMode
The coordinator addressing mode for this primitive and subsequent MPDU.
uint8_t m_capabilityInfo
Specifies the operational capabilities of the associating device (bitmap).
Mac16Address m_coordShortAddr
The short address of the coordinator with which to associate.
uint8_t m_chNum
The channel number on which to attempt association.
uint16_t m_coordPanId
The identifier of the PAN with which to associate.
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).
MlmeScanType m_scanType
Indicates the type of scan performed as described in IEEE 802.15.4-2011 (5.1.2.1).
uint32_t m_scanChannels
The channel numbers to be scanned.
uint8_t m_scanDuration
The factor (0-14) used to calculate the length of time to spend scanning.
uint32_t m_chPage
The channel page on which to perform scan.
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.
bool m_battLifeExt
Flag indicating whether or not the Battery life extension (BLE) features are used.
uint8_t m_logCh
Logical channel on which to start using the new superframe configuration.
uint32_t m_logChPage
Logical channel page on which to start using the new superframe configuration.
bool m_coorRealgn
True if a realignment request command is to be transmitted prior changing the superframe.
uint8_t m_bcnOrd
Beacon Order, Used to calculate the beacon interval, a value of 15 indicates no periodic beacons will...
bool m_panCoor
On true this device will become coordinator.
uint8_t m_sfrmOrd
Superframe Order, indicates the length of the CAP in time slots.
uint16_t m_PanId
Pan Identifier used by the device.
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