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