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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors:
18 * Gary Pei <guangyu.pei@boeing.com>
19 * kwong yin <kwong-sang.yin@boeing.com>
20 * Tom Henderson <thomas.r.henderson@boeing.com>
21 * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
22 * Erwan Livolant <erwan.livolant@inria.fr>
23 * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
24 */
25#include "lr-wpan-mac.h"
26
27#include "lr-wpan-constants.h"
28#include "lr-wpan-csmaca.h"
29#include "lr-wpan-mac-header.h"
31#include "lr-wpan-mac-trailer.h"
32
33#include <ns3/double.h>
34#include <ns3/log.h>
35#include <ns3/node.h>
36#include <ns3/packet.h>
37#include <ns3/random-variable-stream.h>
38#include <ns3/simulator.h>
39#include <ns3/uinteger.h>
40
41#undef NS_LOG_APPEND_CONTEXT
42#define NS_LOG_APPEND_CONTEXT \
43 std::clog << "[address " << m_shortAddress << " | " << m_selfExt << "] ";
44
45namespace ns3
46{
47
48NS_LOG_COMPONENT_DEFINE("LrWpanMac");
50
51std::ostream&
52operator<<(std::ostream& os, const LrWpanMacState& state)
53{
54 switch (state)
55 {
57 os << "MAC IDLE";
58 break;
60 os << "CSMA";
61 break;
63 os << "SENDING";
64 break;
66 os << "ACK PENDING";
67 break;
69 os << "CHANNEL_ACCESS_FAILURE";
70 break;
72 os << "CHANNEL IDLE";
73 break;
75 os << "SET PHY to TX ON";
76 break;
78 os << "MAC GTS PERIOD";
79 break;
81 os << "SUPERFRAME INACTIVE PERIOD";
82 break;
84 os << "CSMA DEFERRED TO NEXT PERIOD";
85 break;
86 }
87 return os;
88};
89
90TypeId
92{
93 static TypeId tid =
94 TypeId("ns3::LrWpanMac")
96 .SetGroupName("LrWpan")
97 .AddConstructor<LrWpanMac>()
98 .AddAttribute("PanId",
99 "16-bit identifier of the associated PAN",
102 MakeUintegerChecker<uint16_t>())
103 .AddTraceSource("MacTxEnqueue",
104 "Trace source indicating a packet has been "
105 "enqueued in the transaction queue",
107 "ns3::Packet::TracedCallback")
108 .AddTraceSource("MacTxDequeue",
109 "Trace source indicating a packet has was "
110 "dequeued from the transaction queue",
112 "ns3::Packet::TracedCallback")
113 .AddTraceSource("MacIndTxEnqueue",
114 "Trace source indicating a packet has been "
115 "enqueued in the indirect transaction queue",
117 "ns3::Packet::TracedCallback")
118 .AddTraceSource("MacIndTxDequeue",
119 "Trace source indicating a packet has was "
120 "dequeued from the indirect transaction queue",
122 "ns3::Packet::TracedCallback")
123 .AddTraceSource("MacTx",
124 "Trace source indicating a packet has "
125 "arrived for transmission by this device",
127 "ns3::Packet::TracedCallback")
128 .AddTraceSource("MacTxOk",
129 "Trace source indicating a packet has been "
130 "successfully sent",
132 "ns3::Packet::TracedCallback")
133 .AddTraceSource("MacTxDrop",
134 "Trace source indicating a packet has been "
135 "dropped during transmission",
137 "ns3::Packet::TracedCallback")
138 .AddTraceSource("MacIndTxDrop",
139 "Trace source indicating a packet has been "
140 "dropped from the indirect transaction queue"
141 "(The pending transaction list)",
143 "ns3::Packet::TracedCallback")
144 .AddTraceSource("MacPromiscRx",
145 "A packet has been received by this device, "
146 "has been passed up from the physical layer "
147 "and is being forwarded up the local protocol stack. "
148 "This is a promiscuous trace,",
150 "ns3::Packet::TracedCallback")
151 .AddTraceSource("MacRx",
152 "A packet has been received by this device, "
153 "has been passed up from the physical layer "
154 "and is being forwarded up the local protocol stack. "
155 "This is a non-promiscuous trace,",
157 "ns3::Packet::TracedCallback")
158 .AddTraceSource("MacRxDrop",
159 "Trace source indicating a packet was received, "
160 "but dropped before being forwarded up the stack",
162 "ns3::Packet::TracedCallback")
163 .AddTraceSource("Sniffer",
164 "Trace source simulating a non-promiscuous "
165 "packet sniffer attached to the device",
167 "ns3::Packet::TracedCallback")
168 .AddTraceSource("PromiscSniffer",
169 "Trace source simulating a promiscuous "
170 "packet sniffer attached to the device",
172 "ns3::Packet::TracedCallback")
173 .AddTraceSource("MacStateValue",
174 "The state of LrWpan Mac",
176 "ns3::TracedValueCallback::LrWpanMacState")
177 .AddTraceSource("MacIncSuperframeStatus",
178 "The period status of the incoming superframe",
180 "ns3::TracedValueCallback::SuperframeState")
181 .AddTraceSource("MacOutSuperframeStatus",
182 "The period status of the outgoing superframe",
184 "ns3::TracedValueCallback::SuperframeState")
185 .AddTraceSource("MacState",
186 "The state of LrWpan Mac",
188 "ns3::LrWpanMac::StateTracedCallback")
189 .AddTraceSource("MacSentPkt",
190 "Trace source reporting some information about "
191 "the sent packet",
193 "ns3::LrWpanMac::SentTracedCallback")
194 .AddTraceSource("IfsEnd",
195 "Trace source reporting the end of an "
196 "Interframe space (IFS)",
198 "ns3::Packet::TracedCallback");
199 return tid;
200}
201
203{
204 // First set the state to a known value, call ChangeMacState to fire trace source.
206
208
211
212 m_macRxOnWhenIdle = true;
213 m_macPanId = 0xffff;
215 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
218 m_macPromiscuousMode = false;
222 m_txPkt = nullptr;
223 m_rxPkt = nullptr;
225 m_ifs = 0;
226
227 m_macLIFSPeriod = 40;
228 m_macSIFSPeriod = 12;
229
230 m_panCoor = false;
231 m_coor = false;
232 m_macBeaconOrder = 15;
234 m_macTransactionPersistenceTime = 500; // 0x01F5
236 m_macAutoRequest = true;
237
240 m_beaconTrackingOn = false;
242
246
249
250 m_maxTxQueueSize = m_txQueue.max_size();
252
253 Ptr<UniformRandomVariable> uniformVar = CreateObject<UniformRandomVariable>();
254 uniformVar->SetAttribute("Min", DoubleValue(0.0));
255 uniformVar->SetAttribute("Max", DoubleValue(255.0));
256 m_macDsn = SequenceNumber8(uniformVar->GetValue());
257 m_macBsn = SequenceNumber8(uniformVar->GetValue());
258 m_macBeaconPayload = nullptr;
260 m_shortAddress = Mac16Address("FF:FF"); // FF:FF = The address is not assigned.
261}
262
264{
265}
266
267void
269{
271 {
272 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
273 }
274 else
275 {
276 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
277 }
278
280}
281
282void
284{
285 if (m_csmaCa)
286 {
287 m_csmaCa->Dispose();
288 m_csmaCa = nullptr;
289 }
290 m_txPkt = nullptr;
291
292 for (uint32_t i = 0; i < m_txQueue.size(); i++)
293 {
294 m_txQueue[i]->txQPkt = nullptr;
295 }
296 m_txQueue.clear();
297
298 for (uint32_t i = 0; i < m_indTxQueue.size(); i++)
299 {
300 m_indTxQueue[i]->txQPkt = nullptr;
301 }
302 m_indTxQueue.clear();
303
304 m_phy = nullptr;
305 m_mcpsDataConfirmCallback = MakeNullCallback<void, McpsDataConfirmParams>();
306 m_mcpsDataIndicationCallback = MakeNullCallback<void, McpsDataIndicationParams, Ptr<Packet>>();
307 m_mlmeStartConfirmCallback = MakeNullCallback<void, MlmeStartConfirmParams>();
309 MakeNullCallback<void, MlmeBeaconNotifyIndicationParams>();
310 m_mlmeSyncLossIndicationCallback = MakeNullCallback<void, MlmeSyncLossIndicationParams>();
311 m_mlmePollConfirmCallback = MakeNullCallback<void, MlmePollConfirmParams>();
312 m_mlmeScanConfirmCallback = MakeNullCallback<void, MlmeScanConfirmParams>();
313 m_mlmeAssociateConfirmCallback = MakeNullCallback<void, MlmeAssociateConfirmParams>();
314 m_mlmeAssociateIndicationCallback = MakeNullCallback<void, MlmeAssociateIndicationParams>();
315 m_mlmeCommStatusIndicationCallback = MakeNullCallback<void, MlmeCommStatusIndicationParams>();
316 m_mlmeOrphanIndicationCallback = MakeNullCallback<void, MlmeOrphanIndicationParams>();
317
318 m_panDescriptorList.clear();
319 m_energyDetectList.clear();
320 m_unscannedChannels.clear();
321
326
328}
329
330bool
332{
333 return m_macRxOnWhenIdle;
334}
335
336void
338{
339 NS_LOG_FUNCTION(this << rxOnWhenIdle);
340 m_macRxOnWhenIdle = rxOnWhenIdle;
341
343 {
345 {
346 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
347 }
348 else
349 {
350 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
351 }
352 }
353}
354
355void
357{
358 NS_LOG_FUNCTION(this << address);
359 m_shortAddress = address;
360}
361
362void
364{
365 NS_LOG_FUNCTION(this << address);
366 m_selfExt = address;
367}
368
371{
372 NS_LOG_FUNCTION(this);
373 return m_shortAddress;
374}
375
378{
379 NS_LOG_FUNCTION(this);
380 return m_selfExt;
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << p);
387
388 McpsDataConfirmParams confirmParams;
389 confirmParams.m_msduHandle = params.m_msduHandle;
390
391 // TODO: We need a drop trace for the case that the packet is too large or the request
392 // parameters are maleformed.
393 // The current tx drop trace is not suitable, because packets dropped using this trace
394 // carry the mac header and footer, while packets being dropped here do not have them.
395
397 m_macDsn++;
398
400 {
401 // Note, this is just testing maximum theoretical frame size per the spec
402 // The frame could still be too large once headers are put on
403 // in which case the phy will reject it instead
404 NS_LOG_ERROR(this << " packet too big: " << p->GetSize());
407 {
408 m_mcpsDataConfirmCallback(confirmParams);
409 }
410 return;
411 }
412
413 if ((params.m_srcAddrMode == NO_PANID_ADDR) && (params.m_dstAddrMode == NO_PANID_ADDR))
414 {
415 NS_LOG_ERROR(this << " Can not send packet with no Address field");
418 {
419 m_mcpsDataConfirmCallback(confirmParams);
420 }
421 return;
422 }
423 switch (params.m_srcAddrMode)
424 {
425 case NO_PANID_ADDR:
426 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
427 macHdr.SetNoPanIdComp();
428 break;
430 NS_ABORT_MSG("Can not set source address type to ADDR_MODE_RESERVED. Aborting.");
431 break;
432 case SHORT_ADDR:
433 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
435 break;
436 case EXT_ADDR:
437 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
439 break;
440 default:
441 NS_LOG_ERROR(this << " Can not send packet with incorrect Source Address mode = "
442 << params.m_srcAddrMode);
445 {
446 m_mcpsDataConfirmCallback(confirmParams);
447 }
448 return;
449 }
450 switch (params.m_dstAddrMode)
451 {
452 case NO_PANID_ADDR:
453 macHdr.SetDstAddrMode(params.m_dstAddrMode);
454 macHdr.SetNoPanIdComp();
455 break;
457 NS_ABORT_MSG("Can not set destination address type to ADDR_MODE_RESERVED. Aborting.");
458 break;
459 case SHORT_ADDR:
460 macHdr.SetDstAddrMode(params.m_dstAddrMode);
461 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstAddr);
462 break;
463 case EXT_ADDR:
464 macHdr.SetDstAddrMode(params.m_dstAddrMode);
465 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstExtAddr);
466 break;
467 default:
468 NS_LOG_ERROR(this << " Can not send packet with incorrect Destination Address mode = "
469 << params.m_dstAddrMode);
472 {
473 m_mcpsDataConfirmCallback(confirmParams);
474 }
475 return;
476 }
477
478 // IEEE 802.15.4-2006 (7.5.6.1)
479 // Src & Dst PANs are identical, PAN compression is ON
480 // only the dst PAN is serialized making the MAC header 2 bytes smaller
481 if ((params.m_dstAddrMode != NO_PANID_ADDR && params.m_srcAddrMode != NO_PANID_ADDR) &&
482 (macHdr.GetDstPanId() == macHdr.GetSrcPanId()))
483 {
484 macHdr.SetPanIdComp();
485 }
486
487 macHdr.SetSecDisable();
488 // extract the first 3 bits in TxOptions
489 int b0 = params.m_txOptions & TX_OPTION_ACK;
490 int b1 = params.m_txOptions & TX_OPTION_GTS;
491 int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
492
493 if (b0 == TX_OPTION_ACK)
494 {
495 // Set AckReq bit only if the destination is not the broadcast address.
496 if (macHdr.GetDstAddrMode() == SHORT_ADDR)
497 {
498 // short address and ACK requested.
499 Mac16Address shortAddr = macHdr.GetShortDstAddr();
500 if (shortAddr.IsBroadcast() || shortAddr.IsMulticast())
501 {
502 NS_LOG_LOGIC("LrWpanMac::McpsDataRequest: requested an ACK on broadcast or "
503 "multicast destination ("
504 << shortAddr << ") - forcefully removing it.");
505 macHdr.SetNoAckReq();
506 params.m_txOptions &= ~uint8_t(TX_OPTION_ACK);
507 }
508 else
509 {
510 macHdr.SetAckReq();
511 }
512 }
513 else
514 {
515 // other address (not short) and ACK requested
516 macHdr.SetAckReq();
517 }
518 }
519 else
520 {
521 macHdr.SetNoAckReq();
522 }
523
524 if (b1 == TX_OPTION_GTS)
525 {
526 // TODO:GTS Transmission
527 }
528 else if (b2 == TX_OPTION_INDIRECT)
529 {
530 // Indirect Tx
531 // A COORDINATOR will save the packet in the pending queue and await for data
532 // requests from its associated devices. The devices are aware of pending data,
533 // from the pending bit information extracted from the received beacon.
534 // A DEVICE must be tracking beacons (MLME-SYNC.request is running) before attempting
535 // request data from the coordinator.
536
537 // Indirect Transmission can only be done by PAN coordinator or coordinators.
539 p->AddHeader(macHdr);
540
541 LrWpanMacTrailer macTrailer;
542 // Calculate FCS if the global attribute ChecksumEnabled is set.
544 {
545 macTrailer.EnableFcs(true);
546 macTrailer.SetFcs(p);
547 }
548 p->AddTrailer(macTrailer);
549
550 NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
551 // Note: The current Pending transaction list should work for indirect transmissions.
552 // However, this is not tested yet. For now, we block the use of indirect transmissions.
553 // TODO: Save packet in the Pending Transaction list.
554 // EnqueueInd (p);
555 }
556 else
557 {
558 // Direct Tx
559 // From this point the packet will be pushed to a Tx queue and immediately
560 // use a slotted (beacon-enabled) or unslotted (nonbeacon-enabled) version of CSMA/CA
561 // before sending the packet, depending on whether it has previously
562 // received a valid beacon or not.
563
564 p->AddHeader(macHdr);
565
566 LrWpanMacTrailer macTrailer;
567 // Calculate FCS if the global attribute ChecksumEnabled is set.
569 {
570 macTrailer.EnableFcs(true);
571 macTrailer.SetFcs(p);
572 }
573 p->AddTrailer(macTrailer);
574
575 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
576 txQElement->txQMsduHandle = params.m_msduHandle;
577 txQElement->txQPkt = p;
578 EnqueueTxQElement(txQElement);
579 CheckQueue();
580 }
581}
582
583void
585{
586 NS_LOG_FUNCTION(this);
588
589 MlmeStartConfirmParams confirmParams;
590
591 if (GetShortAddress() == Mac16Address("ff:ff"))
592 {
593 NS_LOG_ERROR(this << " Invalid MAC short address");
596 {
597 m_mlmeStartConfirmCallback(confirmParams);
598 }
599 return;
600 }
601
602 if ((params.m_bcnOrd > 15) || (params.m_sfrmOrd > params.m_bcnOrd))
603 {
606 {
607 m_mlmeStartConfirmCallback(confirmParams);
608 }
609 NS_LOG_ERROR(this << "Incorrect superframe order or beacon order.");
610 return;
611 }
612
613 // Mark primitive as pending and save the start params while the new page and channel is set.
615 m_startParams = params;
616
617 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
618 pibAttr->phyCurrentPage = m_startParams.m_logChPage;
619 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentPage, pibAttr);
620}
621
622void
624{
625 NS_LOG_FUNCTION(this);
626
627 MlmeScanConfirmParams confirmParams;
628 confirmParams.m_scanType = params.m_scanType;
629 confirmParams.m_chPage = params.m_chPage;
630
632 {
634 {
636 m_mlmeScanConfirmCallback(confirmParams);
637 }
638 NS_LOG_ERROR(this << " A channel scan is already in progress");
639 return;
640 }
641
642 if (params.m_scanDuration > 14 || params.m_scanType > MLMESCAN_ORPHAN)
643 {
645 {
647 m_mlmeScanConfirmCallback(confirmParams);
648 }
649 NS_LOG_ERROR(this << "Invalid scan duration or unsupported scan type");
650 return;
651 }
652 // Temporary store macPanId and set macPanId to 0xFFFF to accept all beacons.
654 m_macPanId = 0xFFFF;
655
656 m_panDescriptorList.clear();
657 m_energyDetectList.clear();
658 m_unscannedChannels.clear();
659
660 // TODO: stop beacon transmission
661
662 // Cancel any ongoing CSMA/CA operations and set to unslotted mode for scan
663 m_csmaCa->Cancel();
669 m_csmaCa->SetUnSlottedCsmaCa();
670
672
673 // Mark primitive as pending and save the scan params while the new page and/or channel is set.
674 m_scanParams = params;
676
677 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
678 pibAttr->phyCurrentPage = params.m_chPage;
679 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentPage, pibAttr);
680}
681
682void
684{
685 NS_LOG_FUNCTION(this);
686
687 // Association is typically preceded by beacon reception and a MLME-SCAN.request, therefore,
688 // the values of the Associate.request params usually come from the information
689 // obtained from those operations.
691 m_associateParams = params;
692 bool invalidRequest = false;
693
694 if (params.m_coordPanId == 0xffff)
695 {
696 invalidRequest = true;
697 }
698
699 if (!invalidRequest && params.m_coordAddrMode == SHORT_ADDR)
700 {
701 if (params.m_coordShortAddr == Mac16Address("ff:ff") ||
702 params.m_coordShortAddr == Mac16Address("ff:fe"))
703 {
704 invalidRequest = true;
705 }
706 }
707 else if (!invalidRequest && params.m_coordAddrMode == EXT_ADDR)
708 {
709 if (params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ff") ||
710 params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed"))
711 {
712 invalidRequest = true;
713 }
714 }
715
716 if (invalidRequest)
717 {
720 NS_LOG_ERROR(this << " Invalid PAN id in Association request");
722 {
723 MlmeAssociateConfirmParams confirmParams;
724 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
726 m_mlmeAssociateConfirmCallback(confirmParams);
727 }
728 }
729 else
730 {
731 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
732 pibAttr->phyCurrentPage = params.m_chPage;
733 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentPage, pibAttr);
734 }
735}
736
737void
739{
740 // the primitive is no longer pending (channel & page are set)
742 // As described in IEEE 802.15.4-2011 (Section 5.1.3.1)
745 {
747 }
748 else
749 {
752 }
753
755}
756
757void
759{
760 // Associate Short Address (m_assocShortAddr)
761 // FF:FF = Association Request failed
762 // FF:FE = The association request is accepted, but the device should use its extended address
763 // Other = The assigned short address by the coordinator
764
765 NS_LOG_FUNCTION(this);
766
768 m_macDsn++;
769 LrWpanMacTrailer macTrailer;
770 Ptr<Packet> commandPacket = Create<Packet>();
771
772 // Mac header Assoc. Response Comm. See 802.15.4-2011 (Section 5.3.2.1)
775 macHdr.SetPanIdComp();
776 macHdr.SetDstAddrFields(m_macPanId, params.m_extDevAddr);
777 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
778
780 macPayload.SetShortAddr(params.m_assocShortAddr);
781 macPayload.SetAssociationStatus(static_cast<uint8_t>(params.m_status));
782
783 macHdr.SetSecDisable();
784 macHdr.SetAckReq();
785
786 commandPacket->AddHeader(macPayload);
787 commandPacket->AddHeader(macHdr);
788
789 // Calculate FCS if the global attribute ChecksumEnabled is set.
791 {
792 macTrailer.EnableFcs(true);
793 macTrailer.SetFcs(commandPacket);
794 }
795
796 commandPacket->AddTrailer(macTrailer);
797
798 // Save packet in the Pending Transaction list.
799 EnqueueInd(commandPacket);
800}
801
802void
804{
805 NS_LOG_FUNCTION(this);
806 // Mac header Coordinator realigment Command
807 // See 802.15.4-2011 (Section 6.2.7.2)
809 m_macDsn++;
810 LrWpanMacTrailer macTrailer;
811 Ptr<Packet> commandPacket = Create<Packet>();
812 macHdr.SetPanIdComp();
814 macHdr.SetDstAddrFields(0xffff, params.m_orphanAddr);
815
818 macHdr.SetSrcAddrFields(m_macPanId, Mac16Address("FF:FF"));
819
820 macHdr.SetFrameVer(0x01);
821 macHdr.SetSecDisable();
822 macHdr.SetAckReq();
823
825 macPayload.SetPanId(m_macPanId);
827 macPayload.SetChannel(m_phy->GetCurrentChannelNum());
828 macPayload.SetPage(m_phy->GetCurrentPage());
829
830 if (params.m_assocMember)
831 {
832 // The orphan device was associated with the coordinator
833
834 // Either FF:FE for extended address mode
835 // or the short address assigned by the coord.
836 macPayload.SetShortAddr(params.m_shortAddr);
837 }
838 else
839 {
840 // The orphan device was NOT associated with the coordinator
841 macPayload.SetShortAddr(Mac16Address("FF:FF"));
842 }
843
844 commandPacket->AddHeader(macPayload);
845 commandPacket->AddHeader(macHdr);
846
847 // Calculate FCS if the global attribute ChecksumEnabled is set.
849 {
850 macTrailer.EnableFcs(true);
851 macTrailer.SetFcs(commandPacket);
852 }
853
854 commandPacket->AddTrailer(macTrailer);
855
856 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
857 txQElement->txQPkt = commandPacket;
858 EnqueueTxQElement(txQElement);
859 CheckQueue();
860}
861
862void
864{
865 NS_LOG_FUNCTION(this);
866 NS_ASSERT(params.m_logCh <= 26 && m_macPanId != 0xffff);
867
868 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
869 // change phy current logical channel
870 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
871 pibAttr->phyCurrentChannel = params.m_logCh;
872 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentChannel, pibAttr);
873
874 // Enable Phy receiver
875 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
876
877 uint64_t searchSymbols;
878 Time searchBeaconTime;
879
881 {
883 }
884
885 if (params.m_trackBcn)
886 {
888 // search for a beacon for a time = incomingSuperframe symbols + 960 symbols
889 searchSymbols =
891 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
892 m_beaconTrackingOn = true;
894 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
895 }
896 else
897 {
898 m_beaconTrackingOn = false;
899 }
900}
901
902void
904{
905 NS_LOG_FUNCTION(this);
906
908 m_macBsn++;
909
911
912 Ptr<Packet> beaconPacket = Create<Packet>();
913 // TODO: complete poll request (part of indirect transmissions)
914 NS_FATAL_ERROR(this << " Poll request currently not supported");
915}
916
917void
919{
920 MlmeSetConfirmParams confirmParams;
921 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
922
923 switch (id)
924 {
925 case macBeaconPayload:
926 if (attribute->macBeaconPayload->GetSize() > lrwpan::aMaxBeaconPayloadLength)
927 {
929 }
930 else
931 {
932 m_macBeaconPayload = attribute->macBeaconPayload;
933 m_macBeaconPayloadLength = attribute->macBeaconPayload->GetSize();
934 }
935 break;
938 break;
939 case macShortAddress:
940 m_shortAddress = attribute->macShortAddress;
941 break;
943 confirmParams.m_status = LrWpanMacStatus::READ_ONLY;
944 break;
945 case macPanId:
947 break;
948 default:
949 // TODO: Add support for setting other attributes
951 break;
952 }
953
955 {
956 confirmParams.id = id;
957 m_mlmeSetConfirmCallback(confirmParams);
958 }
959}
960
961void
963{
965 Ptr<LrWpanMacPibAttributes> attributes = Create<LrWpanMacPibAttributes>();
966
967 switch (id)
968 {
969 case macBeaconPayload:
970 attributes->macBeaconPayload = m_macBeaconPayload;
971 break;
973 attributes->macBeaconPayloadLength = m_macBeaconPayloadLength;
974 break;
975 case macShortAddress:
976 attributes->macShortAddress = m_shortAddress;
977 break;
979 attributes->macExtendedAddress = m_selfExt;
980 break;
981 case macPanId:
982 attributes->macPanId = m_macPanId;
983 break;
984 case pCurrentChannel:
985 attributes->pCurrentChannel = m_phy->GetCurrentChannelNum();
986 break;
987 case pCurrentPage:
988 attributes->pCurrentPage = m_phy->GetCurrentPage();
989 break;
990 default:
992 break;
993 }
994
996 {
997 m_mlmeGetConfirmCallback(status, id, attributes);
998 }
999}
1000
1001void
1003{
1004 NS_LOG_FUNCTION(this);
1006
1008 m_macBsn++;
1009 BeaconPayloadHeader macPayload;
1010 Ptr<Packet> beaconPacket;
1011 LrWpanMacTrailer macTrailer;
1012
1013 if (m_macBeaconPayload == nullptr)
1014 {
1015 beaconPacket = Create<Packet>();
1016 }
1017 else
1018 {
1019 beaconPacket = m_macBeaconPayload;
1020 }
1021
1023 macHdr.SetDstAddrFields(GetPanId(), Mac16Address("ff:ff"));
1024
1025 // see IEEE 802.15.4-2011 Section 5.1.2.4
1026 if (GetShortAddress() == Mac16Address("ff:fe"))
1027 {
1030 }
1031 else
1032 {
1035 }
1036
1037 macHdr.SetSecDisable();
1038 macHdr.SetNoAckReq();
1039
1041 macPayload.SetGtsFields(GetGtsFields());
1043
1044 beaconPacket->AddHeader(macPayload);
1045 beaconPacket->AddHeader(macHdr);
1046
1047 // Calculate FCS if the global attribute ChecksumEnabled is set.
1049 {
1050 macTrailer.EnableFcs(true);
1051 macTrailer.SetFcs(beaconPacket);
1052 }
1053
1054 beaconPacket->AddTrailer(macTrailer);
1055
1056 // Set the Beacon packet to be transmitted
1057 m_txPkt = beaconPacket;
1058
1059 if (m_csmaCa->IsSlottedCsmaCa())
1060 {
1062 NS_LOG_DEBUG("Outgoing superframe Active Portion (Beacon + CAP + CFP): "
1063 << m_superframeDuration << " symbols");
1064 }
1065
1067 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
1068}
1069
1070void
1072{
1073 NS_LOG_FUNCTION(this);
1074
1076 m_macDsn++;
1077 LrWpanMacTrailer macTrailer;
1078 Ptr<Packet> commandPacket = Create<Packet>();
1079
1080 // Beacon Request Command Mac header values See IEEE 802.15.4-2011 (Section 5.3.7)
1081 macHdr.SetNoPanIdComp();
1084
1085 // Not associated PAN, broadcast dst address
1086 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1087
1088 macHdr.SetSecDisable();
1089 macHdr.SetNoAckReq();
1090
1091 CommandPayloadHeader macPayload;
1093
1094 commandPacket->AddHeader(macPayload);
1095 commandPacket->AddHeader(macHdr);
1096
1097 // Calculate FCS if the global attribute ChecksumEnabled is set.
1099 {
1100 macTrailer.EnableFcs(true);
1101 macTrailer.SetFcs(commandPacket);
1102 }
1103
1104 commandPacket->AddTrailer(macTrailer);
1105
1106 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1107 txQElement->txQPkt = commandPacket;
1108 EnqueueTxQElement(txQElement);
1109 CheckQueue();
1110}
1111
1112void
1114{
1116 m_macDsn++;
1117 LrWpanMacTrailer macTrailer;
1118 Ptr<Packet> commandPacket = Create<Packet>();
1119
1120 // See IEEE 802.15.4-2011 (5.3.6)
1121 macHdr.SetPanIdComp();
1122
1124 macHdr.SetSrcAddrFields(0xFFFF, GetExtendedAddress());
1125
1127 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1128
1129 macHdr.SetSecDisable();
1130 macHdr.SetNoAckReq();
1131
1132 CommandPayloadHeader macPayload;
1134
1135 commandPacket->AddHeader(macPayload);
1136 commandPacket->AddHeader(macHdr);
1137
1138 // Calculate FCS if the global attribute ChecksumEnabled is set.
1140 {
1141 macTrailer.EnableFcs(true);
1142 macTrailer.SetFcs(commandPacket);
1143 }
1144
1145 commandPacket->AddTrailer(macTrailer);
1146
1147 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1148 txQElement->txQPkt = commandPacket;
1149 EnqueueTxQElement(txQElement);
1150 CheckQueue();
1151}
1152
1153void
1155{
1156 NS_LOG_FUNCTION(this);
1157
1159 m_macDsn++;
1160 LrWpanMacTrailer macTrailer;
1161 Ptr<Packet> commandPacket = Create<Packet>();
1162
1163 // Assoc. Req. Comm. Mac header values See IEEE 802.15.4-2011 (Section 5.3.1.1)
1165 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
1166
1168 {
1171 }
1172 else
1173 {
1176 }
1177
1178 macHdr.SetSecDisable();
1179 macHdr.SetAckReq();
1180
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
1196 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1197 txQElement->txQPkt = commandPacket;
1198 EnqueueTxQElement(txQElement);
1199 CheckQueue();
1200}
1201
1202void
1204{
1205 // See IEEE 802.15.4-2011 (Section 5.3.5)
1206 // This command can be sent for 3 different situations:
1207 // a) In response to a beacon indicating that there is data for the device.
1208 // b) Triggered by MLME-POLL.request.
1209 // c) To follow an ACK of an Association Request command and continue the associate process.
1210
1211 // TODO: Implementation of a) and b) will be done when Indirect transmissions are fully
1212 // supported.
1213 // for now, only case c) is considered.
1214
1215 NS_LOG_FUNCTION(this);
1216
1218 m_macDsn++;
1219 LrWpanMacTrailer macTrailer;
1220 Ptr<Packet> commandPacket = Create<Packet>();
1221
1222 // Mac Header values (Section 5.3.5)
1224 macHdr.SetSrcAddrFields(0xffff, m_selfExt);
1225
1226 if (m_macCoordShortAddress == Mac16Address("ff:fe"))
1227 {
1230 }
1231 else
1232 {
1235 }
1236
1237 macHdr.SetSecDisable();
1238 macHdr.SetAckReq();
1239
1241
1242 commandPacket->AddHeader(macPayload);
1243 commandPacket->AddHeader(macHdr);
1244
1245 // Calculate FCS if the global attribute ChecksumEnabled is set.
1247 {
1248 macTrailer.EnableFcs(true);
1249 macTrailer.SetFcs(commandPacket);
1250 }
1251
1252 commandPacket->AddTrailer(macTrailer);
1253
1254 // Set the Command packet to be transmitted
1255 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1256 txQElement->txQPkt = commandPacket;
1257 EnqueueTxQElement(txQElement);
1258 CheckQueue();
1259}
1260
1261void
1263{
1264 LrWpanMacHeader receivedMacHdr;
1265 rxDataReqPkt->RemoveHeader(receivedMacHdr);
1266 CommandPayloadHeader receivedMacPayload;
1267 rxDataReqPkt->RemoveHeader(receivedMacPayload);
1268
1270
1271 Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
1272 bool elementFound;
1273 elementFound = DequeueInd(receivedMacHdr.GetExtSrcAddr(), indTxQElement);
1274 if (elementFound)
1275 {
1276 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1277 txQElement->txQPkt = indTxQElement->txQPkt;
1278 m_txQueue.emplace_back(txQElement);
1279 }
1280 else
1281 {
1282 NS_LOG_DEBUG("Requested element not found in pending list");
1283 }
1284}
1285
1286void
1288{
1289 // Association response command was not received, return to default values.
1290 m_macPanId = 0xffff;
1292 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1293
1295 {
1296 MlmeAssociateConfirmParams confirmParams;
1297 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
1298 confirmParams.m_status = LrWpanMacStatus::NO_DATA;
1299 m_mlmeAssociateConfirmCallback(confirmParams);
1300 }
1301}
1302
1303void
1305{
1306 NS_LOG_FUNCTION(this);
1307 // The primitive is no longer pending (Channel & Page have been set)
1309
1310 if (m_startParams.m_coorRealgn) // Coordinator Realignment
1311 {
1312 // TODO: Send realignment request command frame in CSMA/CA
1313 NS_LOG_ERROR(this << " Coordinator realignment request not supported");
1314 return;
1315 }
1316 else
1317 {
1319 {
1320 m_panCoor = true;
1321 }
1322
1323 m_coor = true;
1325
1326 NS_ASSERT(m_startParams.m_PanId != 0xffff);
1327
1329 if (m_macBeaconOrder == 15)
1330 {
1331 // Non-beacon enabled PAN
1332 // Cancel any ongoing events and CSMA-CA process
1334 m_fnlCapSlot = 15;
1335 m_beaconInterval = 0;
1336
1337 m_csmaCa->Cancel();
1346
1347 m_csmaCa->SetUnSlottedCsmaCa();
1348
1350 {
1351 MlmeStartConfirmParams confirmParams;
1352 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
1353 m_mlmeStartConfirmCallback(confirmParams);
1354 }
1355
1356 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
1357 }
1358 else
1359 {
1361 m_csmaCa->SetBatteryLifeExtension(m_startParams.m_battLifeExt);
1362
1363 m_csmaCa->SetSlottedCsmaCa();
1364
1365 // TODO: Calculate the real Final CAP slot (requires GTS implementation)
1366 // FinalCapSlot = Superframe duration slots - CFP slots.
1367 // In the current implementation the value of the final cap slot is equal to
1368 // the total number of possible slots in the superframe (15).
1369 m_fnlCapSlot = 15;
1370
1373 m_superframeDuration = (static_cast<uint32_t>(1 << m_macSuperframeOrder)) *
1375
1376 // TODO: change the beacon sending according to the startTime parameter (if not PAN
1377 // coordinator)
1378
1380 }
1381 }
1382}
1383
1384void
1386{
1387 NS_LOG_FUNCTION(this);
1388
1390
1391 bool channelFound = false;
1392
1393 for (int i = m_channelScanIndex; i <= 26; i++)
1394 {
1396 {
1397 channelFound = true;
1398 break;
1399 }
1401 }
1402
1403 if (channelFound)
1404 {
1405 // Switch to the next channel in the list and restart scan
1406 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
1407 pibAttr->phyCurrentChannel = m_channelScanIndex;
1408 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1409 }
1410 else
1411 {
1412 // All channels in the list scan completed.
1413 // Return variables to the values before the scan and return the status to the next layer.
1415 m_macPanIdScan = 0;
1416
1417 // TODO: restart beacon transmissions that were active before the beginning of the scan
1418 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1419 MlmeScanConfirmParams confirmParams;
1420 confirmParams.m_chPage = m_scanParams.m_chPage;
1421 confirmParams.m_scanType = m_scanParams.m_scanType;
1422 confirmParams.m_energyDetList = {};
1423 confirmParams.m_unscannedCh = m_unscannedChannels;
1424 confirmParams.m_resultListSize = m_panDescriptorList.size();
1425
1426 // See IEEE 802.15.4-2011, Table 31 (panDescriptorList value on macAutoRequest)
1427 // and Section 6.2.10.2
1428 switch (confirmParams.m_scanType)
1429 {
1430 case MLMESCAN_PASSIVE:
1431 if (m_macAutoRequest)
1432 {
1433 confirmParams.m_panDescList = m_panDescriptorList;
1434 }
1435 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
1436 break;
1437 case MLMESCAN_ACTIVE:
1438 if (m_panDescriptorList.empty())
1439 {
1440 confirmParams.m_status = LrWpanMacStatus::NO_BEACON;
1441 }
1442 else
1443 {
1444 if (m_macAutoRequest)
1445 {
1446 confirmParams.m_panDescList = m_panDescriptorList;
1447 }
1448 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
1449 }
1450 break;
1451 case MLMESCAN_ORPHAN:
1452 confirmParams.m_panDescList = {};
1453 confirmParams.m_status = LrWpanMacStatus::NO_BEACON;
1454 confirmParams.m_resultListSize = 0;
1455 // The device lost track of the coordinator and was unable
1456 // to locate it, disassociate from the network.
1457 m_macPanId = 0xffff;
1458 m_shortAddress = Mac16Address("FF:FF");
1460 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1461 break;
1462 default:
1463 NS_LOG_ERROR(this << " Invalid scan type");
1464 }
1465
1468 m_scanParams = {};
1469
1471 {
1472 m_mlmeScanConfirmCallback(confirmParams);
1473 }
1474 }
1475}
1476
1477void
1479{
1480 NS_LOG_FUNCTION(this);
1481 // Add the results of channel energy scan to the detectList
1483 m_maxEnergyLevel = 0;
1484
1486
1487 bool channelFound = false;
1488 for (int i = m_channelScanIndex; i <= 26; i++)
1489 {
1491 {
1492 channelFound = true;
1493 break;
1494 }
1496 }
1497
1498 if (channelFound)
1499 {
1500 // switch to the next channel in the list and restart scan
1501 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
1502 pibAttr->phyCurrentChannel = m_channelScanIndex;
1503 m_phy->PlmeSetAttributeRequest(LrWpanPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1504 }
1505 else
1506 {
1507 // Scan on all channels on the list completed
1508 // Return to the MAC values previous to start of the first scan.
1510 m_macPanIdScan = 0;
1511
1512 // TODO: restart beacon transmissions that were active before the beginning of the scan
1513 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1514
1515 // All channels scanned, report success
1516 MlmeScanConfirmParams confirmParams;
1517 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
1518 confirmParams.m_chPage = m_phy->GetCurrentPage();
1519 confirmParams.m_scanType = m_scanParams.m_scanType;
1520 confirmParams.m_energyDetList = m_energyDetectList;
1521 confirmParams.m_resultListSize = m_energyDetectList.size();
1522
1525 m_scanParams = {};
1526
1528 {
1529 m_mlmeScanConfirmCallback(confirmParams);
1530 }
1531 }
1532}
1533
1534void
1536{
1537 uint32_t activeSlot;
1538 uint64_t capDuration;
1539 Time endCapTime;
1540 uint64_t symbolRate;
1541
1542 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1543
1544 if (superframeType == OUTGOING)
1545 {
1547 activeSlot = m_superframeDuration / 16;
1548 capDuration = activeSlot * (m_fnlCapSlot + 1);
1549 endCapTime = Seconds((double)capDuration / symbolRate);
1550 // Obtain the end of the CAP by adjust the time it took to send the beacon
1551 endCapTime -= (Simulator::Now() - m_macBeaconTxTime);
1552
1553 NS_LOG_DEBUG("Outgoing superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1554 << " symbols (" << endCapTime.As(Time::S)
1555 << ")");
1556 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1557
1558 m_capEvent =
1560 }
1561 else
1562 {
1564 activeSlot = m_incomingSuperframeDuration / 16;
1565 capDuration = activeSlot * (m_incomingFnlCapSlot + 1);
1566 endCapTime = Seconds((double)capDuration / symbolRate);
1567 // Obtain the end of the CAP by adjust the time it took to receive the beacon
1568 endCapTime -= (Simulator::Now() - m_macBeaconRxTime);
1569
1570 NS_LOG_DEBUG("Incoming superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1571 << " symbols (" << endCapTime.As(Time::S)
1572 << ")");
1573 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1574
1575 m_capEvent =
1577 }
1578
1579 CheckQueue();
1580}
1581
1582void
1584{
1585 uint32_t activeSlot;
1586 uint64_t cfpDuration;
1587 Time endCfpTime;
1588 uint64_t symbolRate;
1589
1590 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1591
1592 if (superframeType == INCOMING)
1593 {
1594 activeSlot = m_incomingSuperframeDuration / 16;
1595 cfpDuration = activeSlot * (15 - m_incomingFnlCapSlot);
1596 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1597 if (cfpDuration > 0)
1598 {
1600 }
1601
1602 NS_LOG_DEBUG("Incoming superframe CFP duration " << cfpDuration << " symbols ("
1603 << endCfpTime.As(Time::S) << ")");
1604
1607 this,
1609 }
1610 else
1611 {
1612 activeSlot = m_superframeDuration / 16;
1613 cfpDuration = activeSlot * (15 - m_fnlCapSlot);
1614 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1615
1616 if (cfpDuration > 0)
1617 {
1619 }
1620
1621 NS_LOG_DEBUG("Outgoing superframe CFP duration " << cfpDuration << " symbols ("
1622 << endCfpTime.As(Time::S) << ")");
1623
1624 m_cfpEvent = Simulator::Schedule(endCfpTime,
1626 this,
1628 }
1629 // TODO: Start transmit or receive GTS here.
1630}
1631
1632void
1634{
1635 uint64_t inactiveDuration;
1636 Time endInactiveTime;
1637 uint64_t symbolRate;
1638
1639 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1640
1641 if (superframeType == INCOMING)
1642 {
1644 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1645
1646 if (inactiveDuration > 0)
1647 {
1649 }
1650
1651 NS_LOG_DEBUG("Incoming superframe Inactive Portion duration "
1652 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1653 m_beaconEvent = Simulator::Schedule(endInactiveTime, &LrWpanMac::AwaitBeacon, this);
1654 }
1655 else
1656 {
1657 inactiveDuration = m_beaconInterval - m_superframeDuration;
1658 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1659
1660 if (inactiveDuration > 0)
1661 {
1663 }
1664
1665 NS_LOG_DEBUG("Outgoing superframe Inactive Portion duration "
1666 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1668 }
1669}
1670
1671void
1673{
1675
1676 // TODO: If the device waits more than the expected time to receive the beacon (wait = 46
1677 // symbols for default beacon size)
1678 // it should continue with the start of the incoming CAP even if it did not receive the
1679 // beacon. At the moment, the start of the incoming CAP is only triggered if the beacon is
1680 // received. See MLME-SyncLoss for details.
1681}
1682
1683void
1685{
1686 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1687
1689 {
1690 MlmeSyncLossIndicationParams syncLossParams;
1691 // syncLossParams.m_logCh =
1693 syncLossParams.m_panId = m_macPanId;
1694 m_mlmeSyncLossIndicationCallback(syncLossParams);
1695
1696 m_beaconTrackingOn = false;
1697 m_numLostBeacons = 0;
1698 }
1699 else
1700 {
1702
1703 // Search for one more beacon
1704 uint64_t searchSymbols;
1705 Time searchBeaconTime;
1706 searchSymbols =
1708 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
1710 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
1711 }
1712}
1713
1714void
1716{
1717 NS_LOG_FUNCTION(this);
1718 // Pull a packet from the queue and start sending if we are not already sending.
1720 {
1721 if (m_csmaCa->IsUnSlottedCsmaCa() || (m_outSuperframeStatus == CAP && m_coor) ||
1723 {
1724 // check MAC is not in a IFS
1725 if (!m_ifsEvent.IsRunning())
1726 {
1727 Ptr<TxQueueElement> txQElement = m_txQueue.front();
1728 m_txPkt = txQElement->txQPkt;
1729
1732 }
1733 }
1734 }
1735}
1736
1737uint16_t
1739{
1740 SuperframeField sfrmSpec;
1741
1744 sfrmSpec.SetFinalCapSlot(m_fnlCapSlot);
1745
1746 if (m_csmaCa->GetBatteryLifeExtension())
1747 {
1748 sfrmSpec.SetBattLifeExt(true);
1749 }
1750
1751 if (m_panCoor)
1752 {
1753 sfrmSpec.SetPanCoor(true);
1754 }
1755
1756 // used to associate devices via Beacons
1758 {
1759 sfrmSpec.SetAssocPermit(true);
1760 }
1761
1762 return sfrmSpec.GetSuperframe();
1763}
1764
1767{
1768 GtsFields gtsFields;
1769
1770 // TODO: Logic to populate the GTS Fields from local information here
1771
1772 return gtsFields;
1773}
1774
1777{
1778 PendingAddrFields pndAddrFields;
1779
1780 // TODO: Logic to populate the Pending Address Fields from local information here
1781 return pndAddrFields;
1782}
1783
1784void
1786{
1787 m_csmaCa = csmaCa;
1788}
1789
1790void
1792{
1793 m_phy = phy;
1794}
1795
1798{
1799 return m_phy;
1800}
1801
1802void
1804{
1807 NS_LOG_FUNCTION(this << psduLength << p << (uint16_t)lqi);
1808
1809 bool acceptFrame;
1810
1811 // from sec 7.5.6.2 Reception and rejection, Std802.15.4-2006
1812 // level 1 filtering, test FCS field and reject if frame fails
1813 // level 2 filtering if promiscuous mode pass frame to higher layer otherwise perform level 3
1814 // filtering level 3 filtering accept frame if Frame type and version is not reserved, and if
1815 // there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
1816 // shortDstAddr then shortDstAddr =shortMacAddr or broadcastAddr, and if beacon frame then
1817 // srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
1818 // srcPanId=m_macPanId
1819
1820 Ptr<Packet> originalPkt = p->Copy(); // because we will strip headers
1821 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1822 m_promiscSnifferTrace(originalPkt);
1823
1824 m_macPromiscRxTrace(originalPkt);
1825 // XXX no rejection tracing (to macRxDropTrace) being performed below
1826
1827 LrWpanMacTrailer receivedMacTrailer;
1828 p->RemoveTrailer(receivedMacTrailer);
1830 {
1831 receivedMacTrailer.EnableFcs(true);
1832 }
1833
1834 // level 1 filtering
1835 if (!receivedMacTrailer.CheckFcs(p))
1836 {
1837 m_macRxDropTrace(originalPkt);
1838 }
1839 else
1840 {
1841 LrWpanMacHeader receivedMacHdr;
1842 p->RemoveHeader(receivedMacHdr);
1843
1845 params.m_dsn = receivedMacHdr.GetSeqNum();
1846 params.m_mpduLinkQuality = lqi;
1847 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
1848 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
1849 switch (params.m_srcAddrMode)
1850 {
1851 case SHORT_ADDR:
1852 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
1853 break;
1854 case EXT_ADDR:
1855 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
1856 break;
1857 default:
1858 break;
1859 }
1860 params.m_dstPanId = receivedMacHdr.GetDstPanId();
1861 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
1862 switch (params.m_dstAddrMode)
1863 {
1864 case SHORT_ADDR:
1865 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
1866 break;
1867 case EXT_ADDR:
1868 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
1869 break;
1870 default:
1871 break;
1872 }
1873
1875 {
1876 // level 2 filtering
1877 if (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
1878 {
1879 NS_LOG_DEBUG("Packet from " << params.m_srcAddr);
1880 NS_LOG_DEBUG("Packet to " << params.m_dstAddr);
1881 }
1882 else if (receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
1883 {
1884 NS_LOG_DEBUG("Packet from " << params.m_srcExtAddr);
1885 NS_LOG_DEBUG("Packet to " << params.m_dstExtAddr);
1886 }
1887
1888 // TODO: Fix here, this should trigger different Indication Callbacks
1889 // depending the type of frame received (data,command, beacon)
1891 {
1892 NS_LOG_DEBUG("promiscuous mode, forwarding up");
1894 }
1895 else
1896 {
1897 NS_LOG_ERROR(this << " Data Indication Callback not initialized");
1898 }
1899 }
1900 else
1901 {
1902 // level 3 frame filtering
1903 acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
1904
1905 if (acceptFrame)
1906 {
1907 acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
1908 }
1909
1910 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
1911 {
1912 // Accept frame if one of the following is true:
1913
1914 // 1) Have the same macPanId
1915 // 2) Is Message to all PANs
1916 // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
1917 acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
1918 receivedMacHdr.GetDstPanId() == 0xffff) ||
1919 (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
1920 (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
1921 }
1922
1923 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
1924 {
1925 if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
1926 {
1927 // unicast, for me
1928 acceptFrame = true;
1929 }
1930 else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
1931 receivedMacHdr.GetShortDstAddr().IsMulticast())
1932 {
1933 // Broadcast or multicast.
1934 // Discard broadcast/multicast with the ACK bit set.
1935 acceptFrame = !receivedMacHdr.IsAckReq();
1936 }
1937 else
1938 {
1939 acceptFrame = false;
1940 }
1941 }
1942
1943 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
1944 {
1945 acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_selfExt);
1946 }
1947
1948 if (acceptFrame && m_scanEvent.IsRunning())
1949 {
1950 if (!receivedMacHdr.IsBeacon())
1951 {
1952 acceptFrame = false;
1953 }
1954 }
1955 else if (acceptFrame && m_scanOrphanEvent.IsRunning())
1956 {
1957 if (!receivedMacHdr.IsCommand())
1958 {
1959 acceptFrame = false;
1960 }
1961 }
1962 else if (m_scanEnergyEvent.IsRunning())
1963 {
1964 // Reject any frames if energy scan is running
1965 acceptFrame = false;
1966 }
1967
1968 // Check device is panCoor with association permit when receiving Association Request
1969 // Commands.
1970 // TODO:: Simple coordinators should also be able to receive it (currently only Pan
1971 // Coordinators are checked)
1972 if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
1973 {
1974 CommandPayloadHeader receivedMacPayload;
1975 p->PeekHeader(receivedMacPayload);
1976
1977 if (receivedMacPayload.GetCommandFrameType() ==
1980 {
1981 acceptFrame = false;
1982 }
1983
1984 // Although ACKs do not use CSMA to to be transmitted, we need to make sure
1985 // that the transmitted ACK will not collide with the transmission of a beacon
1986 // when beacon-enabled mode is running in the coordinator.
1987 if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsRunning()))
1988 {
1989 Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
1990 uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
1991 ceil(6 * m_phy->GetPhySymbolsPerOctet());
1992 Time ackTime = Seconds((double)ackSymbols / symbolRate);
1993
1994 if (ackTime >= timeLeftInCap)
1995 {
1996 NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
1997 "before the end of CAP ");
1998 acceptFrame = false;
1999 }
2000 }
2001 }
2002
2003 if (acceptFrame)
2004 {
2005 m_macRxTrace(originalPkt);
2006 // \todo: What should we do if we receive a frame while waiting for an ACK?
2007 // Especially if this frame has the ACK request bit set, should we reply with
2008 // an ACK, possibly missing the pending ACK?
2009
2010 // If the received frame is a frame with the ACK request bit set, we immediately
2011 // send back an ACK. If we are currently waiting for a pending ACK, we assume the
2012 // ACK was lost and trigger a retransmission after sending the ACK.
2013 if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) &&
2014 receivedMacHdr.IsAckReq() &&
2015 !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
2016 (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2017 receivedMacHdr.GetShortDstAddr().IsMulticast())))
2018 {
2019 // If this is a data or mac command frame, which is not a broadcast or
2020 // multicast, with ack req set, generate and send an ack frame. If there is a
2021 // CSMA medium access in progress we cancel the medium access for sending the
2022 // ACK frame. A new transmission attempt will be started after the ACK was send.
2024 {
2027 }
2028 else if (m_lrWpanMacState == MAC_CSMA)
2029 {
2030 // \todo: If we receive a packet while doing CSMA/CA, should we drop the
2031 // packet because of channel busy,
2032 // or should we restart CSMA/CA for the packet after sending the ACK?
2033 // Currently we simply restart CSMA/CA after sending the ACK.
2034 NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
2035 "current CSMA-CA");
2036 m_csmaCa->Cancel();
2037 }
2038 // Cancel any pending MAC state change, ACKs have higher priority.
2041
2042 // save received packet and LQI to process the appropriate indication/response
2043 // after sending ACK (PD-DATA.confirm)
2044 m_rxPkt = originalPkt->Copy();
2045 m_lastRxFrameLqi = lqi;
2046
2047 // LOG Commands with ACK required.
2048 CommandPayloadHeader receivedMacPayload;
2049 p->PeekHeader(receivedMacPayload);
2050 switch (receivedMacPayload.GetCommandFrameType())
2051 {
2053 NS_LOG_DEBUG("Data Request Command Received; processing ACK");
2054 break;
2056 NS_LOG_DEBUG("Association Request Command Received; processing ACK");
2057 break;
2059 m_assocResCmdWaitTimeout.Cancel(); // cancel event to a lost assoc resp cmd.
2060 NS_LOG_DEBUG("Association Response Command Received; processing ACK");
2061 break;
2062 default:
2063 break;
2064 }
2065
2067 this,
2068 receivedMacHdr.GetSeqNum());
2069 }
2070
2071 if (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2072 {
2073 NS_LOG_DEBUG("Packet from " << params.m_srcAddr);
2074 NS_LOG_DEBUG("Packet to " << params.m_dstAddr);
2075 }
2076 else if (receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2077 {
2078 NS_LOG_DEBUG("Packet from " << params.m_srcExtAddr);
2079 NS_LOG_DEBUG("Packet to " << params.m_dstExtAddr);
2080 }
2081
2082 if (receivedMacHdr.IsBeacon())
2083 {
2084 // The received beacon size in symbols
2085 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
2086 // 17 bytes)
2087 m_rxBeaconSymbols = m_phy->GetPhySHRDuration() +
2088 1 * m_phy->GetPhySymbolsPerOctet() +
2089 (originalPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
2090
2091 // The start of Rx beacon time and start of the Incoming superframe Active
2092 // Period
2094 Simulator::Now() - Seconds(double(m_rxBeaconSymbols) / symbolRate);
2095
2096 NS_LOG_DEBUG("Beacon Received; forwarding up (m_macBeaconRxTime: "
2097 << m_macBeaconRxTime.As(Time::S) << ")");
2098
2099 BeaconPayloadHeader receivedMacPayload;
2100 p->RemoveHeader(receivedMacPayload);
2101
2102 // Fill the PAN descriptor
2103 PanDescriptor panDescriptor;
2104
2105 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR)
2106 {
2107 panDescriptor.m_coorAddrMode = SHORT_ADDR;
2108 panDescriptor.m_coorShortAddr = receivedMacHdr.GetShortSrcAddr();
2109 }
2110 else
2111 {
2112 panDescriptor.m_coorAddrMode = EXT_ADDR;
2113 panDescriptor.m_coorExtAddr = receivedMacHdr.GetExtSrcAddr();
2114 }
2115
2116 panDescriptor.m_coorPanId = receivedMacHdr.GetSrcPanId();
2117 panDescriptor.m_gtsPermit = receivedMacPayload.GetGtsFields().GetGtsPermit();
2118 panDescriptor.m_linkQuality = lqi;
2119 panDescriptor.m_logChPage = m_phy->GetCurrentPage();
2120 panDescriptor.m_logCh = m_phy->GetCurrentChannelNum();
2121 panDescriptor.m_superframeSpec = receivedMacPayload.GetSuperframeSpecField();
2122 panDescriptor.m_timeStamp = m_macBeaconRxTime;
2123
2124 // Process beacon when device belongs to a PAN (associated device)
2125 if (!m_scanEvent.IsRunning() && m_macPanId == receivedMacHdr.GetDstPanId())
2126 {
2127 // We need to make sure to cancel any possible ongoing unslotted CSMA/CA
2128 // operations when receiving a beacon (e.g. Those taking place at the
2129 // beginning of an Association).
2130 m_csmaCa->Cancel();
2131
2132 SuperframeField incomingSuperframe(
2133 receivedMacPayload.GetSuperframeSpecField());
2134
2135 m_incomingBeaconOrder = incomingSuperframe.GetBeaconOrder();
2136 m_incomingSuperframeOrder = incomingSuperframe.GetFrameOrder();
2137 m_incomingFnlCapSlot = incomingSuperframe.GetFinalCapSlot();
2138
2139 if (m_incomingBeaconOrder < 15)
2140 {
2141 // Start Beacon-enabled mode
2142 m_csmaCa->SetSlottedCsmaCa();
2144 (static_cast<uint32_t>(1 << m_incomingBeaconOrder)) *
2148 (static_cast<uint32_t>(1 << m_incomingSuperframeOrder));
2149
2150 if (incomingSuperframe.IsBattLifeExt())
2151 {
2152 m_csmaCa->SetBatteryLifeExtension(true);
2153 }
2154 else
2155 {
2156 m_csmaCa->SetBatteryLifeExtension(false);
2157 }
2158
2159 // TODO: get Incoming frame GTS Fields here
2160
2161 // Begin CAP on the current device using info from
2162 // the Incoming superframe
2163 NS_LOG_DEBUG("Incoming superframe Active Portion "
2164 << "(Beacon + CAP + CFP): " << m_incomingSuperframeDuration
2165 << " symbols");
2166
2168 this,
2170 }
2171 else
2172 {
2173 // Start non-beacon enabled mode
2174 m_csmaCa->SetUnSlottedCsmaCa();
2175 }
2176
2179 }
2180 else if (!m_scanEvent.IsRunning() && m_macPanId == 0xFFFF)
2181 {
2182 NS_LOG_DEBUG(this << " Device not associated, cannot process beacon");
2183 }
2184
2185 if (m_macAutoRequest)
2186 {
2187 if (p->GetSize() > 0)
2188 {
2190 {
2191 // The beacon contains payload, send the beacon notification.
2193 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2194 beaconParams.m_panDescriptor = panDescriptor;
2195 beaconParams.m_sduLength = p->GetSize();
2196 beaconParams.m_sdu = p;
2198 }
2199 }
2200
2201 if (m_scanEvent.IsRunning())
2202 {
2203 // Channel scanning is taking place, save only unique PAN descriptors
2204 bool descriptorExists = false;
2205
2206 for (const auto& descriptor : m_panDescriptorList)
2207 {
2208 if (descriptor.m_coorAddrMode == SHORT_ADDR)
2209 {
2210 // Found a coordinator in PAN descriptor list with the same
2211 // registered short address
2212 descriptorExists =
2213 (descriptor.m_coorShortAddr ==
2214 panDescriptor.m_coorShortAddr &&
2215 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
2216 }
2217 else
2218 {
2219 // Found a coordinator in PAN descriptor list with the same
2220 // registered extended address
2221 descriptorExists =
2222 (descriptor.m_coorExtAddr == panDescriptor.m_coorExtAddr &&
2223 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
2224 }
2225
2226 if (descriptorExists)
2227 {
2228 break;
2229 }
2230 }
2231
2232 if (!descriptorExists)
2233 {
2234 m_panDescriptorList.emplace_back(panDescriptor);
2235 }
2236 return;
2237 }
2238 else if (m_trackingEvent.IsRunning())
2239 {
2240 // check if MLME-SYNC.request was previously issued and running
2241 // Sync. is necessary to handle pending messages (indirect
2242 // transmissions)
2244 m_numLostBeacons = 0;
2245
2247 {
2248 // if tracking option is on keep tracking the next beacon
2249 uint64_t searchSymbols;
2250 Time searchBeaconTime;
2251
2252 searchSymbols =
2253 (static_cast<uint64_t>(1 << m_incomingBeaconOrder)) +
2255 searchBeaconTime =
2256 Seconds(static_cast<double>(searchSymbols / symbolRate));
2258 Simulator::Schedule(searchBeaconTime,
2260 this);
2261 }
2262
2263 PendingAddrFields pndAddrFields;
2264 pndAddrFields = receivedMacPayload.GetPndAddrFields();
2265
2266 // TODO: Ignore pending data, and do not send data command request if
2267 // the address is in the GTS list.
2268 // If the address is not in the GTS list, then check if the
2269 // address is in the short address pending list or in the extended
2270 // address pending list and send a data command request.
2271 }
2272 }
2273 else
2274 {
2275 // m_macAutoRequest is FALSE
2276 // Data command request are not send, only the beacon notification.
2277 // see IEEE 802.15.4-2011 Section 6.2.4.1
2279 {
2281 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2282 beaconParams.m_panDescriptor = panDescriptor;
2283 beaconParams.m_sduLength = p->GetSize();
2284 beaconParams.m_sdu = p;
2286 }
2287 }
2288 }
2289 else if (receivedMacHdr.IsCommand())
2290 {
2291 // Handle the reception of frame commands that do not require ACK
2292 // (i.e. Beacon Request, Orphan notification, Coordinator Realigment)
2293 CommandPayloadHeader receivedMacPayload;
2294 p->PeekHeader(receivedMacPayload);
2295
2296 switch (receivedMacPayload.GetCommandFrameType())
2297 {
2299 if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
2300 {
2301 SendOneBeacon();
2302 }
2303 else
2304 {
2305 m_macRxDropTrace(originalPkt);
2306 }
2307 break;
2310 {
2311 if (m_coor)
2312 {
2313 MlmeOrphanIndicationParams orphanParams;
2314 orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
2315 m_mlmeOrphanIndicationCallback(orphanParams);
2316 }
2317 }
2318 break;
2321 {
2322 // Coordinator located, no need to keep scanning other channels
2324
2325 m_macPanIdScan = 0;
2328
2329 // Update the device information with the received information
2330 // from the Coordinator Realigment command.
2331 m_macPanId = receivedMacPayload.GetPanId();
2332 m_shortAddress = receivedMacPayload.GetShortAddr();
2333 m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
2334 m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
2335
2337 {
2338 MlmeScanConfirmParams confirmParams;
2339 confirmParams.m_scanType = m_scanParams.m_scanType;
2340 confirmParams.m_chPage = m_scanParams.m_chPage;
2341 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
2342 m_mlmeScanConfirmCallback(confirmParams);
2343 }
2344 m_scanParams = {};
2345 }
2346 // TODO: handle Coordinator realignment when not
2347 // used during an orphan scan.
2348 break;
2349 default:
2350 m_macRxDropTrace(originalPkt);
2351 break;
2352 }
2353 }
2354 else if (receivedMacHdr.IsData() && !m_mcpsDataIndicationCallback.IsNull())
2355 {
2356 // If it is a data frame, push it up the stack.
2357 NS_LOG_DEBUG("Data Packet is for me; forwarding up");
2359 }
2360 else if (receivedMacHdr.IsAcknowledgment() && m_txPkt &&
2362 {
2363 LrWpanMacHeader peekedMacHdr;
2364 m_txPkt->PeekHeader(peekedMacHdr);
2365 // If it is an ACK with the expected sequence number, finish the transmission
2366 if (receivedMacHdr.GetSeqNum() == peekedMacHdr.GetSeqNum())
2367 {
2370
2371 // TODO: check if the IFS is the correct size after ACK.
2372 Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
2373
2374 // We received an ACK to a command
2375 if (peekedMacHdr.IsCommand())
2376 {
2377 // check the original sent command frame which belongs to this received
2378 // ACK
2379 Ptr<Packet> pkt = m_txPkt->Copy();
2380 LrWpanMacHeader macHdr;
2381 CommandPayloadHeader cmdPayload;
2382 pkt->RemoveHeader(macHdr);
2383 pkt->RemoveHeader(cmdPayload);
2384
2385 switch (cmdPayload.GetCommandFrameType())
2386 {
2388 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2389 Time waitTime = Seconds(static_cast<double>(m_macResponseWaitTime) /
2390 symbolRate);
2391 if (!m_beaconTrackingOn)
2392 {
2394 Simulator::Schedule(waitTime,
2396 this);
2397 }
2398 else
2399 {
2400 // TODO: The data must be extracted by the coordinator within
2401 // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
2402 // with status NO_DATA, and this should trigger the cancellation
2403 // of the beacon tracking (MLME-SYNC.request trackBeacon
2404 // =FALSE)
2405 }
2406 break;
2407 }
2408
2410 // MLME-comm-status.Indication generated as a result of an
2411 // association response command, therefore src and dst address use
2412 // extended mode (see 5.3.2.1)
2414 {
2415 MlmeCommStatusIndicationParams commStatusParams;
2416 commStatusParams.m_panId = m_macPanId;
2417 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2418 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2419 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2420 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2421 commStatusParams.m_status = LrWpanMacStatus::SUCCESS;
2422 m_mlmeCommStatusIndicationCallback(commStatusParams);
2423 }
2424 // Remove element from Pending Transaction List
2426 break;
2427 }
2428
2430 // Schedule an event in case the Association Response Command never
2431 // reached this device during an association process.
2432 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2433 Time waitTime = Seconds(
2434 static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
2436 Simulator::Schedule(waitTime,
2438 this);
2439
2441 {
2442 MlmePollConfirmParams pollConfirmParams;
2443 pollConfirmParams.m_status = LrWpanMacStatus::SUCCESS;
2444 m_mlmePollConfirmCallback(pollConfirmParams);
2445 }
2446 break;
2447 }
2448
2450 // ACK of coordinator realigment commands is not specified in the
2451 // standard, in here, we assume they are required as in other
2452 // commands.
2454 {
2455 MlmeCommStatusIndicationParams commStatusParams;
2456 commStatusParams.m_panId = m_macPanId;
2457 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2458 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2459 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2460 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2461 commStatusParams.m_status = LrWpanMacStatus::SUCCESS;
2462 m_mlmeCommStatusIndicationCallback(commStatusParams);
2463 }
2464 }
2465
2466 default: {
2467 // TODO: add response to other request commands (e.g. Orphan)
2468 break;
2469 }
2470 }
2471 }
2472 else
2473 {
2475 {
2476 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2477 McpsDataConfirmParams confirmParams;
2478 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2479 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
2480 m_mcpsDataConfirmCallback(confirmParams);
2481 }
2482 }
2483
2484 // Ack was successfully received, wait for the Interframe Space (IFS) and
2485 // then proceed
2490 m_ifsEvent = Simulator::Schedule(ifsWaitTime,
2492 this,
2493 ifsWaitTime);
2494 }
2495 else
2496 {
2497 // If it is an ACK with an unexpected sequence number, mark the current
2498 // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
2500 if (!PrepareRetransmission())
2501 {
2504 this,
2505 MAC_IDLE);
2506 }
2507 else
2508 {
2511 this,
2512 MAC_CSMA);
2513 }
2514 }
2515 }
2516 }
2517 else
2518 {
2519 m_macRxDropTrace(originalPkt);
2520 }
2521 }
2522 }
2523}
2524
2525void
2527{
2528 NS_LOG_FUNCTION(this << static_cast<uint32_t>(seqno));
2529
2531
2532 // Generate a corresponding ACK Frame.
2534 LrWpanMacTrailer macTrailer;
2535 Ptr<Packet> ackPacket = Create<Packet>(0);
2536 ackPacket->AddHeader(macHdr);
2537 // Calculate FCS if the global attribute ChecksumEnabled is set.
2539 {
2540 macTrailer.EnableFcs(true);
2541 macTrailer.SetFcs(ackPacket);
2542 }
2543 ackPacket->AddTrailer(macTrailer);
2544
2545 // Enqueue the ACK packet for further processing
2546 // when the transmitter is activated.
2547 m_txPkt = ackPacket;
2548
2549 // Switch transceiver to TX mode. Proceed sending the Ack on confirm.
2551 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
2552}
2553
2554void
2556{
2557 if (m_txQueue.size() < m_maxTxQueueSize)
2558 {
2559 m_txQueue.emplace_back(txQElement);
2560 m_macTxEnqueueTrace(txQElement->txQPkt);
2561 }
2562 else
2563 {
2565 {
2566 McpsDataConfirmParams confirmParams;
2567 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2569 m_mcpsDataConfirmCallback(confirmParams);
2570 }
2571 NS_LOG_DEBUG("TX Queue with size " << m_txQueue.size() << " is full, dropping packet");
2572 m_macTxDropTrace(txQElement->txQPkt);
2573 }
2574}
2575
2576void
2578{
2579 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2580 Ptr<const Packet> p = txQElement->txQPkt;
2581 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2582
2583 Ptr<Packet> pkt = p->Copy();
2584 LrWpanMacHeader hdr;
2585 pkt->RemoveHeader(hdr);
2586 if (!hdr.GetShortDstAddr().IsBroadcast() && !hdr.GetShortDstAddr().IsMulticast())
2587 {
2589 }
2590
2591 txQElement->txQPkt = nullptr;
2592 txQElement = nullptr;
2593 m_txQueue.pop_front();
2594 m_txPkt = nullptr;
2595 m_retransmission = 0;
2596 m_numCsmacaRetry = 0;
2598}
2599
2600void
2602{
2603 NS_LOG_FUNCTION(this);
2604
2605 // TODO: If we are a PAN coordinator and this was an indirect transmission,
2606 // we will not initiate a retransmission. Instead we wait for the data
2607 // being extracted after a new data request command.
2608 if (!PrepareRetransmission())
2609 {
2611 }
2612 else
2613 {
2615 }
2616}
2617
2618void
2620{
2621 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false);
2622 Time lifsTime = Seconds((double)m_macLIFSPeriod / symbolRate);
2623 Time sifsTime = Seconds((double)m_macSIFSPeriod / symbolRate);
2624
2625 if (ifsTime == lifsTime)
2626 {
2627 NS_LOG_DEBUG("LIFS of " << m_macLIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2628 << ") completed ");
2629 }
2630 else if (ifsTime == sifsTime)
2631 {
2632 NS_LOG_DEBUG("SIFS of " << m_macSIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2633 << ") completed ");
2634 }
2635 else
2636 {
2637 NS_LOG_DEBUG("Unknown IFS size (" << ifsTime.As(Time::S) << ") completed ");
2638 }
2639
2640 m_macIfsEndTrace(ifsTime);
2641 CheckQueue();
2642}
2643
2644bool
2646{
2647 NS_LOG_FUNCTION(this);
2648
2649 // Max retransmissions reached without receiving ACK,
2650 // send the proper indication/confirmation
2651 // according to the frame type and call drop trace.
2653 {
2654 LrWpanMacHeader peekedMacHdr;
2655 m_txPkt->PeekHeader(peekedMacHdr);
2656
2657 if (peekedMacHdr.IsCommand())
2658 {
2660
2661 Ptr<Packet> pkt = m_txPkt->Copy();
2662 LrWpanMacHeader macHdr;
2663 CommandPayloadHeader cmdPayload;
2664 pkt->RemoveHeader(macHdr);
2665 pkt->RemoveHeader(cmdPayload);
2666
2667 switch (cmdPayload.GetCommandFrameType())
2668 {
2670 m_macPanId = 0xffff;
2672 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2675 m_csmaCa->SetUnSlottedCsmaCa();
2678
2680 {
2681 MlmeAssociateConfirmParams confirmParams;
2682 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
2683 confirmParams.m_status = LrWpanMacStatus::NO_ACK;
2684 m_mlmeAssociateConfirmCallback(confirmParams);
2685 }
2686 break;
2687 }
2689 // IEEE 802.15.4-2006 (Section 7.1.3.3.3 and 7.1.8.2.3)
2691 {
2692 MlmeCommStatusIndicationParams commStatusParams;
2693 commStatusParams.m_panId = m_macPanId;
2694 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2695 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2696 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2697 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2698 commStatusParams.m_status = LrWpanMacStatus::NO_ACK;
2699 m_mlmeCommStatusIndicationCallback(commStatusParams);
2700 }
2702 break;
2703 }
2705 // IEEE 802.15.4-2006 (Section 7.1.16.1.3)
2706 m_macPanId = 0xffff;
2708 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2711 m_csmaCa->SetUnSlottedCsmaCa();
2714
2716 {
2717 MlmePollConfirmParams pollConfirmParams;
2718 pollConfirmParams.m_status = LrWpanMacStatus::NO_ACK;
2719 m_mlmePollConfirmCallback(pollConfirmParams);
2720 }
2721 break;
2722 }
2723 default: {
2724 // TODO: Specify other indications according to other commands
2725 break;
2726 }
2727 }
2728 }
2729 else
2730 {
2731 // Maximum number of retransmissions has been reached.
2732 // remove the copy of the DATA packet that was just sent
2733 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2734 m_macTxDropTrace(txQElement->txQPkt);
2736 {
2737 McpsDataConfirmParams confirmParams;
2738 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2739 confirmParams.m_status = LrWpanMacStatus::NO_ACK;
2740 m_mcpsDataConfirmCallback(confirmParams);
2741 }
2742 }
2743
2745 return false;
2746 }
2747 else
2748 {
2750 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2751 // Start next CCA process for this packet.
2752 return true;
2753 }
2754}
2755
2756void
2758{
2759 Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
2760 LrWpanMacHeader peekedMacHdr;
2761 p->PeekHeader(peekedMacHdr);
2762
2763 PurgeInd();
2764
2765 NS_ASSERT(peekedMacHdr.GetDstAddrMode() == SHORT_ADDR ||
2766 peekedMacHdr.GetDstAddrMode() == EXT_ADDR);
2767
2768 if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2769 {
2770 indTxQElement->dstShortAddress = peekedMacHdr.GetShortDstAddr();
2771 }
2772 else
2773 {
2774 indTxQElement->dstExtAddress = peekedMacHdr.GetExtDstAddr();
2775 }
2776
2777 indTxQElement->seqNum = peekedMacHdr.GetSeqNum();
2778
2779 // See IEEE 802.15.4-2006, Table 86
2780 uint32_t unit = 0; // The persistence time in symbols
2781 if (m_macBeaconOrder == 15)
2782 {
2783 // Non-beacon enabled mode
2785 }
2786 else
2787 {
2788 // Beacon-enabled mode
2789 unit = ((static_cast<uint32_t>(1) << m_macBeaconOrder) * lrwpan::aBaseSuperframeDuration) *
2791 }
2792
2793 if (m_indTxQueue.size() < m_maxIndTxQueueSize)
2794 {
2795 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2796 Time expireTime = Seconds(unit / symbolRate);
2797 expireTime += Simulator::Now();
2798 indTxQElement->expireTime = expireTime;
2799 indTxQElement->txQPkt = p;
2800 m_indTxQueue.emplace_back(indTxQElement);
2802 }
2803 else
2804 {
2806 {
2807 LrWpanMacHeader peekedMacHdr;
2808 indTxQElement->txQPkt->PeekHeader(peekedMacHdr);
2809 MlmeCommStatusIndicationParams commStatusParams;
2810 commStatusParams.m_panId = m_macPanId;
2811 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2812 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2813 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2814 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2816 m_mlmeCommStatusIndicationCallback(commStatusParams);
2817 }
2819 }
2820}
2821
2822bool
2824{
2825 PurgeInd();
2826
2827 for (auto iter = m_indTxQueue.begin(); iter != m_indTxQueue.end(); iter++)
2828 {
2829 if ((*iter)->dstExtAddress == dst)
2830 {
2831 *entry = **iter;
2832 m_macIndTxDequeueTrace((*iter)->txQPkt->Copy());
2833 m_indTxQueue.erase(iter);
2834 return true;
2835 }
2836 }
2837 return false;
2838}
2839
2840void
2842{
2843 for (uint32_t i = 0; i < m_indTxQueue.size();)
2844 {
2845 if (Simulator::Now() > m_indTxQueue[i]->expireTime)
2846 {
2847 // Transaction expired, remove and send proper confirmation/indication to a higher layer
2848 LrWpanMacHeader peekedMacHdr;
2849 m_indTxQueue[i]->txQPkt->PeekHeader(peekedMacHdr);
2850
2851 if (peekedMacHdr.IsCommand())
2852 {
2853 // IEEE 802.15.4-2006 (Section 7.1.3.3.3)
2855 {
2856 MlmeCommStatusIndicationParams commStatusParams;
2857 commStatusParams.m_panId = m_macPanId;
2858 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2859 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2860 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2861 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2863 m_mlmeCommStatusIndicationCallback(commStatusParams);
2864 }
2865 }
2866 else if (peekedMacHdr.IsData())
2867 {
2868 // IEEE 802.15.4-2006 (Section 7.1.1.1.3)
2870 {
2871 McpsDataConfirmParams confParams;
2873 m_mcpsDataConfirmCallback(confParams);
2874 }
2875 }
2876 m_macIndTxDropTrace(m_indTxQueue[i]->txQPkt->Copy());
2877 m_indTxQueue.erase(m_indTxQueue.begin() + i);
2878 }
2879 else
2880 {
2881 i++;
2882 }
2883 }
2884}
2885
2886void
2887LrWpanMac::PrintPendingTxQueue(std::ostream& os) const
2888{
2889 LrWpanMacHeader peekedMacHdr;
2890
2891 os << "Pending Transaction List [" << GetShortAddress() << " | " << GetExtendedAddress()
2892 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
2893 << " Destination |"
2894 << " Sequence Number |"
2895 << " Frame type |"
2896 << " Expire time\n";
2897
2898 for (auto transaction : m_indTxQueue)
2899 {
2900 transaction->txQPkt->PeekHeader(peekedMacHdr);
2901 os << transaction->dstExtAddress << " "
2902 << static_cast<uint32_t>(transaction->seqNum) << " ";
2903
2904 if (peekedMacHdr.IsCommand())
2905 {
2906 os << " Command Frame ";
2907 }
2908 else if (peekedMacHdr.IsData())
2909 {
2910 os << " Data Frame ";
2911 }
2912 else
2913 {
2914 os << " Unknown Frame ";
2915 }
2916
2917 os << transaction->expireTime.As(Time::S) << "\n";
2918 }
2919}
2920
2921void
2922LrWpanMac::PrintTxQueue(std::ostream& os) const
2923{
2924 LrWpanMacHeader peekedMacHdr;
2925
2926 os << "\nTx Queue [" << GetShortAddress() << " | " << GetExtendedAddress()
2927 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
2928 << " Destination |"
2929 << " Sequence Number |"
2930 << " Dst PAN id |"
2931 << " Frame type |\n";
2932
2933 for (auto transaction : m_txQueue)
2934 {
2935 transaction->txQPkt->PeekHeader(peekedMacHdr);
2936
2937 os << "[" << peekedMacHdr.GetShortDstAddr() << "]"
2938 << ", [" << peekedMacHdr.GetExtDstAddr() << "] "
2939 << static_cast<uint32_t>(peekedMacHdr.GetSeqNum()) << " "
2940 << peekedMacHdr.GetDstPanId() << " ";
2941
2942 if (peekedMacHdr.IsCommand())
2943 {
2944 os << " Command Frame ";
2945 }
2946 else if (peekedMacHdr.IsData())
2947 {
2948 os << " Data Frame ";
2949 }
2950 else
2951 {
2952 os << " Unknown Frame ";
2953 }
2954
2955 os << "\n";
2956 }
2957 os << "\n";
2958}
2959
2960void
2962{
2963 LrWpanMacHeader peekedMacHdr;
2964 p->PeekHeader(peekedMacHdr);
2965
2966 for (auto it = m_indTxQueue.begin(); it != m_indTxQueue.end(); it++)
2967 {
2968 if (peekedMacHdr.GetDstAddrMode() == EXT_ADDR)
2969 {
2970 if (((*it)->dstExtAddress == peekedMacHdr.GetExtDstAddr()) &&
2971 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
2972 {
2974 m_indTxQueue.erase(it);
2975 break;
2976 }
2977 }
2978 else if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2979 {
2980 if (((*it)->dstShortAddress == peekedMacHdr.GetShortDstAddr()) &&
2981 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
2982 {
2984 m_indTxQueue.erase(it);
2985 break;
2986 }
2987 }
2988 }
2989
2990 p = nullptr;
2991}
2992
2993void
2995{
2997 NS_LOG_FUNCTION(this << status << m_txQueue.size());
2998
2999 LrWpanMacHeader macHdr;
3000 Time ifsWaitTime;
3001 double symbolRate;
3002
3003 symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
3004
3005 m_txPkt->PeekHeader(macHdr);
3006
3007 if (status == IEEE_802_15_4_PHY_SUCCESS)
3008 {
3009 if (!macHdr.IsAcknowledgment())
3010 {
3011 if (macHdr.IsBeacon())
3012 {
3013 // Start CAP only if we are in beacon mode (i.e. if slotted csma-ca is running)
3014 if (m_csmaCa->IsSlottedCsmaCa())
3015 {
3016 // The Tx Beacon in symbols
3017 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
3018 // 17 bytes)
3019 uint64_t beaconSymbols = m_phy->GetPhySHRDuration() +
3020 1 * m_phy->GetPhySymbolsPerOctet() +
3021 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
3022
3023 // The beacon Tx time and start of the Outgoing superframe Active Period
3025 Simulator::Now() - Seconds(static_cast<double>(beaconSymbols) / symbolRate);
3026
3028 this,
3030 NS_LOG_DEBUG("Beacon Sent (m_macBeaconTxTime: " << m_macBeaconTxTime.As(Time::S)
3031 << ")");
3032
3034 {
3035 MlmeStartConfirmParams mlmeConfirmParams;
3036 mlmeConfirmParams.m_status = LrWpanMacStatus::SUCCESS;
3037 m_mlmeStartConfirmCallback(mlmeConfirmParams);
3038 }
3039 }
3040
3041 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3042 m_txPkt = nullptr;
3043 }
3044 else if (macHdr.IsAckReq()) // We have sent a regular data packet, check if we have to
3045 // wait for an ACK.
3046 {
3047 // we sent a regular data frame or command frame (e.g. AssocReq command) that
3048 // require ACK wait for the ack or the next retransmission timeout start
3049 // retransmission timer
3050 Time waitTime = Seconds(static_cast<double>(GetMacAckWaitDuration()) / symbolRate);
3056 return;
3057 }
3058 else if (macHdr.IsCommand())
3059 {
3060 // We handle commands that do not require ACK
3061 // (e.g. Coordinator realigment command in an orphan response)
3062 // Other command with ACK required are handle by the previous if statement.
3063
3064 // Check the transmitted packet command type and issue the appropriate indication.
3065 Ptr<Packet> txOriginalPkt = m_txPkt->Copy();
3066 LrWpanMacHeader txMacHdr;
3067 txOriginalPkt->RemoveHeader(txMacHdr);
3068 CommandPayloadHeader txMacPayload;
3069 txOriginalPkt->RemoveHeader(txMacPayload);
3070
3072 {
3074 {
3075 MlmeCommStatusIndicationParams commStatusParams;
3076 commStatusParams.m_panId = m_macPanId;
3077
3078 commStatusParams.m_srcAddrMode = macHdr.GetSrcAddrMode();
3079 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3080 commStatusParams.m_srcShortAddr = macHdr.GetShortSrcAddr();
3081
3082 commStatusParams.m_dstAddrMode = macHdr.GetDstAddrMode();
3083 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3084 commStatusParams.m_dstShortAddr = macHdr.GetShortDstAddr();
3085
3086 commStatusParams.m_status = LrWpanMacStatus::SUCCESS;
3087 m_mlmeCommStatusIndicationCallback(commStatusParams);
3088 }
3089 }
3090
3091 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3093 }
3094 else
3095 {
3097 // remove the copy of the packet that was just sent
3099 {
3100 McpsDataConfirmParams confirmParams;
3101 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3102 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3103 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3104 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
3105 m_mcpsDataConfirmCallback(confirmParams);
3106 }
3107 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3109 }
3110 }
3111 else
3112 {
3113 // The packet sent was a successful ACK
3114
3115 // Check the received frame before the transmission of the ACK,
3116 // and send the appropriate Indication or Confirmation
3117 Ptr<Packet> recvOriginalPkt = m_rxPkt->Copy();
3118 LrWpanMacHeader receivedMacHdr;
3119 recvOriginalPkt->RemoveHeader(receivedMacHdr);
3120
3121 if (receivedMacHdr.IsCommand())
3122 {
3123 CommandPayloadHeader receivedMacPayload;
3124 recvOriginalPkt->RemoveHeader(receivedMacPayload);
3125
3126 if (receivedMacPayload.GetCommandFrameType() ==
3128 {
3130 {
3131 // NOTE: The LQI parameter is not part of the standard but found
3132 // in some implementations as is required for higher layers (See Zboss
3133 // implementation).
3134 MlmeAssociateIndicationParams associateParams;
3135 associateParams.capabilityInfo = receivedMacPayload.GetCapabilityField();
3136 associateParams.m_extDevAddr = receivedMacHdr.GetExtSrcAddr();
3137 associateParams.lqi = m_lastRxFrameLqi;
3138 m_mlmeAssociateIndicationCallback(associateParams);
3139 }
3140
3141 // Clear the packet buffer for the packet request received.
3142 m_rxPkt = nullptr;
3143 }
3144 else if (receivedMacPayload.GetCommandFrameType() ==
3146 {
3147 MlmeAssociateConfirmParams confirmParams;
3148
3149 switch (static_cast<LrWpanMacStatus>(receivedMacPayload.GetAssociationStatus()))
3150 {
3152 // The assigned short address by the coordinator
3153 SetShortAddress(receivedMacPayload.GetShortAddr());
3154 m_macPanId = receivedMacHdr.GetSrcPanId();
3155
3156 confirmParams.m_status = LrWpanMacStatus::SUCCESS;
3157 confirmParams.m_assocShortAddr = GetShortAddress();
3158 break;
3161 m_macPanId = 0xffff;
3163 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3166 m_csmaCa->SetUnSlottedCsmaCa();
3169 break;
3171 default:
3173 m_macPanId = 0xffff;
3175 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3178 m_csmaCa->SetUnSlottedCsmaCa();
3181 break;
3182 }
3183
3185 {
3186 m_mlmeAssociateConfirmCallback(confirmParams);
3187 }
3188 }
3189 else if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::DATA_REQ)
3190 {
3191 // We enqueue the the Assoc Response command frame in the Tx queue
3192 // and the packet is transmitted as soon as the PHY is free and the IFS have
3193 // taken place.
3195 }
3196 }
3197
3198 // Clear the packet buffer for the ACK packet sent.
3199 m_txPkt = nullptr;
3200 }
3201 }
3202 else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
3203 {
3204 if (!macHdr.IsAcknowledgment())
3205 {
3206 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3207 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3208 m_macTxDropTrace(txQElement->txQPkt);
3210 {
3211 McpsDataConfirmParams confirmParams;
3212 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3214 m_mcpsDataConfirmCallback(confirmParams);
3215 }
3217 }
3218 else
3219 {
3220 NS_LOG_ERROR("Unable to send ACK");
3221 }
3222 }
3223 else
3224 {
3225 // Something went really wrong. The PHY is not in the correct state for
3226 // data transmission.
3227 NS_FATAL_ERROR("Transmission attempt failed with PHY status " << status);
3228 }
3229
3230 if (!ifsWaitTime.IsZero())
3231 {
3232 m_ifsEvent =
3233 Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
3234 }
3235
3238}
3239
3240void
3242{
3243 NS_LOG_FUNCTION(this << status);
3244 // Direct this call through the csmaCa object
3245 m_csmaCa->PlmeCcaConfirm(status);
3246}
3247
3248void
3250{
3251 NS_LOG_FUNCTION(this << status << energyLevel);
3252
3253 if (energyLevel > m_maxEnergyLevel)
3254 {
3255 m_maxEnergyLevel = energyLevel;
3256 }
3257
3259 Seconds(8.0 / m_phy->GetDataOrSymbolRate(false)))
3260 {
3261 m_phy->PlmeEdRequest();
3262 }
3263}
3264
3265void
3269{
3270 NS_LOG_FUNCTION(this << status << id << attribute);
3271}
3272
3273void
3275{
3276 NS_LOG_FUNCTION(this << status);
3277
3279 (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3280 {
3282
3283 // Start sending if we are in state SENDING and the PHY transmitter was enabled.
3287 m_phy->PdDataRequest(m_txPkt->GetSize(), m_txPkt);
3288 }
3289 else if (m_lrWpanMacState == MAC_CSMA &&
3290 (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3291 {
3292 // Start the CSMA algorithm as soon as the receiver is enabled.
3293 m_csmaCa->Start();
3294 }
3295 else if (m_lrWpanMacState == MAC_IDLE)
3296 {
3298 status == IEEE_802_15_4_PHY_TRX_OFF);
3299
3301 {
3302 // Kick start Energy Detection Scan
3303 m_phy->PlmeEdRequest();
3304 }
3305 else if (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS)
3306 {
3307 // Check if there is not messages to transmit when going idle
3308 CheckQueue();
3309 }
3310 }
3312 {
3314 }
3315 else
3316 {
3317 // TODO: What to do when we receive an error?
3318 // If we want to transmit a packet, but switching the transceiver on results
3319 // in an error, we have to recover somehow (and start sending again).
3320 NS_FATAL_ERROR("Error changing transceiver state");
3321 }
3322}
3323
3324void
3326{
3327 NS_LOG_FUNCTION(this << status << id);
3329 {
3331 {
3332 // get the first channel to scan from scan channel list
3333 bool channelFound = false;
3334 for (int i = m_channelScanIndex; i <= 26; i++)
3335 {
3337 {
3338 channelFound = true;
3339 break;
3340 }
3342 }
3343
3344 if (channelFound)
3345 {
3346 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
3347 pibAttr->phyCurrentChannel = m_channelScanIndex;
3349 pibAttr);
3350 }
3351 }
3352 else
3353 {
3355 {
3356 MlmeScanConfirmParams confirmParams;
3357 confirmParams.m_scanType = m_scanParams.m_scanType;
3358 confirmParams.m_chPage = m_scanParams.m_chPage;
3360 m_mlmeScanConfirmCallback(confirmParams);
3361 }
3362 NS_LOG_ERROR(this << "Channel Scan: Invalid channel page");
3363 }
3364 }
3367 {
3369 {
3370 auto symbolRate = static_cast<uint64_t>(m_phy->GetDataOrSymbolRate(false));
3371 Time nextScanTime;
3372
3374 {
3375 nextScanTime = Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
3376 }
3377 else
3378 {
3379 uint64_t scanDurationSym =
3381
3382 nextScanTime = Seconds(static_cast<double>(scanDurationSym) / symbolRate);
3383 }
3384
3385 switch (m_scanParams.m_scanType)
3386 {
3387 case MLMESCAN_ED:
3388 m_maxEnergyLevel = 0;
3391 // set phy to RX_ON and kick start the first PLME-ED.request
3392 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3393 break;
3394 case MLMESCAN_ACTIVE:
3397 break;
3398 case MLMESCAN_PASSIVE:
3400 // turn back the phy to RX_ON after setting Page/channel
3401 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3402 break;
3403 case MLMESCAN_ORPHAN:
3405 Simulator::Schedule(nextScanTime, &LrWpanMac::EndChannelScan, this);
3407 break;
3408
3409 default:
3410 MlmeScanConfirmParams confirmParams;
3411 confirmParams.m_scanType = m_scanParams.m_scanType;
3412 confirmParams.m_chPage = m_scanParams.m_chPage;
3415 {
3416 m_mlmeScanConfirmCallback(confirmParams);
3417 }
3418 NS_LOG_ERROR("Scan Type currently not supported");
3419 return;
3420 }
3421 }
3422 else
3423 {
3425 {
3426 MlmeScanConfirmParams confirmParams;
3427 confirmParams.m_scanType = m_scanParams.m_scanType;
3428 confirmParams.m_chPage = m_scanParams.m_chPage;
3430 m_mlmeScanConfirmCallback(confirmParams);
3431 }
3432 NS_LOG_ERROR("Channel " << m_channelScanIndex
3433 << " could not be set in the current page");
3434 }
3435 }
3438 {
3440 {
3441 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
3442 pibAttr->phyCurrentChannel = m_startParams.m_logCh;
3444 pibAttr);
3445 }
3446 else
3447 {
3449 {
3450 MlmeStartConfirmParams confirmParams;
3452 m_mlmeStartConfirmCallback(confirmParams);
3453 }
3454 NS_LOG_ERROR("Invalid page parameter in MLME-start");
3455 }
3456 }
3459 {
3461 {
3463 }
3464 else
3465 {
3467 {
3468 MlmeStartConfirmParams confirmParams;
3470 m_mlmeStartConfirmCallback(confirmParams);
3471 }
3472 NS_LOG_ERROR("Invalid channel parameter in MLME-start");
3473 }
3474 }
3477 {
3479 {
3480 Ptr<LrWpanPhyPibAttributes> pibAttr = Create<LrWpanPhyPibAttributes>();
3481 pibAttr->phyCurrentChannel = m_associateParams.m_chNum;
3483 pibAttr);
3484 }
3485 else
3486 {
3487 m_macPanId = 0xffff;
3489 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3492 m_csmaCa->SetUnSlottedCsmaCa();
3495
3497 {
3498 MlmeAssociateConfirmParams confirmParams;
3499 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3501 m_mlmeAssociateConfirmCallback(confirmParams);
3502 }
3503 NS_LOG_ERROR("Invalid page parameter in MLME-associate");
3504 }
3505 }
3508 {
3510 {
3512 }
3513 else
3514 {
3515 m_macPanId = 0xffff;
3517 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3520 m_csmaCa->SetUnSlottedCsmaCa();
3523
3525 {
3526 MlmeAssociateConfirmParams confirmParams;
3527 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3529 m_mlmeAssociateConfirmCallback(confirmParams);
3530 }
3531 NS_LOG_ERROR("Invalid channel parameter in MLME-associate");
3532 }
3533 }
3534}
3535
3536void
3538{
3539 NS_LOG_FUNCTION(this << "mac state = " << macState);
3540
3541 if (macState == MAC_IDLE)
3542 {
3545 {
3546 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3547 }
3548 else
3549 {
3550 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3551 }
3552 }
3553 else if (macState == MAC_ACK_PENDING)
3554 {
3556 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3557 }
3558 else if (macState == MAC_CSMA)
3559 {
3562 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3563 }
3564 else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_IDLE)
3565 {
3566 // Channel is idle, set transmitter to TX_ON
3568 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
3569 }
3570 else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
3571 {
3573
3574 // Cannot find a clear channel, drop the current packet
3575 // and send the proper confirm/indication according to the packet type
3576 NS_LOG_DEBUG(this << " cannot find clear channel");
3577
3579
3580 Ptr<Packet> pkt = m_txPkt->Copy();
3581 LrWpanMacHeader macHdr;
3582 pkt->RemoveHeader(macHdr);
3583
3584 if (macHdr.IsCommand())
3585 {
3586 CommandPayloadHeader cmdPayload;
3587 pkt->RemoveHeader(cmdPayload);
3588
3589 switch (cmdPayload.GetCommandFrameType())
3590 {
3592 m_macPanId = 0xffff;
3594 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3597 m_csmaCa->SetUnSlottedCsmaCa();
3600
3602 {
3603 MlmeAssociateConfirmParams confirmParams;
3604 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3606 m_mlmeAssociateConfirmCallback(confirmParams);
3607 }
3608 break;
3609 }
3612 {
3613 MlmeCommStatusIndicationParams commStatusParams;
3614 commStatusParams.m_panId = m_macPanId;
3615 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3616 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3617 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3618 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3620 m_mlmeCommStatusIndicationCallback(commStatusParams);
3621 }
3623 break;
3624 }
3626 m_macPanId = 0xffff;
3628 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3631 m_csmaCa->SetUnSlottedCsmaCa();
3634
3636 {
3637 MlmePollConfirmParams pollConfirmParams;
3639 m_mlmePollConfirmCallback(pollConfirmParams);
3640 }
3641 break;
3642 }
3645 {
3646 MlmeCommStatusIndicationParams commStatusParams;
3647 commStatusParams.m_panId = m_macPanId;
3648 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3649 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3650 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3651 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3653 m_mlmeCommStatusIndicationCallback(commStatusParams);
3654 }
3655 break;
3656 }
3659 {
3660 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3661 }
3662 // TODO: Handle orphan notification command during a
3663 // channel access failure when not is not scanning.
3664 break;
3665 }
3667 if (m_scanEvent.IsRunning())
3668 {
3669 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3670 }
3671 // TODO: Handle beacon request command during a
3672 // channel access failure when not scanning.
3673 break;
3674 }
3675 default: {
3676 // TODO: Other commands(e.g. Disassociation notification, etc)
3677 break;
3678 }
3679 }
3681 }
3682 else if (macHdr.IsData())
3683 {
3685 {
3686 McpsDataConfirmParams confirmParams;
3687 confirmParams.m_msduHandle = m_txQueue.front()->txQMsduHandle;
3689 m_mcpsDataConfirmCallback(confirmParams);
3690 }
3691 // remove the copy of the packet that was just sent
3693 }
3694 else
3695 {
3696 // TODO:: specify behavior for other packets
3697 m_txPkt = nullptr;
3698 m_retransmission = 0;
3699 m_numCsmacaRetry = 0;
3700 }
3701
3704 {
3705 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3706 }
3707 else
3708 {
3709 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3710 }
3711 }
3712 else if (m_lrWpanMacState == MAC_CSMA && macState == MAC_CSMA_DEFERRED)
3713 {
3715 m_txPkt = nullptr;
3716 // The MAC is running on beacon mode and the current packet could not be sent in the
3717 // current CAP. The packet will be send on the next CAP after receiving the beacon.
3718 // The PHY state does not change from its current form. The PHY change (RX_ON) will be
3719 // triggered by the scheduled beacon event.
3720
3721 NS_LOG_DEBUG("****** PACKET DEFERRED to the next superframe *****");
3722 }
3723}
3724
3725void
3727{
3729}
3730
3731void
3733{
3735}
3736
3737uint16_t
3739{
3740 return m_macPanId;
3741}
3742
3745{
3747}
3748
3751{
3753}
3754
3755void
3756LrWpanMac::SetPanId(uint16_t panId)
3757{
3758 m_macPanId = panId;
3759}
3760
3761void
3763{
3764 NS_LOG_LOGIC(this << " change lrwpan mac state from " << m_lrWpanMacState << " to "
3765 << newState);
3767 m_lrWpanMacState = newState;
3768}
3769
3770uint64_t
3772{
3773 return lrwpan::aUnitBackoffPeriod + lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
3774 ceil(6 * m_phy->GetPhySymbolsPerOctet());
3775}
3776
3777uint8_t
3779{
3780 return m_macMaxFrameRetries;
3781}
3782
3783void
3785{
3786 NS_LOG_DEBUG("Transmit Queue Size: " << m_txQueue.size());
3787}
3788
3789void
3791{
3792 m_macMaxFrameRetries = retries;
3793}
3794
3795bool
3797{
3799 LrWpanMacHeader macHdr;
3800 m_txPkt->PeekHeader(macHdr);
3801
3802 if (m_coor)
3803 {
3804 // The device is its coordinator and the packet is not to itself
3805 return false;
3806 }
3807 else if (m_macCoordShortAddress == macHdr.GetShortDstAddr() ||
3809 {
3810 return true;
3811 }
3812 else
3813 {
3814 NS_LOG_DEBUG("ERROR: Packet not for the coordinator!");
3815 return false;
3816 }
3817}
3818
3821{
3823
3825 {
3826 return m_macSIFSPeriod;
3827 }
3828 else
3829 {
3830 return m_macLIFSPeriod;
3831 }
3832}
3833
3834void
3836{
3838}
3839
3840void
3842{
3844}
3845
3846uint64_t
3848{
3850 // Sync Header (SHR) + 8 bits PHY header (PHR) + PSDU
3851 return (m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
3852 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet()));
3853}
3854
3855bool
3857{
3859 LrWpanMacHeader macHdr;
3860 m_txPkt->PeekHeader(macHdr);
3861
3862 return macHdr.IsAckReq();
3863}
3864
3865} // namespace ns3
Implements the header for the MAC payload beacon frame according to the IEEE 802.15....
GtsFields GetGtsFields() const
Get the Guaranteed Time Slots (GTS) fields from the beacon payload header.
PendingAddrFields GetPndAddrFields() const
Get the pending address fields from the beacon payload header.
uint16_t GetSuperframeSpecField() const
Get the superframe specification field from the beacon payload header.
void SetSuperframeSpecField(uint16_t sfrmField)
Set the superframe specification field to the beacon payload header.
void SetGtsFields(GtsFields gtsFields)
Set the superframe Guaranteed Time Slot (GTS) fields to the beacon payload header.
void SetPndAddrFields(PendingAddrFields pndAddrFields)
Set the superframe Pending Address fields to the beacon payload header.
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Implements the header for the MAC payload command frame according to the IEEE 802....
void SetPage(uint8_t page)
Set the logical channel page number.
void SetPanId(uint16_t id)
Get the PAN identifier.
Mac16Address GetShortAddr() const
Get the Short address assigned by the coordinator (Association Response and Coordinator Realigment co...
MacCommand GetCommandFrameType() const
Get the command frame type ID.
@ ASSOCIATION_RESP
Association response (RFD true: Rx)
@ BEACON_REQ
Beacon Request (RFD true: none )
@ DATA_REQ
Data Request (RFD true: Tx)
@ ORPHAN_NOTIF
Orphan Notification (RFD true: Tx)
@ ASSOCIATION_REQ
Association request (RFD true: Tx)
@ COOR_REALIGN
Coordinator Realignment (RFD true: Rx)
Mac16Address GetCoordShortAddr() const
Get the coordinator short address.
uint16_t GetPanId() const
Get the PAN identifier.
void SetCommandFrameType(MacCommand macCmd)
Set the command frame type.
void SetCoordShortAddr(Mac16Address addr)
Set the coordinator short address (16 bit address).
uint8_t GetCapabilityField() const
Get the Capability Information Field from the command payload header.
void SetAssociationStatus(uint8_t status)
Set status resulting from the association attempt (Association Response Command).
void SetCapabilityField(uint8_t cap)
Set the Capability Information Field to the command payload header (Association Request Command).
uint8_t GetAssociationStatus() const
Get the status resulting from an association request (Association Response Command).
void SetShortAddr(Mac16Address shortAddr)
Set the Short Address Assigned by the coordinator (Association Response and Coordinator Realigment Co...
void SetChannel(uint8_t channel)
Set the logical channel number.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:69
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
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.
MlmeStartConfirmCallback m_mlmeStartConfirmCallback
This callback is used to report the start of a new PAN or the begin of a new superframe configuration...
MlmeCommStatusIndicationCallback m_mlmeCommStatusIndicationCallback
This callback is instigated through a response primitive.
McpsDataIndicationCallback m_mcpsDataIndicationCallback
This callback is used to notify incoming packets to the upper layers.
MlmeGetConfirmCallback m_mlmeGetConfirmCallback
This callback is used to report the result of an attribute read request to the upper layers.
MlmeBeaconNotifyIndicationCallback m_mlmeBeaconNotifyIndicationCallback
This callback is used to notify incoming beacon packets to the upper layers.
MlmeAssociateConfirmCallback m_mlmeAssociateConfirmCallback
This callback is used to report the status after a device request an association with a coordinator.
MlmeAssociateIndicationCallback m_mlmeAssociateIndicationCallback
This callback is used to indicate the reception of an association request command.
MlmeScanConfirmCallback m_mlmeScanConfirmCallback
This callback is used to report the result of a scan on a group of channels for the selected channel ...
McpsDataConfirmCallback m_mcpsDataConfirmCallback
This callback is used to report data transmission request status 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...
MlmeSetConfirmCallback m_mlmeSetConfirmCallback
This callback is used to report the result of an attribute writing request to the upper layers.
MlmeSyncLossIndicationCallback m_mlmeSyncLossIndicationCallback
This callback is used to indicate the loss of synchronization with a coordinator.
Represent the Mac Header with the Frame Control and Sequence Number fields.
Mac16Address GetShortSrcAddr() const
Get the Source Short address.
@ LRWPAN_MAC_BEACON
LRWPAN_MAC_BEACON.
@ LRWPAN_MAC_COMMAND
LRWPAN_MAC_COMMAND.
@ LRWPAN_MAC_DATA
LRWPAN_MAC_DATA.
@ LRWPAN_MAC_ACKNOWLEDGMENT
LRWPAN_MAC_ACKNOWLEDGMENT.
@ LRWPAN_MAC_RESERVED
LRWPAN_MAC_RESERVED.
bool IsCommand() const
Returns true if the header is a command.
bool IsBeacon() const
Returns true if the header is a beacon.
Mac64Address GetExtSrcAddr() const
Get the Source Extended address.
void SetNoPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to false.
uint8_t GetSrcAddrMode() const
Get the Source Addressing Mode of Frame control field.
void SetPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to true.
void SetSrcAddrMode(uint8_t addrMode)
Set the Source address mode.
uint8_t GetDstAddrMode() const
Get the Dest.
void SetSecDisable()
Set the Frame Control field "Security Enabled" bit to false.
void SetSrcAddrFields(uint16_t panId, Mac16Address addr)
Set Source address fields.
bool IsAcknowledgment() const
Returns true if the header is an ack.
bool IsData() const
Returns true if the header is a data.
void SetDstAddrFields(uint16_t panId, Mac16Address addr)
Set Destination address fields.
uint8_t GetSeqNum() const
Get the frame Sequence number.
void SetDstAddrMode(uint8_t addrMode)
Set the Destination address mode.
void SetNoAckReq()
Set the Frame Control field "Ack. Request" bit to false.
Mac64Address GetExtDstAddr() const
Get the Destination Extended address.
LrWpanMacType GetType() const
Get the header type.
uint16_t GetDstPanId() const
Get the Destination PAN ID.
uint8_t GetFrameVer() const
Get the Frame Version of Frame control field.
void SetFrameVer(uint8_t ver)
Set the Frame version.
uint16_t GetSrcPanId() const
Get the Source PAN ID.
bool IsAckReq() const
Check if Ack.
Mac16Address GetShortDstAddr() const
Get the Destination Short address.
void SetAckReq()
Set the Frame Control field "Ack. Request" bit to true.
Class that implements the LR-WPAN MAC state machine.
Definition: lr-wpan-mac.h:161
uint32_t m_incomingBeaconInterval
Indication of the interval a node should receive a superframe expressed in symbols.
Definition: lr-wpan-mac.h:610
uint32_t GetIfsSize()
Get the size of the Interframe Space according to MPDU size (m_txPkt).
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.
Definition: lr-wpan-mac.cc:384
Ptr< LrWpanCsmaCa > m_csmaCa
The CSMA/CA implementation used by this MAC.
Definition: lr-wpan-mac.h:1132
uint64_t m_assocRespCmdWaitTime
The maximum wait time for an association response command after the reception of data request command...
Definition: lr-wpan-mac.h:406
uint64_t GetMacAckWaitDuration() const
Get the macAckWaitDuration attribute value.
Time m_macBeaconRxTime
The time that the device received its last bit of the beacon frame.
Definition: lr-wpan-mac.h:391
void PlmeCcaConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
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...
Definition: lr-wpan-mac.cc:683
~LrWpanMac() override
Definition: lr-wpan-mac.cc:263
bool m_macRxOnWhenIdle
Indication of whether the MAC sublayer is to enable its receiver during idle periods.
Definition: lr-wpan-mac.h:544
bool m_macAssociationPermit
Indication of whether a coordinator is currently allowing association.
Definition: lr-wpan-mac.h:563
TracedCallback< Ptr< const Packet > > m_macTxOkTrace
The trace source fired when packets where successfully transmitted, that is an acknowledgment was rec...
Definition: lr-wpan-mac.h:1029
uint64_t m_rxBeaconSymbols
The total size of the received beacon in symbols.
Definition: lr-wpan-mac.h:461
void SetRxOnWhenIdle(bool rxOnWhenIdle)
Set if the receiver should be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:337
uint64_t GetTxPacketSymbols()
Obtain the number of symbols in the packet which is currently being sent by the MAC layer.
bool m_panCoor
Indication of whether the current device is the PAN coordinator.
Definition: lr-wpan-mac.h:587
void PlmeSetTRXStateConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.8 PLME-SET-TRX-STATE.confirm Set PHY state.
uint8_t m_numCsmacaRetry
The number of CSMA/CA retries used for sending the current packet.
Definition: lr-wpan-mac.h:1247
static TypeId GetTypeId()
Get the type ID.
Definition: lr-wpan-mac.cc:91
uint8_t m_deviceCapability
Indication of current device capability (FFD or RFD)
Definition: lr-wpan-mac.h:621
void AwaitBeacon()
Called after the end of an INCOMING superframe to start the moment a device waits for a new incoming ...
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...
Definition: lr-wpan-mac.cc:903
bool m_coor
Indicates if the current device is a coordinator type.
Definition: lr-wpan-mac.h:592
void LostAssocRespCommand()
Called after m_assocRespCmdWaitTime timeout while waiting for an association response command.
bool isCoordDest()
Check if the packet destination is its coordinator.
EventId m_trackingEvent
Scheduler event to track the incoming beacons.
Definition: lr-wpan-mac.h:1308
uint32_t m_maxIndTxQueueSize
The maximum size of the indirect transmit queue (The pending transaction list).
Definition: lr-wpan-mac.h:1191
EventId m_assocResCmdWaitTimeout
Scheduler event for the lost of a association response command frame.
Definition: lr-wpan-mac.h:1268
void PurgeInd()
Purge expired transactions from the pending transactions list.
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 ...
Definition: lr-wpan-mac.cc:758
void RemoveFirstTxQElement()
Remove the tip of the transmission queue, including clean up related to the last packet transmission.
void PlmeEdConfirm(LrWpanPhyEnumeration status, uint8_t energyLevel)
IEEE 802.15.4-2006 section 6.2.2.4 PLME-ED.confirm status and energy level.
TracedCallback< Ptr< const Packet > > m_macRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
Definition: lr-wpan-mac.h:1063
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
A trace source that emulates a promiscuous mode protocol sniffer connected to the device.
Definition: lr-wpan-mac.h:1112
void SetExtendedAddress(Mac64Address address)
Set the extended address of this MAC.
Definition: lr-wpan-mac.cc:363
uint32_t m_macLIFSPeriod
The minimum time forming a Long InterFrame Spacing (LIFS) period.
Definition: lr-wpan-mac.h:550
void StartInactivePeriod(SuperframeType superframeType)
Start the Inactive Period in a beacon-enabled mode.
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
The trace source fired when packets are dropped due to missing ACKs or because of transmission failur...
Definition: lr-wpan-mac.h:1037
TracedCallback< Ptr< const Packet > > m_macIndTxDequeueTrace
The trace source fired when packets are dequeued from the L3/l2 indirect transmission queue (Pending ...
Definition: lr-wpan-mac.h:1013
TracedCallback< Ptr< const Packet > > m_macIndTxDropTrace
The trace source fired when packets are dropped due to indirect Tx queue overflows or expiration.
Definition: lr-wpan-mac.h:1045
Mac16Address GetShortAddress() const
Get the short address of this MAC.
Definition: lr-wpan-mac.cc:370
void SendDataRequestCommand()
Used to send a data request command (i.e.
EventId m_cfpEvent
Scheduler event for the end of the outgoing superframe CFP.
Definition: lr-wpan-mac.h:1293
void PlmeGetAttributeConfirm(LrWpanPhyEnumeration status, LrWpanPibAttributeIdentifier id, Ptr< LrWpanPhyPibAttributes > 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_macMaxFrameRetries
The maximum number of retries allowed after a transmission failure.
Definition: lr-wpan-mac.h:537
Mac64Address m_macCoordExtendedAddress
The extended address of the coordinator through which the device is associated.
Definition: lr-wpan-mac.h:422
PendingPrimitiveStatus m_pendPrimitive
Indicates the pending primitive when PLME.SET operation (page or channel switch) is called from withi...
Definition: lr-wpan-mac.h:1236
uint8_t GetMacMaxFrameRetries() const
Get the macMaxFrameRetries attribute value.
uint16_t m_channelScanIndex
The channel list index used to obtain the current scanned channel.
Definition: lr-wpan-mac.h:1230
uint16_t GetPanId() const
Get the PAN id used by this MAC.
PendingAddrFields GetPendingAddrFields()
Constructs Pending Address Fields from the local information, the Pending Address Fields are part of ...
std::vector< PanDescriptor > m_panDescriptorList
The list of PAN descriptors accumulated during channel scans, used to select a PAN to associate.
Definition: lr-wpan-mac.h:1197
void SendBeaconRequestCommand()
Called to send a beacon request command.
EventId m_respWaitTimeout
Scheduler event for a response to a request command frame.
Definition: lr-wpan-mac.h:1263
uint32_t m_maxTxQueueSize
The maximum size of the transmit queue.
Definition: lr-wpan-mac.h:1186
Ptr< Packet > m_macBeaconPayload
The contents of the beacon payload.
Definition: lr-wpan-mac.h:525
std::deque< Ptr< TxQueueElement > > m_txQueue
The transmit queue used by the MAC.
Definition: lr-wpan-mac.h:1175
SequenceNumber8 m_macBsn
Sequence number added to transmitted beacon frame, 00-ff.
Definition: lr-wpan-mac.h:518
Ptr< Packet > m_rxPkt
The command request packet received.
Definition: lr-wpan-mac.h:1158
TracedCallback< Ptr< const Packet > > m_macIndTxEnqueueTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
Definition: lr-wpan-mac.h:1005
void SetLrWpanMacState(LrWpanMacState macState)
CSMA-CA algorithm calls back the MAC after executing channel assessment.
Mac16Address m_shortAddress
The short address (16 bit address) used by this MAC.
Definition: lr-wpan-mac.h:1165
uint8_t m_macSuperframeOrder
Used by a PAN coordinator or coordinator.
Definition: lr-wpan-mac.h:444
void SetCsmaCa(Ptr< LrWpanCsmaCa > csmaCa)
Set the CSMA/CA implementation to be used by the MAC.
void BeaconSearchTimeout()
Called if the device is unable to locate a beacon in the time set by MLME-SYNC.request.
bool isTxAckReq()
Check if the packet to transmit requires acknowledgment.
std::vector< uint8_t > m_energyDetectList
The list of energy measurements, one for each channel searched during an ED scan.
Definition: lr-wpan-mac.h:1202
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...
void SendOneBeacon()
Called to send a single beacon frame.
Time m_macBeaconTxTime
The time that the device transmitted its last beacon frame.
Definition: lr-wpan-mac.h:383
uint16_t GetSuperframeField()
Constructs a Superframe specification field from the local information, the superframe Specification ...
void EndStartRequest()
Called to end a MLME-START.request after changing the page and channel number.
TracedCallback< LrWpanMacState, LrWpanMacState > m_macStateLogger
A trace source that fires when the LrWpanMac changes states.
Definition: lr-wpan-mac.h:1122
Mac64Address GetExtendedAddress() const
Get the extended address of this MAC.
Definition: lr-wpan-mac.cc:377
EventId m_setMacState
Scheduler event for a deferred MAC state change.
Definition: lr-wpan-mac.h:1273
uint64_t m_macResponseWaitTime
The maximum time, in multiples of aBaseSuperframeDuration, a device shall wait for a response command...
Definition: lr-wpan-mac.h:398
void EnqueueInd(Ptr< Packet > p)
Adds a packet to the pending transactions list (Indirect transmissions).
void SendAssocResponseCommand(Ptr< Packet > rxDataReqPkt)
Called to send an associate response command.
void StartCFP(SuperframeType superframeType)
Called to begin the Contention Free Period (CFP) in a beacon-enabled mode.
EventId m_scanEnergyEvent
Scheduler event for the end of a ED channel scan.
Definition: lr-wpan-mac.h:1323
bool PrepareRetransmission()
Check for remaining retransmissions for the packet currently being sent.
void EnqueueTxQElement(Ptr< TxQueueElement > txQElement)
Add an element to the transmission queue.
void SetPanId(uint16_t panId)
Set the PAN id used by this MAC.
EventId m_scanEvent
Scheduler event for the end of an ACTIVE or PASSIVE channel scan.
Definition: lr-wpan-mac.h:1313
TracedCallback< Ptr< const Packet > > m_snifferTrace
A trace source that emulates a non-promiscuous protocol sniffer connected to the device.
Definition: lr-wpan-mac.h:1092
uint8_t m_incomingBeaconOrder
The beaconOrder value of the INCOMING frame.
Definition: lr-wpan-mac.h:473
SequenceNumber8 m_macDsn
Sequence number added to transmitted data or MAC command frame, 00-ff.
Definition: lr-wpan-mac.h:512
void SendOrphanNotificationCommand()
Called to send a orphan notification command.
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...
Definition: lr-wpan-mac.cc:863
uint32_t m_ifs
The value of the necessary InterFrame Space after the transmission of a packet.
Definition: lr-wpan-mac.h:582
uint16_t m_macTransactionPersistenceTime
The maximum time (in UNIT periods) that a transaction is stored by a coordinator and indicated in its...
Definition: lr-wpan-mac.h:455
Mac16Address GetCoordShortAddress() const
Get the coordinator short address currently associated to this device.
void ChangeMacState(LrWpanMacState newState)
Change the current MAC state to the given new state.
MlmeStartRequestParams m_startParams
The parameters used during a MLME-START.request.
Definition: lr-wpan-mac.h:1219
void AckWaitTimeout()
Handle an ACK timeout with a packet retransmission, if there are retransmission left,...
std::vector< uint8_t > m_unscannedChannels
The list of unscanned channels during a scan operation.
Definition: lr-wpan-mac.h:1207
Mac64Address GetCoordExtAddress() const
Get the coordinator extended address currently associated to this device.
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...
Definition: lr-wpan-mac.cc:623
uint8_t m_macBeaconOrder
Used by a PAN coordinator or coordinator.
Definition: lr-wpan-mac.h:436
TracedCallback< Time > m_macIfsEndTrace
The trace source is fired at the end of any Interframe Space (IFS).
Definition: lr-wpan-mac.h:969
TracedValue< SuperframeStatus > m_outSuperframeStatus
The current period of the outgoing superframe.
Definition: lr-wpan-mac.h:1147
void PlmeSetAttributeConfirm(LrWpanPhyEnumeration status, LrWpanPibAttributeIdentifier id)
IEEE 802.15.4-2006 section 6.2.2.10 PLME-SET.confirm Set attributes per definition from Table 23 in s...
bool DequeueInd(Mac64Address dst, Ptr< IndTxQueueElement > entry)
Extracts a packet from pending transactions list (Indirect transmissions).
MlmeAssociateRequestParams m_associateParams
The parameters used during a MLME-ASSOCIATE.request.
Definition: lr-wpan-mac.h:1225
LrWpanMac()
Default constructor.
Definition: lr-wpan-mac.cc:202
void CheckQueue()
Check the transmission queue.
EventId m_ackWaitTimeout
Scheduler event for the ACK timeout of the currently transmitted data packet.
Definition: lr-wpan-mac.h:1258
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...
Definition: lr-wpan-mac.cc:584
bool m_macPromiscuousMode
Indicates if MAC sublayer is in receive all mode.
Definition: lr-wpan-mac.h:493
uint8_t m_fnlCapSlot
Indication of the Slot where the CAP portion of the OUTGOING Superframe ends.
Definition: lr-wpan-mac.h:466
uint32_t m_macSIFSPeriod
The minimum time forming a Short InterFrame Spacing (SIFS) period.
Definition: lr-wpan-mac.h:556
void IfsWaitTimeout(Time ifsTime)
After a successful transmission of a frame (beacon, data) or an ack frame reception,...
std::deque< Ptr< IndTxQueueElement > > m_indTxQueue
The indirect transmit queue used by the MAC pending messages (The pending transaction list).
Definition: lr-wpan-mac.h:1181
void PrintPendingTxQueue(std::ostream &os) const
Print the Pending transaction list.
uint32_t m_beaconInterval
Indication of the Interval used by the coordinator to transmit beacon frames expressed in symbols.
Definition: lr-wpan-mac.h:598
TracedValue< LrWpanMacState > m_lrWpanMacState
The current state of the MAC layer.
Definition: lr-wpan-mac.h:1137
TracedCallback< Ptr< const Packet > > m_macTxEnqueueTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
Definition: lr-wpan-mac.h:989
EventId m_capEvent
Scheduler event for the end of the outgoing superframe CAP.
Definition: lr-wpan-mac.h:1288
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets are being sent down to L1.
Definition: lr-wpan-mac.h:1020
uint16_t m_macPanId
16 bits id of PAN on which this device is operating.
Definition: lr-wpan-mac.h:500
void EndChannelScan()
Called at the end of the current channel scan (Active or Passive) for a given duration.
void DoInitialize() override
Initialize() implementation.
Definition: lr-wpan-mac.cc:268
void MlmeGetRequest(LrWpanMacPibAttributeIdentifier id) override
IEEE 802.15.4-2011, section 6.2.5.1 MLME-GET.request Request information about a given PIB attribute.
Definition: lr-wpan-mac.cc:962
void PrintTxQueue(std::ostream &os) const
Print the Transmit Queue.
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired for packets successfully received by the device but dropped before being forwa...
Definition: lr-wpan-mac.h:1072
bool m_macAutoRequest
Indication of whether a device automatically sends data request command if its address is listed in t...
Definition: lr-wpan-mac.h:572
uint8_t m_incomingSuperframeOrder
Used by all devices that have a parent.
Definition: lr-wpan-mac.h:481
uint16_t m_macPanIdScan
Temporally stores the value of the current m_macPanId when a MLME-SCAN.request is performed.
Definition: lr-wpan-mac.h:506
uint32_t m_macBeaconPayloadLength
The length, in octets, of the beacon payload.
Definition: lr-wpan-mac.h:531
TracedCallback< Ptr< const Packet > > m_macTxDequeueTrace
The trace source fired when packets are dequeued from the L3/l2 transmission queue.
Definition: lr-wpan-mac.h:997
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...
Definition: lr-wpan-mac.cc:803
void PdDataConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.1.2 Confirm the end of transmission of an MPDU to MAC.
uint8_t m_numLostBeacons
The number of consecutive loss beacons in a beacon tracking operation.
Definition: lr-wpan-mac.h:631
Ptr< Packet > m_txPkt
The packet which is currently being sent by the MAC layer.
Definition: lr-wpan-mac.h:1152
void SendAssocRequestCommand()
Called to send an associate request command.
uint8_t m_maxEnergyLevel
The maximum energy level detected during ED scan on the current channel.
Definition: lr-wpan-mac.h:577
void DoDispose() override
Destructor implementation.
Definition: lr-wpan-mac.cc:283
MlmeScanRequestParams m_scanParams
The parameters used during a MLME-SCAN.request.
Definition: lr-wpan-mac.h:1213
void SetPhy(Ptr< LrWpanPhy > phy)
Set the underlying PHY for the MAC.
Ptr< LrWpanPhy > GetPhy()
Get the underlying PHY of the MAC.
uint8_t m_lastRxFrameLqi
Keep track of the last received frame Link Quality Indicator.
Definition: lr-wpan-mac.h:1252
EventId m_scanOrphanEvent
Scheduler event for the end of an ORPHAN channel scan.
Definition: lr-wpan-mac.h:1318
void EndAssociateRequest()
Called to end an MLME-ASSOCIATE.request after changing the page and channel number.
Definition: lr-wpan-mac.cc:738
Mac64Address m_selfExt
The extended 64 address (IEEE EUI-64) used by this MAC.
Definition: lr-wpan-mac.h:1170
EventId m_incCapEvent
Scheduler event for the end of the incoming superframe CAP.
Definition: lr-wpan-mac.h:1298
void SetTxQMaxSize(uint32_t queueSize)
Set the max size of the transmit queue.
void SetIndTxQMaxSize(uint32_t queueSize)
Set the max size of the indirect transmit queue (Pending Transaction list)
bool m_beaconTrackingOn
Indication of whether the current device is tracking incoming beacons.
Definition: lr-wpan-mac.h:626
uint32_t m_superframeDuration
Indication of the superframe duration in symbols.
Definition: lr-wpan-mac.h:604
bool GetRxOnWhenIdle() const
Check if the receiver will be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:331
Mac16Address m_macCoordShortAddress
The short address of the coordinator through which the device is associated.
Definition: lr-wpan-mac.h:415
GtsFields GetGtsFields()
Constructs the Guaranteed Time Slots (GTS) Fields from local information.
Ptr< LrWpanPhy > m_phy
The PHY associated with this MAC.
Definition: lr-wpan-mac.h:1127
void MlmeSetRequest(LrWpanMacPibAttributeIdentifier id, Ptr< LrWpanMacPibAttributes > attribute) override
IEEE 802.15.4-2011, section 6.2.11.1 MLME-SET.request Attempts to write the given value to the indica...
Definition: lr-wpan-mac.cc:918
void EndChannelEnergyScan()
Called at the end of one ED channel scan.
void PrintTransmitQueueSize()
Print the number of elements in the packet transmit queue.
void StartCAP(SuperframeType superframeType)
Called to begin the Contention Access Period (CAP) in a beacon-enabled mode.
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
Definition: lr-wpan-mac.h:1054
EventId m_ifsEvent
Scheduler event for Interframe spacing wait time.
Definition: lr-wpan-mac.h:1278
EventId m_beaconEvent
Scheduler event for generation of one beacon.
Definition: lr-wpan-mac.h:1283
uint32_t m_incomingSuperframeDuration
Indication of the superframe duration in symbols (e.g.
Definition: lr-wpan-mac.h:616
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 ...
Definition: lr-wpan-mac.h:981
void RemovePendTxQElement(Ptr< Packet > p)
Remove an element from the pending transaction list.
void SetShortAddress(Mac16Address address)
Set the short address of this MAC.
Definition: lr-wpan-mac.cc:356
void SetMacMaxFrameRetries(uint8_t retries)
Set the macMaxFrameRetries attribute value.
uint8_t m_retransmission
The number of already used retransmission for the currently transmitted packet.
Definition: lr-wpan-mac.h:1242
EventId m_incCfpEvent
Scheduler event for the end of the incoming superframe CFP.
Definition: lr-wpan-mac.h:1303
void SendAck(uint8_t seqno)
Send an acknowledgment packet for the given sequence number.
uint8_t m_incomingFnlCapSlot
Indication of the Slot where the CAP portion of the INCOMING Superframe ends.
Definition: lr-wpan-mac.h:486
TracedValue< SuperframeStatus > m_incSuperframeStatus
The current period of the incoming superframe.
Definition: lr-wpan-mac.h:1142
void SetAssociatedCoor(Mac16Address mac)
Check if the packet destination is its coordinator.
Represent the Mac Trailer with the Frame Check Sequence field.
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.
void EnableFcs(bool enable)
Enable or disable FCS calculation for this trailer.
This class can contain 16 bit addresses.
Definition: mac16-address.h:44
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
Definition: mac64-address.h:46
static Mac64Address Allocate()
Allocate a new Mac64Address.
static bool ChecksumEnabled()
Definition: node.cc:285
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:359
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Represent the Pending Address Specification field.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:217
Represent the Superframe Specification information field.
uint8_t GetFinalCapSlot() const
Get the the Final CAP Slot.
uint16_t GetSuperframe() const
Get the Superframe specification information field.
void SetAssocPermit(bool assocPermit)
Set the Superframe Specification Association Permit field.
void SetBattLifeExt(bool battLifeExt)
Set the Superframe Specification Battery Life Extension (BLE).
uint8_t GetBeaconOrder() const
Get the Superframe Specification Beacon Order field.
bool IsBattLifeExt() const
Check if the Battery Life Extension bit is enabled.
void SetFinalCapSlot(uint8_t capSlot)
Set the superframe specification Final CAP slot field.
void SetSuperframeOrder(uint8_t frmOrder)
Set the superframe specification Superframe Order field.
void SetPanCoor(bool panCoor)
Set the Superframe Specification PAN coordinator field.
void SetBeaconOrder(uint8_t bcnOrder)
Set the superframe specification Beacon Order field.
uint8_t GetFrameOrder() const
Get the Superframe Specification Frame Order field.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
@ S
second
Definition: nstime.h:116
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
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:66
#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:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
LrWpanMacState
MAC states.
Definition: lr-wpan-mac.h:72
LrWpanPhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
Definition: lr-wpan-phy.h:111
LrWpanMacStatus
The status of a confirm or an indication primitive as a result of a previous request.
SuperframeType
Superframe type.
Definition: lr-wpan-mac.h:113
LrWpanMacPibAttributeIdentifier
IEEE802.15.4-2011 MAC PIB Attribute Identifiers Table 52 in section 6.4.2.
LrWpanPibAttributeIdentifier
IEEE802.15.4-2006 PHY PIB Attribute Identifiers Table 23 in section 6.4.2.
Definition: lr-wpan-phy.h:163
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition: lr-wpan-mac.h:77
@ MAC_IDLE
MAC_IDLE.
Definition: lr-wpan-mac.h:73
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition: lr-wpan-mac.h:82
@ MAC_CSMA
MAC_CSMA.
Definition: lr-wpan-mac.h:74
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition: lr-wpan-mac.h:78
@ MAC_GTS
MAC_GTS.
Definition: lr-wpan-mac.h:80
@ SET_PHY_TX_ON
SET_PHY_TX_ON.
Definition: lr-wpan-mac.h:79
@ MAC_INACTIVE
MAC_INACTIVE.
Definition: lr-wpan-mac.h:81
@ MAC_SENDING
MAC_SENDING.
Definition: lr-wpan-mac.h:75
@ MAC_ACK_PENDING
MAC_ACK_PENDING.
Definition: lr-wpan-mac.h:76
@ FFD
Full Functional Device (FFD)
@ MLMESCAN_PASSIVE
@ MLMESCAN_ORPHAN
@ MLMESCAN_ACTIVE
@ CFP
Contention Free Period.
Definition: lr-wpan-mac.h:103
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition: lr-wpan-mac.h:104
@ CAP
Contention Access Period.
Definition: lr-wpan-mac.h:102
@ BEACON
The Beacon transmission or reception Period.
Definition: lr-wpan-mac.h:101
@ IEEE_802_15_4_PHY_SUCCESS
Definition: lr-wpan-phy.h:119
@ IEEE_802_15_4_PHY_UNSPECIFIED
Definition: lr-wpan-phy.h:124
@ IEEE_802_15_4_PHY_TRX_OFF
Definition: lr-wpan-phy.h:120
@ IEEE_802_15_4_PHY_RX_ON
Definition: lr-wpan-phy.h:118
@ IEEE_802_15_4_PHY_TX_ON
Definition: lr-wpan-phy.h:121
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:61
@ TX_OPTION_INDIRECT
TX_OPTION_INDIRECT.
Definition: lr-wpan-mac.h:63
@ TX_OPTION_GTS
TX_OPTION_GTS.
Definition: lr-wpan-mac.h:62
@ 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.
@ MLME_SCAN_REQ
Pending MLME-SCAN.request primitive.
Definition: lr-wpan-mac.h:127
@ MLME_ASSOC_REQ
Pending MLME-ASSOCIATION.request primitive.
Definition: lr-wpan-mac.h:128
@ MLME_START_REQ
Pending MLME-START.request primitive.
Definition: lr-wpan-mac.h:126
@ MLME_NONE
No pending primitive.
Definition: lr-wpan-mac.h:125
@ SHORT_ADDR
@ NO_PANID_ADDR
@ ADDR_MODE_RESERVED
@ INCOMING
Incoming Superframe.
Definition: lr-wpan-mac.h:115
@ OUTGOING
Outgoing Superframe.
Definition: lr-wpan-mac.h:114
@ pCurrentChannel
@ macBeaconPayloadLength
@ pCurrentPage
@ macShortAddress
@ macBeaconPayload
@ macExtendedAddress
@ phyCurrentChannel
Definition: lr-wpan-phy.h:164
@ phyCurrentPage
Definition: lr-wpan-phy.h:168
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
SequenceNumber< uint8_t, int8_t > SequenceNumber8
8 bit Sequence number.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
MCPS-DATA.confirm params.
LrWpanMacStatus m_status
The status of the last MSDU transmission.
uint8_t m_msduHandle
MSDU handle.
MCPS-DATA.indication params.
MCPS-DATA.request params.
MLME-ASSOCIATE.confirm params.
LrWpanMacStatus m_status
The status of a MLME-associate.request.
Mac16Address m_assocShortAddr
The short address used in the association request.
MLME-ASSOCIATE.indication params.
uint8_t capabilityInfo
The operational capabilities of the device requesting association.
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.
MLME-ASSOCIATE.request params.
uint8_t m_chNum
The channel number on which to attempt association.
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).
Mac64Address m_coordExtAddr
The extended address of the coordinator with which to associate.
Mac16Address m_coordShortAddr
The short address of the coordinator with which to associate.
uint16_t m_coordPanId
The identifier of the PAN with which to associate.
MLME-ASSOCIATE.response params.
MLME-BEACON-NOTIFY.indication params.
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.
PanDescriptor m_panDescriptor
The PAN descriptor for the received beacon.
MLME-COMM-STATUS.indication params.
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.
Mac64Address m_dstExtAddr
The extended address of the device for which the frame was intended.
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.
uint8_t m_dstAddrMode
The destination addressing mode for this primitive.
uint8_t m_srcAddrMode
The source addressing mode for this primitive.
LrWpanMacStatus m_status
The communication status.
MLME-ORPHAN.indication params.
Mac64Address m_orphanAddr
The address of the orphaned device.
MLME-ORPHAN.response params.
MLME-START.confirm params.
LrWpanMacStatus m_status
The confirmation status resulting from a MLME-poll.request.
MLME-POLL.request params.
MLME-SCAN.confirm params.
std::vector< PanDescriptor > m_panDescList
A list of PAN descriptor, one for each beacon found (Not valid for ED and Orphan scans).
uint32_t m_chPage
The channel page on which the scan was performed.
uint8_t m_scanType
Indicates the type of scan performed (ED,ACTIVE,PASSIVE,ORPHAN).
std::vector< uint8_t > m_unscannedCh
A list of channels given in the request which were not scanned (Not valid for ED scans).
std::vector< uint8_t > m_energyDetList
A list of energy measurements, one for each channel searched during ED scan (Not valid for Active,...
LrWpanMacStatus m_status
The status of the scan request.
uint8_t m_resultListSize
The number of elements returned in the appropriate result list.
MLME-SCAN.request params.
uint32_t m_scanChannels
The channel numbers to be scanned.
uint32_t m_chPage
The channel page on which to perform scan.
uint8_t m_scanDuration
The factor (0-14) used to calculate the length of time to spend scanning.
LrWpanMlmeScanType m_scanType
Indicates the type of scan performed as described in IEEE 802.15.4-2011 (5.1.2.1).
MLME-SET.confirm params.
LrWpanMacStatus m_status
The result of the request to write the PIB attribute.
LrWpanMacPibAttributeIdentifier id
The id of the PIB attribute that was written.
MLME-START.confirm params.
LrWpanMacStatus m_status
The status of a MLME-start.request.
MLME-START.request params.
uint32_t m_logChPage
Logical channel page on which to start using the new superframe configuration.
uint8_t m_logCh
Logical channel on which to start using the new superframe configuration.
bool m_panCoor
On true this device will become coordinator.
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...
uint16_t m_PanId
Pan Identifier used by the device.
uint8_t m_sfrmOrd
Superframe Order, indicates the length of the CAP in time slots.
bool m_battLifeExt
Flag indicating whether or not the Battery life extension (BLE) features are used.
MLME-SYNC-LOSS.indication params.
uint16_t m_panId
The PAN identifier with which the device lost synchronization or to which it was realigned.
LrWpanMacStatus m_lossReason
The reason for the lost of synchronization.
MLME-SYNC.request params.
PAN Descriptor, Table 17 IEEE 802.15.4-2011.
LrWpanAddressMode m_coorAddrMode
The coordinator addressing mode corresponding to the received beacon frame.
uint16_t m_superframeSpec
The superframe specification as specified in the received beacon frame.
Mac64Address m_coorExtAddr
The coordinator extended address as specified in the coordinator address mode.
Mac16Address m_coorShortAddr
The coordinator short address as specified in the coordinator address mode.
uint8_t m_logChPage
The current channel page occupied by the network.
uint16_t m_coorPanId
The PAN ID of the coordinator as specified in the received beacon frame.
bool m_gtsPermit
TRUE if the beacon is from the PAN coordinator that is accepting GTS requests.
uint8_t m_linkQuality
The LQI at which the network beacon was received.
Time m_timeStamp
Beacon frame reception time.
uint8_t m_logCh
The current channel number occupied by the network.
std::ofstream queueSize