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_macExtendedAddress << "] ";
44
45namespace ns3
46{
47namespace lrwpan
48{
49
50NS_LOG_COMPONENT_DEFINE("LrWpanMac");
52
53std::ostream&
54operator<<(std::ostream& os, const MacState& state)
55{
56 switch (state)
57 {
59 os << "MAC IDLE";
60 break;
62 os << "CSMA";
63 break;
65 os << "SENDING";
66 break;
68 os << "ACK PENDING";
69 break;
71 os << "CHANNEL_ACCESS_FAILURE";
72 break;
74 os << "CHANNEL IDLE";
75 break;
77 os << "SET PHY to TX ON";
78 break;
80 os << "MAC GTS PERIOD";
81 break;
83 os << "SUPERFRAME INACTIVE PERIOD";
84 break;
86 os << "CSMA DEFERRED TO NEXT PERIOD";
87 break;
88 }
89 return os;
90};
91
94{
95 static TypeId tid =
96 TypeId("ns3::LrWpanMac")
98 .SetGroupName("LrWpan")
99 .AddConstructor<LrWpanMac>()
100 .AddAttribute("PanId",
101 "16-bit identifier of the associated PAN",
104 MakeUintegerChecker<uint16_t>())
105 .AddTraceSource("MacTxEnqueue",
106 "Trace source indicating a packet has been "
107 "enqueued in the transaction queue",
109 "ns3::Packet::TracedCallback")
110 .AddTraceSource("MacTxDequeue",
111 "Trace source indicating a packet has was "
112 "dequeued from the transaction queue",
114 "ns3::Packet::TracedCallback")
115 .AddTraceSource("MacIndTxEnqueue",
116 "Trace source indicating a packet has been "
117 "enqueued in the indirect transaction queue",
119 "ns3::Packet::TracedCallback")
120 .AddTraceSource("MacIndTxDequeue",
121 "Trace source indicating a packet has was "
122 "dequeued from the indirect transaction queue",
124 "ns3::Packet::TracedCallback")
125 .AddTraceSource("MacTx",
126 "Trace source indicating a packet has "
127 "arrived for transmission by this device",
129 "ns3::Packet::TracedCallback")
130 .AddTraceSource("MacTxOk",
131 "Trace source indicating a packet has been "
132 "successfully sent",
134 "ns3::Packet::TracedCallback")
135 .AddTraceSource("MacTxDrop",
136 "Trace source indicating a packet has been "
137 "dropped during transmission",
139 "ns3::Packet::TracedCallback")
140 .AddTraceSource("MacIndTxDrop",
141 "Trace source indicating a packet has been "
142 "dropped from the indirect transaction queue"
143 "(The pending transaction list)",
145 "ns3::Packet::TracedCallback")
146 .AddTraceSource("MacPromiscRx",
147 "A packet has been received by this device, "
148 "has been passed up from the physical layer "
149 "and is being forwarded up the local protocol stack. "
150 "This is a promiscuous trace,",
152 "ns3::Packet::TracedCallback")
153 .AddTraceSource("MacRx",
154 "A packet has been received by this device, "
155 "has been passed up from the physical layer "
156 "and is being forwarded up the local protocol stack. "
157 "This is a non-promiscuous trace,",
159 "ns3::Packet::TracedCallback")
160 .AddTraceSource("MacRxDrop",
161 "Trace source indicating a packet was received, "
162 "but dropped before being forwarded up the stack",
164 "ns3::Packet::TracedCallback")
165 .AddTraceSource("Sniffer",
166 "Trace source simulating a non-promiscuous "
167 "packet sniffer attached to the device",
169 "ns3::Packet::TracedCallback")
170 .AddTraceSource("PromiscSniffer",
171 "Trace source simulating a promiscuous "
172 "packet sniffer attached to the device",
174 "ns3::Packet::TracedCallback")
175 .AddTraceSource("MacStateValue",
176 "The state of LrWpan Mac",
178 "ns3::TracedValueCallback::LrWpanMacState")
179 .AddTraceSource("MacIncSuperframeStatus",
180 "The period status of the incoming superframe",
182 "ns3::TracedValueCallback::SuperframeState")
183 .AddTraceSource("MacOutSuperframeStatus",
184 "The period status of the outgoing superframe",
186 "ns3::TracedValueCallback::SuperframeState")
187 .AddTraceSource("MacState",
188 "The state of LrWpan Mac",
190 "ns3::LrWpanMac::StateTracedCallback")
191 .AddTraceSource("MacSentPkt",
192 "Trace source reporting some information about "
193 "the sent packet",
195 "ns3::LrWpanMac::SentTracedCallback")
196 .AddTraceSource("IfsEnd",
197 "Trace source reporting the end of an "
198 "Interframe space (IFS)",
200 "ns3::Packet::TracedCallback");
201 return tid;
202}
203
205{
206 // First set the state to a known value, call ChangeMacState to fire trace source.
208
210
213
214 m_macRxOnWhenIdle = true;
215 m_macPanId = 0xffff;
217 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
220 m_macPromiscuousMode = false;
224 m_txPkt = nullptr;
225 m_rxPkt = nullptr;
227 m_ifs = 0;
228
229 m_macLIFSPeriod = 40;
230 m_macSIFSPeriod = 12;
231
232 m_panCoor = false;
233 m_coor = false;
234 m_macBeaconOrder = 15;
236 m_macTransactionPersistenceTime = 500; // 0x01F5
238 m_macAutoRequest = true;
239
242 m_beaconTrackingOn = false;
244
248
251
252 m_maxTxQueueSize = m_txQueue.max_size();
254
255 Ptr<UniformRandomVariable> uniformVar = CreateObject<UniformRandomVariable>();
256 uniformVar->SetAttribute("Min", DoubleValue(0.0));
257 uniformVar->SetAttribute("Max", DoubleValue(255.0));
258 m_macDsn = SequenceNumber8(uniformVar->GetValue());
259 m_macBsn = SequenceNumber8(uniformVar->GetValue());
260 m_macBeaconPayload = nullptr;
262 m_shortAddress = Mac16Address("FF:FF"); // FF:FF = The address is not assigned.
263}
264
266{
267}
268
269void
271{
273 {
274 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
275 }
276 else
277 {
278 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
279 }
280
282}
283
284void
286{
287 if (m_csmaCa)
288 {
289 m_csmaCa->Dispose();
290 m_csmaCa = nullptr;
291 }
292 m_txPkt = nullptr;
293
294 for (uint32_t i = 0; i < m_txQueue.size(); i++)
295 {
296 m_txQueue[i]->txQPkt = nullptr;
297 }
298 m_txQueue.clear();
299
300 for (uint32_t i = 0; i < m_indTxQueue.size(); i++)
301 {
302 m_indTxQueue[i]->txQPkt = nullptr;
303 }
304 m_indTxQueue.clear();
305
306 m_phy = nullptr;
307 m_mcpsDataConfirmCallback = MakeNullCallback<void, McpsDataConfirmParams>();
308 m_mcpsDataIndicationCallback = MakeNullCallback<void, McpsDataIndicationParams, Ptr<Packet>>();
309 m_mlmeStartConfirmCallback = MakeNullCallback<void, MlmeStartConfirmParams>();
311 MakeNullCallback<void, MlmeBeaconNotifyIndicationParams>();
312 m_mlmeSyncLossIndicationCallback = MakeNullCallback<void, MlmeSyncLossIndicationParams>();
313 m_mlmePollConfirmCallback = MakeNullCallback<void, MlmePollConfirmParams>();
314 m_mlmeScanConfirmCallback = MakeNullCallback<void, MlmeScanConfirmParams>();
315 m_mlmeAssociateConfirmCallback = MakeNullCallback<void, MlmeAssociateConfirmParams>();
316 m_mlmeAssociateIndicationCallback = MakeNullCallback<void, MlmeAssociateIndicationParams>();
317 m_mlmeCommStatusIndicationCallback = MakeNullCallback<void, MlmeCommStatusIndicationParams>();
318 m_mlmeOrphanIndicationCallback = MakeNullCallback<void, MlmeOrphanIndicationParams>();
319
320 m_panDescriptorList.clear();
321 m_energyDetectList.clear();
322 m_unscannedChannels.clear();
323
328
330}
331
332bool
334{
335 return m_macRxOnWhenIdle;
336}
337
338void
340{
341 NS_LOG_FUNCTION(this << rxOnWhenIdle);
342 m_macRxOnWhenIdle = rxOnWhenIdle;
343
344 if (m_macState == MAC_IDLE)
345 {
347 {
348 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
349 }
350 else
351 {
352 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
353 }
354 }
355}
356
357void
359{
360 NS_LOG_FUNCTION(this << address);
361 m_shortAddress = address;
362}
363
364void
366{
367 NS_LOG_FUNCTION(this << address);
368 m_macExtendedAddress = address;
369}
370
373{
374 NS_LOG_FUNCTION(this);
375 return m_shortAddress;
376}
377
380{
381 NS_LOG_FUNCTION(this);
383}
384
385void
387{
388 NS_LOG_FUNCTION(this << p);
389
390 McpsDataConfirmParams confirmParams;
391 confirmParams.m_msduHandle = params.m_msduHandle;
392
393 // TODO: We need a drop trace for the case that the packet is too large or the request
394 // parameters are maleformed.
395 // The current tx drop trace is not suitable, because packets dropped using this trace
396 // carry the mac header and footer, while packets being dropped here do not have them.
397
399 m_macDsn++;
400
402 {
403 // Note, this is just testing maximum theoretical frame size per the spec
404 // The frame could still be too large once headers are put on
405 // in which case the phy will reject it instead
406 NS_LOG_ERROR(this << " packet too big: " << p->GetSize());
407 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
409 {
410 m_mcpsDataConfirmCallback(confirmParams);
411 }
412 return;
413 }
414
415 if ((params.m_srcAddrMode == NO_PANID_ADDR) && (params.m_dstAddrMode == NO_PANID_ADDR))
416 {
417 NS_LOG_ERROR(this << " Can not send packet with no Address field");
418 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
420 {
421 m_mcpsDataConfirmCallback(confirmParams);
422 }
423 return;
424 }
425 switch (params.m_srcAddrMode)
426 {
427 case NO_PANID_ADDR:
428 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
429 macHdr.SetNoPanIdComp();
430 break;
432 NS_ABORT_MSG("Can not set source address type to ADDR_MODE_RESERVED. Aborting.");
433 break;
434 case SHORT_ADDR:
435 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
437 break;
438 case EXT_ADDR:
439 macHdr.SetSrcAddrMode(params.m_srcAddrMode);
441 break;
442 default:
443 NS_LOG_ERROR(this << " Can not send packet with incorrect Source Address mode = "
444 << params.m_srcAddrMode);
445 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
447 {
448 m_mcpsDataConfirmCallback(confirmParams);
449 }
450 return;
451 }
452 switch (params.m_dstAddrMode)
453 {
454 case NO_PANID_ADDR:
455 macHdr.SetDstAddrMode(params.m_dstAddrMode);
456 macHdr.SetNoPanIdComp();
457 break;
459 NS_ABORT_MSG("Can not set destination address type to ADDR_MODE_RESERVED. Aborting.");
460 break;
461 case SHORT_ADDR:
462 macHdr.SetDstAddrMode(params.m_dstAddrMode);
463 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstAddr);
464 break;
465 case EXT_ADDR:
466 macHdr.SetDstAddrMode(params.m_dstAddrMode);
467 macHdr.SetDstAddrFields(params.m_dstPanId, params.m_dstExtAddr);
468 break;
469 default:
470 NS_LOG_ERROR(this << " Can not send packet with incorrect Destination Address mode = "
471 << params.m_dstAddrMode);
472 confirmParams.m_status = MacStatus::INVALID_ADDRESS;
474 {
475 m_mcpsDataConfirmCallback(confirmParams);
476 }
477 return;
478 }
479
480 // IEEE 802.15.4-2006 (7.5.6.1)
481 // Src & Dst PANs are identical, PAN compression is ON
482 // only the dst PAN is serialized making the MAC header 2 bytes smaller
483 if ((params.m_dstAddrMode != NO_PANID_ADDR && params.m_srcAddrMode != NO_PANID_ADDR) &&
484 (macHdr.GetDstPanId() == macHdr.GetSrcPanId()))
485 {
486 macHdr.SetPanIdComp();
487 }
488
489 macHdr.SetSecDisable();
490 // extract the first 3 bits in TxOptions
491 int b0 = params.m_txOptions & TX_OPTION_ACK;
492 int b1 = params.m_txOptions & TX_OPTION_GTS;
493 int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
494
495 if (b0 == TX_OPTION_ACK)
496 {
497 // Set AckReq bit only if the destination is not the broadcast address.
498 if (macHdr.GetDstAddrMode() == SHORT_ADDR)
499 {
500 // short address and ACK requested.
501 Mac16Address shortAddr = macHdr.GetShortDstAddr();
502 if (shortAddr.IsBroadcast() || shortAddr.IsMulticast())
503 {
504 NS_LOG_LOGIC("LrWpanMac::McpsDataRequest: requested an ACK on broadcast or "
505 "multicast destination ("
506 << shortAddr << ") - forcefully removing it.");
507 macHdr.SetNoAckReq();
508 params.m_txOptions &= ~uint8_t(TX_OPTION_ACK);
509 }
510 else
511 {
512 macHdr.SetAckReq();
513 }
514 }
515 else
516 {
517 // other address (not short) and ACK requested
518 macHdr.SetAckReq();
519 }
520 }
521 else
522 {
523 macHdr.SetNoAckReq();
524 }
525
526 if (b1 == TX_OPTION_GTS)
527 {
528 // TODO:GTS Transmission
529 }
530 else if (b2 == TX_OPTION_INDIRECT)
531 {
532 // Indirect Tx
533 // A COORDINATOR will save the packet in the pending queue and await for data
534 // requests from its associated devices. The devices are aware of pending data,
535 // from the pending bit information extracted from the received beacon.
536 // A DEVICE must be tracking beacons (MLME-SYNC.request is running) before attempting
537 // request data from the coordinator.
538
539 // Indirect Transmission can only be done by PAN coordinator or coordinators.
541 p->AddHeader(macHdr);
542
543 LrWpanMacTrailer macTrailer;
544 // Calculate FCS if the global attribute ChecksumEnabled is set.
546 {
547 macTrailer.EnableFcs(true);
548 macTrailer.SetFcs(p);
549 }
550 p->AddTrailer(macTrailer);
551
552 NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
553 // Note: The current Pending transaction list should work for indirect transmissions.
554 // However, this is not tested yet. For now, we block the use of indirect transmissions.
555 // TODO: Save packet in the Pending Transaction list.
556 // EnqueueInd (p);
557 }
558 else
559 {
560 // Direct Tx
561 // From this point the packet will be pushed to a Tx queue and immediately
562 // use a slotted (beacon-enabled) or unslotted (nonbeacon-enabled) version of CSMA/CA
563 // before sending the packet, depending on whether it has previously
564 // received a valid beacon or not.
565
566 p->AddHeader(macHdr);
567
568 LrWpanMacTrailer macTrailer;
569 // Calculate FCS if the global attribute ChecksumEnabled is set.
571 {
572 macTrailer.EnableFcs(true);
573 macTrailer.SetFcs(p);
574 }
575 p->AddTrailer(macTrailer);
576
577 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
578 txQElement->txQMsduHandle = params.m_msduHandle;
579 txQElement->txQPkt = p;
580 EnqueueTxQElement(txQElement);
581 CheckQueue();
582 }
583}
584
585void
587{
588 NS_LOG_FUNCTION(this);
590
591 MlmeStartConfirmParams confirmParams;
592
593 if (GetShortAddress() == Mac16Address("ff:ff"))
594 {
595 NS_LOG_ERROR(this << " Invalid MAC short address");
598 {
599 m_mlmeStartConfirmCallback(confirmParams);
600 }
601 return;
602 }
603
604 if ((params.m_bcnOrd > 15) || (params.m_sfrmOrd > params.m_bcnOrd))
605 {
608 {
609 m_mlmeStartConfirmCallback(confirmParams);
610 }
611 NS_LOG_ERROR(this << "Incorrect superframe order or beacon order.");
612 return;
613 }
614
615 // Mark primitive as pending and save the start params while the new page and channel is set.
617 m_startParams = params;
618
619 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
620 pibAttr->phyCurrentPage = m_startParams.m_logChPage;
621 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
622}
623
624void
626{
627 NS_LOG_FUNCTION(this);
628
629 MlmeScanConfirmParams confirmParams;
630 confirmParams.m_scanType = params.m_scanType;
631 confirmParams.m_chPage = params.m_chPage;
632
634 {
636 {
638 m_mlmeScanConfirmCallback(confirmParams);
639 }
640 NS_LOG_ERROR(this << " A channel scan is already in progress");
641 return;
642 }
643
644 if (params.m_scanDuration > 14 || params.m_scanType > MLMESCAN_ORPHAN)
645 {
647 {
649 m_mlmeScanConfirmCallback(confirmParams);
650 }
651 NS_LOG_ERROR(this << "Invalid scan duration or unsupported scan type");
652 return;
653 }
654 // Temporary store macPanId and set macPanId to 0xFFFF to accept all beacons.
656 m_macPanId = 0xFFFF;
657
658 m_panDescriptorList.clear();
659 m_energyDetectList.clear();
660 m_unscannedChannels.clear();
661
662 // TODO: stop beacon transmission
663
664 // Cancel any ongoing CSMA/CA operations and set to unslotted mode for scan
665 m_csmaCa->Cancel();
671 m_csmaCa->SetUnSlottedCsmaCa();
672
674
675 // Mark primitive as pending and save the scan params while the new page and/or channel is set.
676 m_scanParams = params;
678
679 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
680 pibAttr->phyCurrentPage = params.m_chPage;
681 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
682}
683
684void
686{
687 NS_LOG_FUNCTION(this);
688
689 // Association is typically preceded by beacon reception and a MLME-SCAN.request, therefore,
690 // the values of the Associate.request params usually come from the information
691 // obtained from those operations.
693 m_associateParams = params;
694 bool invalidRequest = false;
695
696 if (params.m_coordPanId == 0xffff)
697 {
698 invalidRequest = true;
699 }
700
701 if (!invalidRequest && params.m_coordAddrMode == SHORT_ADDR)
702 {
703 if (params.m_coordShortAddr == Mac16Address("ff:ff") ||
704 params.m_coordShortAddr == Mac16Address("ff:fe"))
705 {
706 invalidRequest = true;
707 }
708 }
709 else if (!invalidRequest && params.m_coordAddrMode == EXT_ADDR)
710 {
711 if (params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ff") ||
712 params.m_coordExtAddr == Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed"))
713 {
714 invalidRequest = true;
715 }
716 }
717
718 if (invalidRequest)
719 {
722 NS_LOG_ERROR(this << " Invalid PAN id in Association request");
724 {
725 MlmeAssociateConfirmParams confirmParams;
726 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
728 m_mlmeAssociateConfirmCallback(confirmParams);
729 }
730 }
731 else
732 {
733 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
734 pibAttr->phyCurrentPage = params.m_chPage;
735 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentPage, pibAttr);
736 }
737}
738
739void
741{
742 // the primitive is no longer pending (channel & page are set)
744 // As described in IEEE 802.15.4-2011 (Section 5.1.3.1)
747 {
749 }
750 else
751 {
754 }
755
757}
758
759void
761{
762 // Associate Short Address (m_assocShortAddr)
763 // FF:FF = Association Request failed
764 // FF:FE = The association request is accepted, but the device should use its extended address
765 // Other = The assigned short address by the coordinator
766
767 NS_LOG_FUNCTION(this);
768
770 m_macDsn++;
771 LrWpanMacTrailer macTrailer;
772 Ptr<Packet> commandPacket = Create<Packet>();
773
774 // Mac header Assoc. Response Comm. See 802.15.4-2011 (Section 5.3.2.1)
777 macHdr.SetPanIdComp();
778 macHdr.SetDstAddrFields(m_macPanId, params.m_extDevAddr);
779 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
780
782 macPayload.SetShortAddr(params.m_assocShortAddr);
783 macPayload.SetAssociationStatus(static_cast<uint8_t>(params.m_status));
784
785 macHdr.SetSecDisable();
786 macHdr.SetAckReq();
787
788 commandPacket->AddHeader(macPayload);
789 commandPacket->AddHeader(macHdr);
790
791 // Calculate FCS if the global attribute ChecksumEnabled is set.
793 {
794 macTrailer.EnableFcs(true);
795 macTrailer.SetFcs(commandPacket);
796 }
797
798 commandPacket->AddTrailer(macTrailer);
799
800 // Save packet in the Pending Transaction list.
801 EnqueueInd(commandPacket);
802}
803
804void
806{
807 NS_LOG_FUNCTION(this);
808 // Mac header Coordinator realigment Command
809 // See 802.15.4-2011 (Section 6.2.7.2)
811 m_macDsn++;
812 LrWpanMacTrailer macTrailer;
813 Ptr<Packet> commandPacket = Create<Packet>();
814 macHdr.SetPanIdComp();
816 macHdr.SetDstAddrFields(0xffff, params.m_orphanAddr);
817
820 macHdr.SetSrcAddrFields(m_macPanId, Mac16Address("FF:FF"));
821
822 macHdr.SetFrameVer(0x01);
823 macHdr.SetSecDisable();
824 macHdr.SetAckReq();
825
827 macPayload.SetPanId(m_macPanId);
829 macPayload.SetChannel(m_phy->GetCurrentChannelNum());
830 macPayload.SetPage(m_phy->GetCurrentPage());
831
832 if (params.m_assocMember)
833 {
834 // The orphan device was associated with the coordinator
835
836 // Either FF:FE for extended address mode
837 // or the short address assigned by the coord.
838 macPayload.SetShortAddr(params.m_shortAddr);
839 }
840 else
841 {
842 // The orphan device was NOT associated with the coordinator
843 macPayload.SetShortAddr(Mac16Address("FF:FF"));
844 }
845
846 commandPacket->AddHeader(macPayload);
847 commandPacket->AddHeader(macHdr);
848
849 // Calculate FCS if the global attribute ChecksumEnabled is set.
851 {
852 macTrailer.EnableFcs(true);
853 macTrailer.SetFcs(commandPacket);
854 }
855
856 commandPacket->AddTrailer(macTrailer);
857
858 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
859 txQElement->txQPkt = commandPacket;
860 EnqueueTxQElement(txQElement);
861 CheckQueue();
862}
863
864void
866{
867 NS_LOG_FUNCTION(this);
868 NS_ASSERT(params.m_logCh <= 26 && m_macPanId != 0xffff);
869
870 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
871 // change phy current logical channel
872 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
873 pibAttr->phyCurrentChannel = params.m_logCh;
874 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
875
876 // Enable Phy receiver
877 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
878
879 uint64_t searchSymbols;
880 Time searchBeaconTime;
881
883 {
885 }
886
887 if (params.m_trackBcn)
888 {
890 // search for a beacon for a time = incomingSuperframe symbols + 960 symbols
891 searchSymbols =
893 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
894 m_beaconTrackingOn = true;
896 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
897 }
898 else
899 {
900 m_beaconTrackingOn = false;
901 }
902}
903
904void
906{
907 NS_LOG_FUNCTION(this);
908
910 m_macBsn++;
911
913
914 Ptr<Packet> beaconPacket = Create<Packet>();
915 // TODO: complete poll request (part of indirect transmissions)
916 NS_FATAL_ERROR(this << " Poll request currently not supported");
917}
918
919void
921{
922 MlmeSetConfirmParams confirmParams;
923 confirmParams.m_status = MacStatus::SUCCESS;
924
925 switch (id)
926 {
927 case macBeaconPayload:
928 if (attribute->macBeaconPayload->GetSize() > lrwpan::aMaxBeaconPayloadLength)
929 {
931 }
932 else
933 {
934 m_macBeaconPayload = attribute->macBeaconPayload;
935 m_macBeaconPayloadLength = attribute->macBeaconPayload->GetSize();
936 }
937 break;
940 break;
941 case macShortAddress:
942 m_shortAddress = attribute->macShortAddress;
943 break;
945 confirmParams.m_status = MacStatus::READ_ONLY;
946 break;
947 case macPanId:
949 break;
950 default:
951 // TODO: Add support for setting other attributes
953 break;
954 }
955
957 {
958 confirmParams.id = id;
959 m_mlmeSetConfirmCallback(confirmParams);
960 }
961}
962
963void
965{
967 Ptr<MacPibAttributes> attributes = Create<MacPibAttributes>();
968
969 switch (id)
970 {
971 case macBeaconPayload:
972 attributes->macBeaconPayload = m_macBeaconPayload;
973 break;
975 attributes->macBeaconPayloadLength = m_macBeaconPayloadLength;
976 break;
977 case macShortAddress:
978 attributes->macShortAddress = m_shortAddress;
979 break;
981 attributes->macExtendedAddress = m_macExtendedAddress;
982 break;
983 case macPanId:
984 attributes->macPanId = m_macPanId;
985 break;
986 case pCurrentChannel:
987 attributes->pCurrentChannel = m_phy->GetCurrentChannelNum();
988 break;
989 case pCurrentPage:
990 attributes->pCurrentPage = m_phy->GetCurrentPage();
991 break;
992 default:
994 break;
995 }
996
998 {
999 m_mlmeGetConfirmCallback(status, id, attributes);
1000 }
1001}
1002
1003void
1005{
1006 NS_LOG_FUNCTION(this);
1008
1010 m_macBsn++;
1011 BeaconPayloadHeader macPayload;
1012 Ptr<Packet> beaconPacket;
1013 LrWpanMacTrailer macTrailer;
1014
1015 if (m_macBeaconPayload == nullptr)
1016 {
1017 beaconPacket = Create<Packet>();
1018 }
1019 else
1020 {
1021 beaconPacket = m_macBeaconPayload;
1022 }
1023
1025 macHdr.SetDstAddrFields(GetPanId(), Mac16Address("ff:ff"));
1026
1027 // see IEEE 802.15.4-2011 Section 5.1.2.4
1028 if (GetShortAddress() == Mac16Address("ff:fe"))
1029 {
1032 }
1033 else
1034 {
1037 }
1038
1039 macHdr.SetSecDisable();
1040 macHdr.SetNoAckReq();
1041
1043 macPayload.SetGtsFields(GetGtsFields());
1045
1046 beaconPacket->AddHeader(macPayload);
1047 beaconPacket->AddHeader(macHdr);
1048
1049 // Calculate FCS if the global attribute ChecksumEnabled is set.
1051 {
1052 macTrailer.EnableFcs(true);
1053 macTrailer.SetFcs(beaconPacket);
1054 }
1055
1056 beaconPacket->AddTrailer(macTrailer);
1057
1058 // Set the Beacon packet to be transmitted
1059 m_txPkt = beaconPacket;
1060
1061 if (m_csmaCa->IsSlottedCsmaCa())
1062 {
1064 NS_LOG_DEBUG("Outgoing superframe Active Portion (Beacon + CAP + CFP): "
1065 << m_superframeDuration << " symbols");
1066 }
1067
1069 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
1070}
1071
1072void
1074{
1075 NS_LOG_FUNCTION(this);
1076
1078 m_macDsn++;
1079 LrWpanMacTrailer macTrailer;
1080 Ptr<Packet> commandPacket = Create<Packet>();
1081
1082 // Beacon Request Command Mac header values See IEEE 802.15.4-2011 (Section 5.3.7)
1083 macHdr.SetNoPanIdComp();
1086
1087 // Not associated PAN, broadcast dst address
1088 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1089
1090 macHdr.SetSecDisable();
1091 macHdr.SetNoAckReq();
1092
1093 CommandPayloadHeader macPayload;
1095
1096 commandPacket->AddHeader(macPayload);
1097 commandPacket->AddHeader(macHdr);
1098
1099 // Calculate FCS if the global attribute ChecksumEnabled is set.
1101 {
1102 macTrailer.EnableFcs(true);
1103 macTrailer.SetFcs(commandPacket);
1104 }
1105
1106 commandPacket->AddTrailer(macTrailer);
1107
1108 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1109 txQElement->txQPkt = commandPacket;
1110 EnqueueTxQElement(txQElement);
1111 CheckQueue();
1112}
1113
1114void
1116{
1118 m_macDsn++;
1119 LrWpanMacTrailer macTrailer;
1120 Ptr<Packet> commandPacket = Create<Packet>();
1121
1122 // See IEEE 802.15.4-2011 (5.3.6)
1123 macHdr.SetPanIdComp();
1124
1126 macHdr.SetSrcAddrFields(0xFFFF, GetExtendedAddress());
1127
1129 macHdr.SetDstAddrFields(0xFFFF, Mac16Address("FF:FF"));
1130
1131 macHdr.SetSecDisable();
1132 macHdr.SetNoAckReq();
1133
1134 CommandPayloadHeader macPayload;
1136
1137 commandPacket->AddHeader(macPayload);
1138 commandPacket->AddHeader(macHdr);
1139
1140 // Calculate FCS if the global attribute ChecksumEnabled is set.
1142 {
1143 macTrailer.EnableFcs(true);
1144 macTrailer.SetFcs(commandPacket);
1145 }
1146
1147 commandPacket->AddTrailer(macTrailer);
1148
1149 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1150 txQElement->txQPkt = commandPacket;
1151 EnqueueTxQElement(txQElement);
1152 CheckQueue();
1153}
1154
1155void
1157{
1158 NS_LOG_FUNCTION(this);
1159
1161 m_macDsn++;
1162 LrWpanMacTrailer macTrailer;
1163 Ptr<Packet> commandPacket = Create<Packet>();
1164
1165 // Assoc. Req. Comm. Mac header values See IEEE 802.15.4-2011 (Section 5.3.1.1)
1167 macHdr.SetSrcAddrFields(0xffff, GetExtendedAddress());
1168
1170 {
1173 }
1174 else
1175 {
1178 }
1179
1180 macHdr.SetSecDisable();
1181 macHdr.SetAckReq();
1182
1185
1186 commandPacket->AddHeader(macPayload);
1187 commandPacket->AddHeader(macHdr);
1188
1189 // Calculate FCS if the global attribute ChecksumEnabled is set.
1191 {
1192 macTrailer.EnableFcs(true);
1193 macTrailer.SetFcs(commandPacket);
1194 }
1195
1196 commandPacket->AddTrailer(macTrailer);
1197
1198 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1199 txQElement->txQPkt = commandPacket;
1200 EnqueueTxQElement(txQElement);
1201 CheckQueue();
1202}
1203
1204void
1206{
1207 // See IEEE 802.15.4-2011 (Section 5.3.5)
1208 // This command can be sent for 3 different situations:
1209 // a) In response to a beacon indicating that there is data for the device.
1210 // b) Triggered by MLME-POLL.request.
1211 // c) To follow an ACK of an Association Request command and continue the associate process.
1212
1213 // TODO: Implementation of a) and b) will be done when Indirect transmissions are fully
1214 // supported.
1215 // for now, only case c) is considered.
1216
1217 NS_LOG_FUNCTION(this);
1218
1220 m_macDsn++;
1221 LrWpanMacTrailer macTrailer;
1222 Ptr<Packet> commandPacket = Create<Packet>();
1223
1224 // Mac Header values (Section 5.3.5)
1226 macHdr.SetSrcAddrFields(0xffff, m_macExtendedAddress);
1227
1228 if (m_macCoordShortAddress == Mac16Address("ff:fe"))
1229 {
1232 }
1233 else
1234 {
1237 }
1238
1239 macHdr.SetSecDisable();
1240 macHdr.SetAckReq();
1241
1243
1244 commandPacket->AddHeader(macPayload);
1245 commandPacket->AddHeader(macHdr);
1246
1247 // Calculate FCS if the global attribute ChecksumEnabled is set.
1249 {
1250 macTrailer.EnableFcs(true);
1251 macTrailer.SetFcs(commandPacket);
1252 }
1253
1254 commandPacket->AddTrailer(macTrailer);
1255
1256 // Set the Command packet to be transmitted
1257 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1258 txQElement->txQPkt = commandPacket;
1259 EnqueueTxQElement(txQElement);
1260 CheckQueue();
1261}
1262
1263void
1265{
1266 LrWpanMacHeader receivedMacHdr;
1267 rxDataReqPkt->RemoveHeader(receivedMacHdr);
1268 CommandPayloadHeader receivedMacPayload;
1269 rxDataReqPkt->RemoveHeader(receivedMacPayload);
1270
1272
1273 Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
1274 bool elementFound;
1275 elementFound = DequeueInd(receivedMacHdr.GetExtSrcAddr(), indTxQElement);
1276 if (elementFound)
1277 {
1278 Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
1279 txQElement->txQPkt = indTxQElement->txQPkt;
1280 m_txQueue.emplace_back(txQElement);
1281 }
1282 else
1283 {
1284 NS_LOG_DEBUG("Requested element not found in pending list");
1285 }
1286}
1287
1288void
1290{
1291 // Association response command was not received, return to default values.
1292 m_macPanId = 0xffff;
1294 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1295
1297 {
1298 MlmeAssociateConfirmParams confirmParams;
1299 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
1300 confirmParams.m_status = MacStatus::NO_DATA;
1301 m_mlmeAssociateConfirmCallback(confirmParams);
1302 }
1303}
1304
1305void
1307{
1308 NS_LOG_FUNCTION(this);
1309 // The primitive is no longer pending (Channel & Page have been set)
1311
1312 if (m_startParams.m_coorRealgn) // Coordinator Realignment
1313 {
1314 // TODO: Send realignment request command frame in CSMA/CA
1315 NS_LOG_ERROR(this << " Coordinator realignment request not supported");
1316 return;
1317 }
1318 else
1319 {
1321 {
1322 m_panCoor = true;
1323 }
1324
1325 m_coor = true;
1327
1328 NS_ASSERT(m_startParams.m_PanId != 0xffff);
1329
1331 if (m_macBeaconOrder == 15)
1332 {
1333 // Non-beacon enabled PAN
1334 // Cancel any ongoing events and CSMA-CA process
1336 m_fnlCapSlot = 15;
1337 m_beaconInterval = 0;
1338
1339 m_csmaCa->Cancel();
1348
1349 m_csmaCa->SetUnSlottedCsmaCa();
1350
1352 {
1353 MlmeStartConfirmParams confirmParams;
1354 confirmParams.m_status = MacStatus::SUCCESS;
1355 m_mlmeStartConfirmCallback(confirmParams);
1356 }
1357
1358 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
1359 }
1360 else
1361 {
1363 m_csmaCa->SetBatteryLifeExtension(m_startParams.m_battLifeExt);
1364
1365 m_csmaCa->SetSlottedCsmaCa();
1366
1367 // TODO: Calculate the real Final CAP slot (requires GTS implementation)
1368 // FinalCapSlot = Superframe duration slots - CFP slots.
1369 // In the current implementation the value of the final cap slot is equal to
1370 // the total number of possible slots in the superframe (15).
1371 m_fnlCapSlot = 15;
1372
1375 m_superframeDuration = (static_cast<uint32_t>(1 << m_macSuperframeOrder)) *
1377
1378 // TODO: change the beacon sending according to the startTime parameter (if not PAN
1379 // coordinator)
1380
1382 }
1383 }
1384}
1385
1386void
1388{
1389 NS_LOG_FUNCTION(this);
1390
1392
1393 bool channelFound = false;
1394
1395 for (int i = m_channelScanIndex; i <= 26; i++)
1396 {
1398 {
1399 channelFound = true;
1400 break;
1401 }
1403 }
1404
1405 if (channelFound)
1406 {
1407 // Switch to the next channel in the list and restart scan
1408 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
1409 pibAttr->phyCurrentChannel = m_channelScanIndex;
1410 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1411 }
1412 else
1413 {
1414 // All channels in the list scan completed.
1415 // Return variables to the values before the scan and return the status to the next layer.
1417 m_macPanIdScan = 0;
1418
1419 // TODO: restart beacon transmissions that were active before the beginning of the scan
1420 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1421 MlmeScanConfirmParams confirmParams;
1422 confirmParams.m_chPage = m_scanParams.m_chPage;
1423 confirmParams.m_scanType = m_scanParams.m_scanType;
1424 confirmParams.m_energyDetList = {};
1425 confirmParams.m_unscannedCh = m_unscannedChannels;
1426 confirmParams.m_resultListSize = m_panDescriptorList.size();
1427
1428 // See IEEE 802.15.4-2011, Table 31 (panDescriptorList value on macAutoRequest)
1429 // and Section 6.2.10.2
1430 switch (confirmParams.m_scanType)
1431 {
1432 case MLMESCAN_PASSIVE:
1433 if (m_macAutoRequest)
1434 {
1435 confirmParams.m_panDescList = m_panDescriptorList;
1436 }
1437 confirmParams.m_status = MacStatus::SUCCESS;
1438 break;
1439 case MLMESCAN_ACTIVE:
1440 if (m_panDescriptorList.empty())
1441 {
1442 confirmParams.m_status = MacStatus::NO_BEACON;
1443 }
1444 else
1445 {
1446 if (m_macAutoRequest)
1447 {
1448 confirmParams.m_panDescList = m_panDescriptorList;
1449 }
1450 confirmParams.m_status = MacStatus::SUCCESS;
1451 }
1452 break;
1453 case MLMESCAN_ORPHAN:
1454 confirmParams.m_panDescList = {};
1455 confirmParams.m_status = MacStatus::NO_BEACON;
1456 confirmParams.m_resultListSize = 0;
1457 // The device lost track of the coordinator and was unable
1458 // to locate it, disassociate from the network.
1459 m_macPanId = 0xffff;
1460 m_shortAddress = Mac16Address("FF:FF");
1462 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
1463 break;
1464 default:
1465 NS_LOG_ERROR(this << " Invalid scan type");
1466 }
1467
1470 m_scanParams = {};
1471
1473 {
1474 m_mlmeScanConfirmCallback(confirmParams);
1475 }
1476 }
1477}
1478
1479void
1481{
1482 NS_LOG_FUNCTION(this);
1483 // Add the results of channel energy scan to the detectList
1485 m_maxEnergyLevel = 0;
1486
1488
1489 bool channelFound = false;
1490 for (int i = m_channelScanIndex; i <= 26; i++)
1491 {
1493 {
1494 channelFound = true;
1495 break;
1496 }
1498 }
1499
1500 if (channelFound)
1501 {
1502 // switch to the next channel in the list and restart scan
1503 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
1504 pibAttr->phyCurrentChannel = m_channelScanIndex;
1505 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
1506 }
1507 else
1508 {
1509 // Scan on all channels on the list completed
1510 // Return to the MAC values previous to start of the first scan.
1512 m_macPanIdScan = 0;
1513
1514 // TODO: restart beacon transmissions that were active before the beginning of the scan
1515 // (i.e when a coordinator perform a scan and it was already transmitting beacons)
1516
1517 // All channels scanned, report success
1518 MlmeScanConfirmParams confirmParams;
1519 confirmParams.m_status = MacStatus::SUCCESS;
1520 confirmParams.m_chPage = m_phy->GetCurrentPage();
1521 confirmParams.m_scanType = m_scanParams.m_scanType;
1522 confirmParams.m_energyDetList = m_energyDetectList;
1523 confirmParams.m_resultListSize = m_energyDetectList.size();
1524
1527 m_scanParams = {};
1528
1530 {
1531 m_mlmeScanConfirmCallback(confirmParams);
1532 }
1533 }
1534}
1535
1536void
1538{
1539 uint32_t activeSlot;
1540 uint64_t capDuration;
1541 Time endCapTime;
1542 uint64_t symbolRate;
1543
1544 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1545
1546 if (superframeType == OUTGOING)
1547 {
1549 activeSlot = m_superframeDuration / 16;
1550 capDuration = activeSlot * (m_fnlCapSlot + 1);
1551 endCapTime = Seconds((double)capDuration / symbolRate);
1552 // Obtain the end of the CAP by adjust the time it took to send the beacon
1553 endCapTime -= (Simulator::Now() - m_macBeaconTxTime);
1554
1555 NS_LOG_DEBUG("Outgoing superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1556 << " symbols (" << endCapTime.As(Time::S)
1557 << ")");
1558 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1559
1560 m_capEvent =
1562 }
1563 else
1564 {
1566 activeSlot = m_incomingSuperframeDuration / 16;
1567 capDuration = activeSlot * (m_incomingFnlCapSlot + 1);
1568 endCapTime = Seconds((double)capDuration / symbolRate);
1569 // Obtain the end of the CAP by adjust the time it took to receive the beacon
1570 endCapTime -= (Simulator::Now() - m_macBeaconRxTime);
1571
1572 NS_LOG_DEBUG("Incoming superframe CAP duration " << (endCapTime.GetSeconds() * symbolRate)
1573 << " symbols (" << endCapTime.As(Time::S)
1574 << ")");
1575 NS_LOG_DEBUG("Active Slots duration " << activeSlot << " symbols");
1576
1577 m_capEvent =
1579 }
1580
1581 CheckQueue();
1582}
1583
1584void
1586{
1587 uint32_t activeSlot;
1588 uint64_t cfpDuration;
1589 Time endCfpTime;
1590 uint64_t symbolRate;
1591
1592 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1593
1594 if (superframeType == INCOMING)
1595 {
1596 activeSlot = m_incomingSuperframeDuration / 16;
1597 cfpDuration = activeSlot * (15 - m_incomingFnlCapSlot);
1598 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1599 if (cfpDuration > 0)
1600 {
1602 }
1603
1604 NS_LOG_DEBUG("Incoming superframe CFP duration " << cfpDuration << " symbols ("
1605 << endCfpTime.As(Time::S) << ")");
1606
1609 this,
1611 }
1612 else
1613 {
1614 activeSlot = m_superframeDuration / 16;
1615 cfpDuration = activeSlot * (15 - m_fnlCapSlot);
1616 endCfpTime = Seconds((double)cfpDuration / symbolRate);
1617
1618 if (cfpDuration > 0)
1619 {
1621 }
1622
1623 NS_LOG_DEBUG("Outgoing superframe CFP duration " << cfpDuration << " symbols ("
1624 << endCfpTime.As(Time::S) << ")");
1625
1626 m_cfpEvent = Simulator::Schedule(endCfpTime,
1628 this,
1630 }
1631 // TODO: Start transmit or receive GTS here.
1632}
1633
1634void
1636{
1637 uint64_t inactiveDuration;
1638 Time endInactiveTime;
1639 uint64_t symbolRate;
1640
1641 symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1642
1643 if (superframeType == INCOMING)
1644 {
1646 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1647
1648 if (inactiveDuration > 0)
1649 {
1651 }
1652
1653 NS_LOG_DEBUG("Incoming superframe Inactive Portion duration "
1654 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1655 m_beaconEvent = Simulator::Schedule(endInactiveTime, &LrWpanMac::AwaitBeacon, this);
1656 }
1657 else
1658 {
1659 inactiveDuration = m_beaconInterval - m_superframeDuration;
1660 endInactiveTime = Seconds((double)inactiveDuration / symbolRate);
1661
1662 if (inactiveDuration > 0)
1663 {
1665 }
1666
1667 NS_LOG_DEBUG("Outgoing superframe Inactive Portion duration "
1668 << inactiveDuration << " symbols (" << endInactiveTime.As(Time::S) << ")");
1670 }
1671}
1672
1673void
1675{
1677
1678 // TODO: If the device waits more than the expected time to receive the beacon (wait = 46
1679 // symbols for default beacon size)
1680 // it should continue with the start of the incoming CAP even if it did not receive the
1681 // beacon. At the moment, the start of the incoming CAP is only triggered if the beacon is
1682 // received. See MLME-SyncLoss for details.
1683}
1684
1685void
1687{
1688 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1689
1691 {
1692 MlmeSyncLossIndicationParams syncLossParams;
1693 // syncLossParams.m_logCh =
1694 syncLossParams.m_lossReason = MacStatus::BEACON_LOSS;
1695 syncLossParams.m_panId = m_macPanId;
1696 m_mlmeSyncLossIndicationCallback(syncLossParams);
1697
1698 m_beaconTrackingOn = false;
1699 m_numLostBeacons = 0;
1700 }
1701 else
1702 {
1704
1705 // Search for one more beacon
1706 uint64_t searchSymbols;
1707 Time searchBeaconTime;
1708 searchSymbols =
1710 searchBeaconTime = Seconds((double)searchSymbols / symbolRate);
1712 Simulator::Schedule(searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this);
1713 }
1714}
1715
1716void
1718{
1719 NS_LOG_FUNCTION(this);
1720 // Pull a packet from the queue and start sending if we are not already sending.
1721 if (m_macState == MAC_IDLE && !m_txQueue.empty() && !m_setMacState.IsRunning())
1722 {
1723 if (m_csmaCa->IsUnSlottedCsmaCa() || (m_outSuperframeStatus == CAP && m_coor) ||
1725 {
1726 // check MAC is not in a IFS
1727 if (!m_ifsEvent.IsRunning())
1728 {
1729 Ptr<TxQueueElement> txQElement = m_txQueue.front();
1730 m_txPkt = txQElement->txQPkt;
1731
1734 }
1735 }
1736 }
1737}
1738
1739uint16_t
1741{
1742 SuperframeField sfrmSpec;
1743
1746 sfrmSpec.SetFinalCapSlot(m_fnlCapSlot);
1747
1748 if (m_csmaCa->GetBatteryLifeExtension())
1749 {
1750 sfrmSpec.SetBattLifeExt(true);
1751 }
1752
1753 if (m_panCoor)
1754 {
1755 sfrmSpec.SetPanCoor(true);
1756 }
1757
1758 // used to associate devices via Beacons
1760 {
1761 sfrmSpec.SetAssocPermit(true);
1762 }
1763
1764 return sfrmSpec.GetSuperframe();
1765}
1766
1769{
1770 GtsFields gtsFields;
1771
1772 // TODO: Logic to populate the GTS Fields from local information here
1773
1774 return gtsFields;
1775}
1776
1779{
1780 PendingAddrFields pndAddrFields;
1781
1782 // TODO: Logic to populate the Pending Address Fields from local information here
1783 return pndAddrFields;
1784}
1785
1786void
1788{
1789 m_csmaCa = csmaCa;
1790}
1791
1792void
1794{
1795 m_phy = phy;
1796}
1797
1800{
1801 return m_phy;
1802}
1803
1804void
1806{
1808 NS_LOG_FUNCTION(this << psduLength << p << (uint16_t)lqi);
1809
1810 bool acceptFrame;
1811
1812 // from sec 7.5.6.2 Reception and rejection, Std802.15.4-2006
1813 // level 1 filtering, test FCS field and reject if frame fails
1814 // level 2 filtering if promiscuous mode pass frame to higher layer otherwise perform level 3
1815 // filtering level 3 filtering accept frame if Frame type and version is not reserved, and if
1816 // there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
1817 // shortDstAddr then shortDstAddr =shortMacAddr or broadcastAddr, and if beacon frame then
1818 // srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
1819 // srcPanId=m_macPanId
1820
1821 Ptr<Packet> originalPkt = p->Copy(); // because we will strip headers
1822 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
1823 m_promiscSnifferTrace(originalPkt);
1824
1825 m_macPromiscRxTrace(originalPkt);
1826 // XXX no rejection tracing (to macRxDropTrace) being performed below
1827
1828 LrWpanMacTrailer receivedMacTrailer;
1829 p->RemoveTrailer(receivedMacTrailer);
1831 {
1832 receivedMacTrailer.EnableFcs(true);
1833 }
1834
1835 // level 1 filtering
1836 if (!receivedMacTrailer.CheckFcs(p))
1837 {
1838 m_macRxDropTrace(originalPkt);
1839 }
1840 else
1841 {
1842 LrWpanMacHeader receivedMacHdr;
1843 p->RemoveHeader(receivedMacHdr);
1844
1846 params.m_dsn = receivedMacHdr.GetSeqNum();
1847 params.m_mpduLinkQuality = lqi;
1848 params.m_srcPanId = receivedMacHdr.GetSrcPanId();
1849 params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
1850 switch (params.m_srcAddrMode)
1851 {
1852 case SHORT_ADDR:
1853 params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
1854 break;
1855 case EXT_ADDR:
1856 params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
1857 break;
1858 default:
1859 break;
1860 }
1861 params.m_dstPanId = receivedMacHdr.GetDstPanId();
1862 params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
1863 switch (params.m_dstAddrMode)
1864 {
1865 case SHORT_ADDR:
1866 params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
1867 break;
1868 case EXT_ADDR:
1869 params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
1870 break;
1871 default:
1872 break;
1873 }
1874
1876 {
1877 // level 2 filtering
1878 if (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
1879 {
1880 NS_LOG_DEBUG("Packet from " << params.m_srcAddr);
1881 NS_LOG_DEBUG("Packet to " << params.m_dstAddr);
1882 }
1883 else if (receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
1884 {
1885 NS_LOG_DEBUG("Packet from " << params.m_srcExtAddr);
1886 NS_LOG_DEBUG("Packet to " << params.m_dstExtAddr);
1887 }
1888
1889 // TODO: Fix here, this should trigger different Indication Callbacks
1890 // depending the type of frame received (data,command, beacon)
1892 {
1893 NS_LOG_DEBUG("promiscuous mode, forwarding up");
1895 }
1896 else
1897 {
1898 NS_LOG_ERROR(this << " Data Indication Callback not initialized");
1899 }
1900 }
1901 else
1902 {
1903 // level 3 frame filtering
1904 acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
1905
1906 if (acceptFrame)
1907 {
1908 acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
1909 }
1910
1911 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
1912 {
1913 // Accept frame if one of the following is true:
1914
1915 // 1) Have the same macPanId
1916 // 2) Is Message to all PANs
1917 // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
1918 acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
1919 receivedMacHdr.GetDstPanId() == 0xffff) ||
1920 (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
1921 (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
1922 }
1923
1924 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
1925 {
1926 if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
1927 {
1928 // unicast, for me
1929 acceptFrame = true;
1930 }
1931 else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
1932 receivedMacHdr.GetShortDstAddr().IsMulticast())
1933 {
1934 // Broadcast or multicast.
1935 // Discard broadcast/multicast with the ACK bit set.
1936 acceptFrame = !receivedMacHdr.IsAckReq();
1937 }
1938 else
1939 {
1940 acceptFrame = false;
1941 }
1942 }
1943
1944 if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
1945 {
1946 acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_macExtendedAddress);
1947 }
1948
1949 if (acceptFrame && m_scanEvent.IsRunning())
1950 {
1951 if (!receivedMacHdr.IsBeacon())
1952 {
1953 acceptFrame = false;
1954 }
1955 }
1956 else if (acceptFrame && m_scanOrphanEvent.IsRunning())
1957 {
1958 if (!receivedMacHdr.IsCommand())
1959 {
1960 acceptFrame = false;
1961 }
1962 }
1963 else if (m_scanEnergyEvent.IsRunning())
1964 {
1965 // Reject any frames if energy scan is running
1966 acceptFrame = false;
1967 }
1968
1969 // Check device is panCoor with association permit when receiving Association Request
1970 // Commands.
1971 // TODO:: Simple coordinators should also be able to receive it (currently only Pan
1972 // Coordinators are checked)
1973 if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
1974 {
1975 CommandPayloadHeader receivedMacPayload;
1976 p->PeekHeader(receivedMacPayload);
1977
1978 if (receivedMacPayload.GetCommandFrameType() ==
1981 {
1982 acceptFrame = false;
1983 }
1984
1985 // Although ACKs do not use CSMA to to be transmitted, we need to make sure
1986 // that the transmitted ACK will not collide with the transmission of a beacon
1987 // when beacon-enabled mode is running in the coordinator.
1988 if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsRunning()))
1989 {
1990 Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
1991 uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
1992 ceil(6 * m_phy->GetPhySymbolsPerOctet());
1993 Time ackTime = Seconds((double)ackSymbols / symbolRate);
1994
1995 if (ackTime >= timeLeftInCap)
1996 {
1997 NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
1998 "before the end of CAP ");
1999 acceptFrame = false;
2000 }
2001 }
2002 }
2003
2004 if (acceptFrame)
2005 {
2006 m_macRxTrace(originalPkt);
2007 // \todo: What should we do if we receive a frame while waiting for an ACK?
2008 // Especially if this frame has the ACK request bit set, should we reply with
2009 // an ACK, possibly missing the pending ACK?
2010
2011 // If the received frame is a frame with the ACK request bit set, we immediately
2012 // send back an ACK. If we are currently waiting for a pending ACK, we assume the
2013 // ACK was lost and trigger a retransmission after sending the ACK.
2014 if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) &&
2015 receivedMacHdr.IsAckReq() &&
2016 !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
2017 (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
2018 receivedMacHdr.GetShortDstAddr().IsMulticast())))
2019 {
2020 // If this is a data or mac command frame, which is not a broadcast or
2021 // multicast, with ack req set, generate and send an ack frame. If there is a
2022 // CSMA medium access in progress we cancel the medium access for sending the
2023 // ACK frame. A new transmission attempt will be started after the ACK was send.
2025 {
2028 }
2029 else if (m_macState == MAC_CSMA)
2030 {
2031 // \todo: If we receive a packet while doing CSMA/CA, should we drop the
2032 // packet because of channel busy,
2033 // or should we restart CSMA/CA for the packet after sending the ACK?
2034 // Currently we simply restart CSMA/CA after sending the ACK.
2035 NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
2036 "current CSMA-CA");
2037 m_csmaCa->Cancel();
2038 }
2039 // Cancel any pending MAC state change, ACKs have higher priority.
2042
2043 // save received packet and LQI to process the appropriate indication/response
2044 // after sending ACK (PD-DATA.confirm)
2045 m_rxPkt = originalPkt->Copy();
2046 m_lastRxFrameLqi = lqi;
2047
2048 // LOG Commands with ACK required.
2049 CommandPayloadHeader receivedMacPayload;
2050 p->PeekHeader(receivedMacPayload);
2051 switch (receivedMacPayload.GetCommandFrameType())
2052 {
2054 NS_LOG_DEBUG("Data Request Command Received; processing ACK");
2055 break;
2057 NS_LOG_DEBUG("Association Request Command Received; processing ACK");
2058 break;
2060 m_assocResCmdWaitTimeout.Cancel(); // cancel event to a lost assoc resp cmd.
2061 NS_LOG_DEBUG("Association Response Command Received; processing ACK");
2062 break;
2063 default:
2064 break;
2065 }
2066
2068 this,
2069 receivedMacHdr.GetSeqNum());
2070 }
2071
2072 if (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2073 {
2074 NS_LOG_DEBUG("Packet from " << params.m_srcAddr);
2075 NS_LOG_DEBUG("Packet to " << params.m_dstAddr);
2076 }
2077 else if (receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
2078 {
2079 NS_LOG_DEBUG("Packet from " << params.m_srcExtAddr);
2080 NS_LOG_DEBUG("Packet to " << params.m_dstExtAddr);
2081 }
2082
2083 if (receivedMacHdr.IsBeacon())
2084 {
2085 // The received beacon size in symbols
2086 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
2087 // 17 bytes)
2088 m_rxBeaconSymbols = m_phy->GetPhySHRDuration() +
2089 1 * m_phy->GetPhySymbolsPerOctet() +
2090 (originalPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
2091
2092 // The start of Rx beacon time and start of the Incoming superframe Active
2093 // Period
2095 Simulator::Now() - Seconds(double(m_rxBeaconSymbols) / symbolRate);
2096
2097 NS_LOG_DEBUG("Beacon Received; forwarding up (m_macBeaconRxTime: "
2098 << m_macBeaconRxTime.As(Time::S) << ")");
2099
2100 BeaconPayloadHeader receivedMacPayload;
2101 p->RemoveHeader(receivedMacPayload);
2102
2103 // Fill the PAN descriptor
2104 PanDescriptor panDescriptor;
2105
2106 if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR)
2107 {
2108 panDescriptor.m_coorAddrMode = SHORT_ADDR;
2109 panDescriptor.m_coorShortAddr = receivedMacHdr.GetShortSrcAddr();
2110 }
2111 else
2112 {
2113 panDescriptor.m_coorAddrMode = EXT_ADDR;
2114 panDescriptor.m_coorExtAddr = receivedMacHdr.GetExtSrcAddr();
2115 }
2116
2117 panDescriptor.m_coorPanId = receivedMacHdr.GetSrcPanId();
2118 panDescriptor.m_gtsPermit = receivedMacPayload.GetGtsFields().GetGtsPermit();
2119 panDescriptor.m_linkQuality = lqi;
2120 panDescriptor.m_logChPage = m_phy->GetCurrentPage();
2121 panDescriptor.m_logCh = m_phy->GetCurrentChannelNum();
2122 panDescriptor.m_superframeSpec = receivedMacPayload.GetSuperframeSpecField();
2123 panDescriptor.m_timeStamp = m_macBeaconRxTime;
2124
2125 // Process beacon when device belongs to a PAN (associated device)
2126 if (!m_scanEvent.IsRunning() && m_macPanId == receivedMacHdr.GetDstPanId())
2127 {
2128 // We need to make sure to cancel any possible ongoing unslotted CSMA/CA
2129 // operations when receiving a beacon (e.g. Those taking place at the
2130 // beginning of an Association).
2131 m_csmaCa->Cancel();
2132
2133 SuperframeField incomingSuperframe(
2134 receivedMacPayload.GetSuperframeSpecField());
2135
2136 m_incomingBeaconOrder = incomingSuperframe.GetBeaconOrder();
2137 m_incomingSuperframeOrder = incomingSuperframe.GetFrameOrder();
2138 m_incomingFnlCapSlot = incomingSuperframe.GetFinalCapSlot();
2139
2140 if (m_incomingBeaconOrder < 15)
2141 {
2142 // Start Beacon-enabled mode
2143 m_csmaCa->SetSlottedCsmaCa();
2145 (static_cast<uint32_t>(1 << m_incomingBeaconOrder)) *
2149 (static_cast<uint32_t>(1 << m_incomingSuperframeOrder));
2150
2151 if (incomingSuperframe.IsBattLifeExt())
2152 {
2153 m_csmaCa->SetBatteryLifeExtension(true);
2154 }
2155 else
2156 {
2157 m_csmaCa->SetBatteryLifeExtension(false);
2158 }
2159
2160 // TODO: get Incoming frame GTS Fields here
2161
2162 // Begin CAP on the current device using info from
2163 // the Incoming superframe
2164 NS_LOG_DEBUG("Incoming superframe Active Portion "
2165 << "(Beacon + CAP + CFP): " << m_incomingSuperframeDuration
2166 << " symbols");
2167
2169 this,
2171 }
2172 else
2173 {
2174 // Start non-beacon enabled mode
2175 m_csmaCa->SetUnSlottedCsmaCa();
2176 }
2177
2180 }
2181 else if (!m_scanEvent.IsRunning() && m_macPanId == 0xFFFF)
2182 {
2183 NS_LOG_DEBUG(this << " Device not associated, cannot process beacon");
2184 }
2185
2186 if (m_macAutoRequest)
2187 {
2188 if (p->GetSize() > 0)
2189 {
2191 {
2192 // The beacon contains payload, send the beacon notification.
2194 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2195 beaconParams.m_panDescriptor = panDescriptor;
2196 beaconParams.m_sduLength = p->GetSize();
2197 beaconParams.m_sdu = p;
2199 }
2200 }
2201
2202 if (m_scanEvent.IsRunning())
2203 {
2204 // Channel scanning is taking place, save only unique PAN descriptors
2205 bool descriptorExists = false;
2206
2207 for (const auto& descriptor : m_panDescriptorList)
2208 {
2209 if (descriptor.m_coorAddrMode == SHORT_ADDR)
2210 {
2211 // Found a coordinator in PAN descriptor list with the same
2212 // registered short address
2213 descriptorExists =
2214 (descriptor.m_coorShortAddr ==
2215 panDescriptor.m_coorShortAddr &&
2216 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
2217 }
2218 else
2219 {
2220 // Found a coordinator in PAN descriptor list with the same
2221 // registered extended address
2222 descriptorExists =
2223 (descriptor.m_coorExtAddr == panDescriptor.m_coorExtAddr &&
2224 descriptor.m_coorPanId == panDescriptor.m_coorPanId);
2225 }
2226
2227 if (descriptorExists)
2228 {
2229 break;
2230 }
2231 }
2232
2233 if (!descriptorExists)
2234 {
2235 m_panDescriptorList.emplace_back(panDescriptor);
2236 }
2237 return;
2238 }
2239 else if (m_trackingEvent.IsRunning())
2240 {
2241 // check if MLME-SYNC.request was previously issued and running
2242 // Sync. is necessary to handle pending messages (indirect
2243 // transmissions)
2245 m_numLostBeacons = 0;
2246
2248 {
2249 // if tracking option is on keep tracking the next beacon
2250 uint64_t searchSymbols;
2251 Time searchBeaconTime;
2252
2253 searchSymbols =
2254 (static_cast<uint64_t>(1 << m_incomingBeaconOrder)) +
2256 searchBeaconTime =
2257 Seconds(static_cast<double>(searchSymbols / symbolRate));
2259 Simulator::Schedule(searchBeaconTime,
2261 this);
2262 }
2263
2264 PendingAddrFields pndAddrFields;
2265 pndAddrFields = receivedMacPayload.GetPndAddrFields();
2266
2267 // TODO: Ignore pending data, and do not send data command request if
2268 // the address is in the GTS list.
2269 // If the address is not in the GTS list, then check if the
2270 // address is in the short address pending list or in the extended
2271 // address pending list and send a data command request.
2272 }
2273 }
2274 else
2275 {
2276 // m_macAutoRequest is FALSE
2277 // Data command request are not send, only the beacon notification.
2278 // see IEEE 802.15.4-2011 Section 6.2.4.1
2280 {
2282 beaconParams.m_bsn = receivedMacHdr.GetSeqNum();
2283 beaconParams.m_panDescriptor = panDescriptor;
2284 beaconParams.m_sduLength = p->GetSize();
2285 beaconParams.m_sdu = p;
2287 }
2288 }
2289 }
2290 else if (receivedMacHdr.IsCommand())
2291 {
2292 // Handle the reception of frame commands that do not require ACK
2293 // (i.e. Beacon Request, Orphan notification, Coordinator Realigment)
2294 CommandPayloadHeader receivedMacPayload;
2295 p->PeekHeader(receivedMacPayload);
2296
2297 switch (receivedMacPayload.GetCommandFrameType())
2298 {
2300 if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
2301 {
2302 SendOneBeacon();
2303 }
2304 else
2305 {
2306 m_macRxDropTrace(originalPkt);
2307 }
2308 break;
2311 {
2312 if (m_coor)
2313 {
2314 MlmeOrphanIndicationParams orphanParams;
2315 orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
2316 m_mlmeOrphanIndicationCallback(orphanParams);
2317 }
2318 }
2319 break;
2322 {
2323 // Coordinator located, no need to keep scanning other channels
2325
2326 m_macPanIdScan = 0;
2329
2330 // Update the device information with the received information
2331 // from the Coordinator Realigment command.
2332 m_macPanId = receivedMacPayload.GetPanId();
2333 m_shortAddress = receivedMacPayload.GetShortAddr();
2334 m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
2335 m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
2336
2338 {
2339 MlmeScanConfirmParams confirmParams;
2340 confirmParams.m_scanType = m_scanParams.m_scanType;
2341 confirmParams.m_chPage = m_scanParams.m_chPage;
2342 confirmParams.m_status = MacStatus::SUCCESS;
2343 m_mlmeScanConfirmCallback(confirmParams);
2344 }
2345 m_scanParams = {};
2346 }
2347 // TODO: handle Coordinator realignment when not
2348 // used during an orphan scan.
2349 break;
2350 default:
2351 m_macRxDropTrace(originalPkt);
2352 break;
2353 }
2354 }
2355 else if (receivedMacHdr.IsData() && !m_mcpsDataIndicationCallback.IsNull())
2356 {
2357 // If it is a data frame, push it up the stack.
2358 NS_LOG_DEBUG("Data Packet is for me; forwarding up");
2360 }
2361 else if (receivedMacHdr.IsAcknowledgment() && m_txPkt &&
2363 {
2364 LrWpanMacHeader peekedMacHdr;
2365 m_txPkt->PeekHeader(peekedMacHdr);
2366 // If it is an ACK with the expected sequence number, finish the transmission
2367 if (receivedMacHdr.GetSeqNum() == peekedMacHdr.GetSeqNum())
2368 {
2371
2372 // TODO: check if the IFS is the correct size after ACK.
2373 Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
2374
2375 // We received an ACK to a command
2376 if (peekedMacHdr.IsCommand())
2377 {
2378 // check the original sent command frame which belongs to this received
2379 // ACK
2380 Ptr<Packet> pkt = m_txPkt->Copy();
2381 LrWpanMacHeader macHdr;
2382 CommandPayloadHeader cmdPayload;
2383 pkt->RemoveHeader(macHdr);
2384 pkt->RemoveHeader(cmdPayload);
2385
2386 switch (cmdPayload.GetCommandFrameType())
2387 {
2389 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2390 Time waitTime = Seconds(static_cast<double>(m_macResponseWaitTime) /
2391 symbolRate);
2392 if (!m_beaconTrackingOn)
2393 {
2395 Simulator::Schedule(waitTime,
2397 this);
2398 }
2399 else
2400 {
2401 // TODO: The data must be extracted by the coordinator within
2402 // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
2403 // with status NO_DATA, and this should trigger the cancellation
2404 // of the beacon tracking (MLME-SYNC.request trackBeacon
2405 // =FALSE)
2406 }
2407 break;
2408 }
2409
2411 // MLME-comm-status.Indication generated as a result of an
2412 // association response command, therefore src and dst address use
2413 // extended mode (see 5.3.2.1)
2415 {
2416 MlmeCommStatusIndicationParams commStatusParams;
2417 commStatusParams.m_panId = m_macPanId;
2418 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2419 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2420 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2421 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2422 commStatusParams.m_status = MacStatus::SUCCESS;
2423 m_mlmeCommStatusIndicationCallback(commStatusParams);
2424 }
2425 // Remove element from Pending Transaction List
2427 break;
2428 }
2429
2431 // Schedule an event in case the Association Response Command never
2432 // reached this device during an association process.
2433 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2434 Time waitTime = Seconds(
2435 static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
2437 Simulator::Schedule(waitTime,
2439 this);
2440
2442 {
2443 MlmePollConfirmParams pollConfirmParams;
2444 pollConfirmParams.m_status = MacStatus::SUCCESS;
2445 m_mlmePollConfirmCallback(pollConfirmParams);
2446 }
2447 break;
2448 }
2449
2451 // ACK of coordinator realigment commands is not specified in the
2452 // standard, in here, we assume they are required as in other
2453 // commands.
2455 {
2456 MlmeCommStatusIndicationParams commStatusParams;
2457 commStatusParams.m_panId = m_macPanId;
2458 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2459 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2460 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2461 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2462 commStatusParams.m_status = MacStatus::SUCCESS;
2463 m_mlmeCommStatusIndicationCallback(commStatusParams);
2464 }
2465 }
2466
2467 default: {
2468 // TODO: add response to other request commands (e.g. Orphan)
2469 break;
2470 }
2471 }
2472 }
2473 else
2474 {
2476 {
2477 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2478 McpsDataConfirmParams confirmParams;
2479 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2480 confirmParams.m_status = MacStatus::SUCCESS;
2481 m_mcpsDataConfirmCallback(confirmParams);
2482 }
2483 }
2484
2485 // Ack was successfully received, wait for the Interframe Space (IFS) and
2486 // then proceed
2491 m_ifsEvent = Simulator::Schedule(ifsWaitTime,
2493 this,
2494 ifsWaitTime);
2495 }
2496 else
2497 {
2498 // If it is an ACK with an unexpected sequence number, mark the current
2499 // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
2501 if (!PrepareRetransmission())
2502 {
2505 this,
2506 MAC_IDLE);
2507 }
2508 else
2509 {
2512 this,
2513 MAC_CSMA);
2514 }
2515 }
2516 }
2517 }
2518 else
2519 {
2520 m_macRxDropTrace(originalPkt);
2521 }
2522 }
2523 }
2524}
2525
2526void
2528{
2529 NS_LOG_FUNCTION(this << static_cast<uint32_t>(seqno));
2530
2532
2533 // Generate a corresponding ACK Frame.
2535 LrWpanMacTrailer macTrailer;
2536 Ptr<Packet> ackPacket = Create<Packet>(0);
2537 ackPacket->AddHeader(macHdr);
2538 // Calculate FCS if the global attribute ChecksumEnabled is set.
2540 {
2541 macTrailer.EnableFcs(true);
2542 macTrailer.SetFcs(ackPacket);
2543 }
2544 ackPacket->AddTrailer(macTrailer);
2545
2546 // Enqueue the ACK packet for further processing
2547 // when the transmitter is activated.
2548 m_txPkt = ackPacket;
2549
2550 // Switch transceiver to TX mode. Proceed sending the Ack on confirm.
2552 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
2553}
2554
2555void
2557{
2558 if (m_txQueue.size() < m_maxTxQueueSize)
2559 {
2560 m_txQueue.emplace_back(txQElement);
2561 m_macTxEnqueueTrace(txQElement->txQPkt);
2562 }
2563 else
2564 {
2566 {
2567 McpsDataConfirmParams confirmParams;
2568 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2570 m_mcpsDataConfirmCallback(confirmParams);
2571 }
2572 NS_LOG_DEBUG("TX Queue with size " << m_txQueue.size() << " is full, dropping packet");
2573 m_macTxDropTrace(txQElement->txQPkt);
2574 }
2575}
2576
2577void
2579{
2580 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2581 Ptr<const Packet> p = txQElement->txQPkt;
2582 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2583
2584 Ptr<Packet> pkt = p->Copy();
2585 LrWpanMacHeader hdr;
2586 pkt->RemoveHeader(hdr);
2587 if (!hdr.GetShortDstAddr().IsBroadcast() && !hdr.GetShortDstAddr().IsMulticast())
2588 {
2590 }
2591
2592 txQElement->txQPkt = nullptr;
2593 txQElement = nullptr;
2594 m_txQueue.pop_front();
2595 m_txPkt = nullptr;
2596 m_retransmission = 0;
2597 m_numCsmacaRetry = 0;
2599}
2600
2601void
2603{
2604 NS_LOG_FUNCTION(this);
2605
2606 // TODO: If we are a PAN coordinator and this was an indirect transmission,
2607 // we will not initiate a retransmission. Instead we wait for the data
2608 // being extracted after a new data request command.
2609 if (!PrepareRetransmission())
2610 {
2612 }
2613 else
2614 {
2616 }
2617}
2618
2619void
2621{
2622 auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false);
2623 Time lifsTime = Seconds((double)m_macLIFSPeriod / symbolRate);
2624 Time sifsTime = Seconds((double)m_macSIFSPeriod / symbolRate);
2625
2626 if (ifsTime == lifsTime)
2627 {
2628 NS_LOG_DEBUG("LIFS of " << m_macLIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2629 << ") completed ");
2630 }
2631 else if (ifsTime == sifsTime)
2632 {
2633 NS_LOG_DEBUG("SIFS of " << m_macSIFSPeriod << " symbols (" << ifsTime.As(Time::S)
2634 << ") completed ");
2635 }
2636 else
2637 {
2638 NS_LOG_DEBUG("Unknown IFS size (" << ifsTime.As(Time::S) << ") completed ");
2639 }
2640
2641 m_macIfsEndTrace(ifsTime);
2642 CheckQueue();
2643}
2644
2645bool
2647{
2648 NS_LOG_FUNCTION(this);
2649
2650 // Max retransmissions reached without receiving ACK,
2651 // send the proper indication/confirmation
2652 // according to the frame type and call drop trace.
2654 {
2655 LrWpanMacHeader peekedMacHdr;
2656 m_txPkt->PeekHeader(peekedMacHdr);
2657
2658 if (peekedMacHdr.IsCommand())
2659 {
2661
2662 Ptr<Packet> pkt = m_txPkt->Copy();
2663 LrWpanMacHeader macHdr;
2664 CommandPayloadHeader cmdPayload;
2665 pkt->RemoveHeader(macHdr);
2666 pkt->RemoveHeader(cmdPayload);
2667
2668 switch (cmdPayload.GetCommandFrameType())
2669 {
2671 m_macPanId = 0xffff;
2673 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2676 m_csmaCa->SetUnSlottedCsmaCa();
2679
2681 {
2682 MlmeAssociateConfirmParams confirmParams;
2683 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
2684 confirmParams.m_status = MacStatus::NO_ACK;
2685 m_mlmeAssociateConfirmCallback(confirmParams);
2686 }
2687 break;
2688 }
2690 // IEEE 802.15.4-2006 (Section 7.1.3.3.3 and 7.1.8.2.3)
2692 {
2693 MlmeCommStatusIndicationParams commStatusParams;
2694 commStatusParams.m_panId = m_macPanId;
2695 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2696 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
2697 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2698 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
2699 commStatusParams.m_status = MacStatus::NO_ACK;
2700 m_mlmeCommStatusIndicationCallback(commStatusParams);
2701 }
2703 break;
2704 }
2706 // IEEE 802.15.4-2006 (Section 7.1.16.1.3)
2707 m_macPanId = 0xffff;
2709 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
2712 m_csmaCa->SetUnSlottedCsmaCa();
2715
2717 {
2718 MlmePollConfirmParams pollConfirmParams;
2719 pollConfirmParams.m_status = MacStatus::NO_ACK;
2720 m_mlmePollConfirmCallback(pollConfirmParams);
2721 }
2722 break;
2723 }
2724 default: {
2725 // TODO: Specify other indications according to other commands
2726 break;
2727 }
2728 }
2729 }
2730 else
2731 {
2732 // Maximum number of retransmissions has been reached.
2733 // remove the copy of the DATA packet that was just sent
2734 Ptr<TxQueueElement> txQElement = m_txQueue.front();
2735 m_macTxDropTrace(txQElement->txQPkt);
2737 {
2738 McpsDataConfirmParams confirmParams;
2739 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
2740 confirmParams.m_status = MacStatus::NO_ACK;
2741 m_mcpsDataConfirmCallback(confirmParams);
2742 }
2743 }
2744
2746 return false;
2747 }
2748 else
2749 {
2751 m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
2752 // Start next CCA process for this packet.
2753 return true;
2754 }
2755}
2756
2757void
2759{
2760 Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
2761 LrWpanMacHeader peekedMacHdr;
2762 p->PeekHeader(peekedMacHdr);
2763
2764 PurgeInd();
2765
2766 NS_ASSERT(peekedMacHdr.GetDstAddrMode() == SHORT_ADDR ||
2767 peekedMacHdr.GetDstAddrMode() == EXT_ADDR);
2768
2769 if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2770 {
2771 indTxQElement->dstShortAddress = peekedMacHdr.GetShortDstAddr();
2772 }
2773 else
2774 {
2775 indTxQElement->dstExtAddress = peekedMacHdr.GetExtDstAddr();
2776 }
2777
2778 indTxQElement->seqNum = peekedMacHdr.GetSeqNum();
2779
2780 // See IEEE 802.15.4-2006, Table 86
2781 uint32_t unit = 0; // The persistence time in symbols
2782 if (m_macBeaconOrder == 15)
2783 {
2784 // Non-beacon enabled mode
2786 }
2787 else
2788 {
2789 // Beacon-enabled mode
2790 unit = ((static_cast<uint32_t>(1) << m_macBeaconOrder) * lrwpan::aBaseSuperframeDuration) *
2792 }
2793
2794 if (m_indTxQueue.size() < m_maxIndTxQueueSize)
2795 {
2796 double symbolRate = m_phy->GetDataOrSymbolRate(false);
2797 Time expireTime = Seconds(unit / symbolRate);
2798 expireTime += Simulator::Now();
2799 indTxQElement->expireTime = expireTime;
2800 indTxQElement->txQPkt = p;
2801 m_indTxQueue.emplace_back(indTxQElement);
2803 }
2804 else
2805 {
2807 {
2808 LrWpanMacHeader peekedMacHdr;
2809 indTxQElement->txQPkt->PeekHeader(peekedMacHdr);
2810 MlmeCommStatusIndicationParams commStatusParams;
2811 commStatusParams.m_panId = m_macPanId;
2812 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2813 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2814 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2815 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2816 commStatusParams.m_status = MacStatus::TRANSACTION_OVERFLOW;
2817 m_mlmeCommStatusIndicationCallback(commStatusParams);
2818 }
2820 }
2821}
2822
2823bool
2825{
2826 PurgeInd();
2827
2828 for (auto iter = m_indTxQueue.begin(); iter != m_indTxQueue.end(); iter++)
2829 {
2830 if ((*iter)->dstExtAddress == dst)
2831 {
2832 *entry = **iter;
2833 m_macIndTxDequeueTrace((*iter)->txQPkt->Copy());
2834 m_indTxQueue.erase(iter);
2835 return true;
2836 }
2837 }
2838 return false;
2839}
2840
2841void
2843{
2844 for (uint32_t i = 0; i < m_indTxQueue.size();)
2845 {
2846 if (Simulator::Now() > m_indTxQueue[i]->expireTime)
2847 {
2848 // Transaction expired, remove and send proper confirmation/indication to a higher layer
2849 LrWpanMacHeader peekedMacHdr;
2850 m_indTxQueue[i]->txQPkt->PeekHeader(peekedMacHdr);
2851
2852 if (peekedMacHdr.IsCommand())
2853 {
2854 // IEEE 802.15.4-2006 (Section 7.1.3.3.3)
2856 {
2857 MlmeCommStatusIndicationParams commStatusParams;
2858 commStatusParams.m_panId = m_macPanId;
2859 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
2860 commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
2861 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
2862 commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
2863 commStatusParams.m_status = MacStatus::TRANSACTION_EXPIRED;
2864 m_mlmeCommStatusIndicationCallback(commStatusParams);
2865 }
2866 }
2867 else if (peekedMacHdr.IsData())
2868 {
2869 // IEEE 802.15.4-2006 (Section 7.1.1.1.3)
2871 {
2872 McpsDataConfirmParams confParams;
2874 m_mcpsDataConfirmCallback(confParams);
2875 }
2876 }
2877 m_macIndTxDropTrace(m_indTxQueue[i]->txQPkt->Copy());
2878 m_indTxQueue.erase(m_indTxQueue.begin() + i);
2879 }
2880 else
2881 {
2882 i++;
2883 }
2884 }
2885}
2886
2887void
2888LrWpanMac::PrintPendingTxQueue(std::ostream& os) const
2889{
2890 LrWpanMacHeader peekedMacHdr;
2891
2892 os << "Pending Transaction List [" << GetShortAddress() << " | " << GetExtendedAddress()
2893 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
2894 << " Destination |"
2895 << " Sequence Number |"
2896 << " Frame type |"
2897 << " Expire time\n";
2898
2899 for (auto transaction : m_indTxQueue)
2900 {
2901 transaction->txQPkt->PeekHeader(peekedMacHdr);
2902 os << transaction->dstExtAddress << " "
2903 << static_cast<uint32_t>(transaction->seqNum) << " ";
2904
2905 if (peekedMacHdr.IsCommand())
2906 {
2907 os << " Command Frame ";
2908 }
2909 else if (peekedMacHdr.IsData())
2910 {
2911 os << " Data Frame ";
2912 }
2913 else
2914 {
2915 os << " Unknown Frame ";
2916 }
2917
2918 os << transaction->expireTime.As(Time::S) << "\n";
2919 }
2920}
2921
2922void
2923LrWpanMac::PrintTxQueue(std::ostream& os) const
2924{
2925 LrWpanMacHeader peekedMacHdr;
2926
2927 os << "\nTx Queue [" << GetShortAddress() << " | " << GetExtendedAddress()
2928 << "] | CurrentTime: " << Simulator::Now().As(Time::S) << "\n"
2929 << " Destination |"
2930 << " Sequence Number |"
2931 << " Dst PAN id |"
2932 << " Frame type |\n";
2933
2934 for (auto transaction : m_txQueue)
2935 {
2936 transaction->txQPkt->PeekHeader(peekedMacHdr);
2937
2938 os << "[" << peekedMacHdr.GetShortDstAddr() << "]"
2939 << ", [" << peekedMacHdr.GetExtDstAddr() << "] "
2940 << static_cast<uint32_t>(peekedMacHdr.GetSeqNum()) << " "
2941 << peekedMacHdr.GetDstPanId() << " ";
2942
2943 if (peekedMacHdr.IsCommand())
2944 {
2945 os << " Command Frame ";
2946 }
2947 else if (peekedMacHdr.IsData())
2948 {
2949 os << " Data Frame ";
2950 }
2951 else
2952 {
2953 os << " Unknown Frame ";
2954 }
2955
2956 os << "\n";
2957 }
2958 os << "\n";
2959}
2960
2961void
2963{
2964 LrWpanMacHeader peekedMacHdr;
2965 p->PeekHeader(peekedMacHdr);
2966
2967 for (auto it = m_indTxQueue.begin(); it != m_indTxQueue.end(); it++)
2968 {
2969 if (peekedMacHdr.GetDstAddrMode() == EXT_ADDR)
2970 {
2971 if (((*it)->dstExtAddress == peekedMacHdr.GetExtDstAddr()) &&
2972 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
2973 {
2975 m_indTxQueue.erase(it);
2976 break;
2977 }
2978 }
2979 else if (peekedMacHdr.GetDstAddrMode() == SHORT_ADDR)
2980 {
2981 if (((*it)->dstShortAddress == peekedMacHdr.GetShortDstAddr()) &&
2982 ((*it)->seqNum == peekedMacHdr.GetSeqNum()))
2983 {
2985 m_indTxQueue.erase(it);
2986 break;
2987 }
2988 }
2989 }
2990
2991 p = nullptr;
2992}
2993
2994void
2996{
2998 NS_LOG_FUNCTION(this << status << m_txQueue.size());
2999
3000 LrWpanMacHeader macHdr;
3001 Time ifsWaitTime;
3002 double symbolRate;
3003
3004 symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
3005
3006 m_txPkt->PeekHeader(macHdr);
3007
3008 if (status == IEEE_802_15_4_PHY_SUCCESS)
3009 {
3010 if (!macHdr.IsAcknowledgment())
3011 {
3012 if (macHdr.IsBeacon())
3013 {
3014 // Start CAP only if we are in beacon mode (i.e. if slotted csma-ca is running)
3015 if (m_csmaCa->IsSlottedCsmaCa())
3016 {
3017 // The Tx Beacon in symbols
3018 // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default
3019 // 17 bytes)
3020 uint64_t beaconSymbols = m_phy->GetPhySHRDuration() +
3021 1 * m_phy->GetPhySymbolsPerOctet() +
3022 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet());
3023
3024 // The beacon Tx time and start of the Outgoing superframe Active Period
3026 Simulator::Now() - Seconds(static_cast<double>(beaconSymbols) / symbolRate);
3027
3029 this,
3031 NS_LOG_DEBUG("Beacon Sent (m_macBeaconTxTime: " << m_macBeaconTxTime.As(Time::S)
3032 << ")");
3033
3035 {
3036 MlmeStartConfirmParams mlmeConfirmParams;
3037 mlmeConfirmParams.m_status = MacStatus::SUCCESS;
3038 m_mlmeStartConfirmCallback(mlmeConfirmParams);
3039 }
3040 }
3041
3042 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3043 m_txPkt = nullptr;
3044 }
3045 else if (macHdr.IsAckReq()) // We have sent a regular data packet, check if we have to
3046 // wait for an ACK.
3047 {
3048 // we sent a regular data frame or command frame (e.g. AssocReq command) that
3049 // require ACK wait for the ack or the next retransmission timeout start
3050 // retransmission timer
3051 Time waitTime = Seconds(static_cast<double>(GetMacAckWaitDuration()) / symbolRate);
3057 return;
3058 }
3059 else if (macHdr.IsCommand())
3060 {
3061 // We handle commands that do not require ACK
3062 // (e.g. Coordinator realigment command in an orphan response)
3063 // Other command with ACK required are handle by the previous if statement.
3064
3065 // Check the transmitted packet command type and issue the appropriate indication.
3066 Ptr<Packet> txOriginalPkt = m_txPkt->Copy();
3067 LrWpanMacHeader txMacHdr;
3068 txOriginalPkt->RemoveHeader(txMacHdr);
3069 CommandPayloadHeader txMacPayload;
3070 txOriginalPkt->RemoveHeader(txMacPayload);
3071
3073 {
3075 {
3076 MlmeCommStatusIndicationParams commStatusParams;
3077 commStatusParams.m_panId = m_macPanId;
3078
3079 commStatusParams.m_srcAddrMode = macHdr.GetSrcAddrMode();
3080 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3081 commStatusParams.m_srcShortAddr = macHdr.GetShortSrcAddr();
3082
3083 commStatusParams.m_dstAddrMode = macHdr.GetDstAddrMode();
3084 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3085 commStatusParams.m_dstShortAddr = macHdr.GetShortDstAddr();
3086
3087 commStatusParams.m_status = MacStatus::SUCCESS;
3088 m_mlmeCommStatusIndicationCallback(commStatusParams);
3089 }
3090 }
3091
3092 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3094 }
3095 else
3096 {
3098 // remove the copy of the packet that was just sent
3100 {
3101 McpsDataConfirmParams confirmParams;
3102 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3103 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3104 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3105 confirmParams.m_status = MacStatus::SUCCESS;
3106 m_mcpsDataConfirmCallback(confirmParams);
3107 }
3108 ifsWaitTime = Seconds(static_cast<double>(GetIfsSize()) / symbolRate);
3110 }
3111 }
3112 else
3113 {
3114 // The packet sent was a successful ACK
3115
3116 // Check the received frame before the transmission of the ACK,
3117 // and send the appropriate Indication or Confirmation
3118 Ptr<Packet> recvOriginalPkt = m_rxPkt->Copy();
3119 LrWpanMacHeader receivedMacHdr;
3120 recvOriginalPkt->RemoveHeader(receivedMacHdr);
3121
3122 if (receivedMacHdr.IsCommand())
3123 {
3124 CommandPayloadHeader receivedMacPayload;
3125 recvOriginalPkt->RemoveHeader(receivedMacPayload);
3126
3127 if (receivedMacPayload.GetCommandFrameType() ==
3129 {
3131 {
3132 // NOTE: The LQI parameter is not part of the standard but found
3133 // in some implementations as is required for higher layers (See Zboss
3134 // implementation).
3135 MlmeAssociateIndicationParams associateParams;
3136 associateParams.capabilityInfo = receivedMacPayload.GetCapabilityField();
3137 associateParams.m_extDevAddr = receivedMacHdr.GetExtSrcAddr();
3138 associateParams.lqi = m_lastRxFrameLqi;
3139 m_mlmeAssociateIndicationCallback(associateParams);
3140 }
3141
3142 // Clear the packet buffer for the packet request received.
3143 m_rxPkt = nullptr;
3144 }
3145 else if (receivedMacPayload.GetCommandFrameType() ==
3147 {
3148 MlmeAssociateConfirmParams confirmParams;
3149
3150 switch (static_cast<MacStatus>(receivedMacPayload.GetAssociationStatus()))
3151 {
3152 case MacStatus::SUCCESS:
3153 // The assigned short address by the coordinator
3154 SetShortAddress(receivedMacPayload.GetShortAddr());
3155 m_macPanId = receivedMacHdr.GetSrcPanId();
3156
3157 confirmParams.m_status = MacStatus::SUCCESS;
3158 confirmParams.m_assocShortAddr = GetShortAddress();
3159 break;
3161 confirmParams.m_status = MacStatus::FULL_CAPACITY;
3162 m_macPanId = 0xffff;
3164 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3167 m_csmaCa->SetUnSlottedCsmaCa();
3170 break;
3172 default:
3173 confirmParams.m_status = MacStatus::ACCESS_DENIED;
3174 m_macPanId = 0xffff;
3176 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3179 m_csmaCa->SetUnSlottedCsmaCa();
3182 break;
3183 }
3184
3186 {
3187 m_mlmeAssociateConfirmCallback(confirmParams);
3188 }
3189 }
3190 else if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::DATA_REQ)
3191 {
3192 // We enqueue the the Assoc Response command frame in the Tx queue
3193 // and the packet is transmitted as soon as the PHY is free and the IFS have
3194 // taken place.
3196 }
3197 }
3198
3199 // Clear the packet buffer for the ACK packet sent.
3200 m_txPkt = nullptr;
3201 }
3202 }
3203 else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
3204 {
3205 if (!macHdr.IsAcknowledgment())
3206 {
3207 NS_ASSERT_MSG(!m_txQueue.empty(), "TxQsize = 0");
3208 Ptr<TxQueueElement> txQElement = m_txQueue.front();
3209 m_macTxDropTrace(txQElement->txQPkt);
3211 {
3212 McpsDataConfirmParams confirmParams;
3213 confirmParams.m_msduHandle = txQElement->txQMsduHandle;
3214 confirmParams.m_status = MacStatus::FRAME_TOO_LONG;
3215 m_mcpsDataConfirmCallback(confirmParams);
3216 }
3218 }
3219 else
3220 {
3221 NS_LOG_ERROR("Unable to send ACK");
3222 }
3223 }
3224 else
3225 {
3226 // Something went really wrong. The PHY is not in the correct state for
3227 // data transmission.
3228 NS_FATAL_ERROR("Transmission attempt failed with PHY status " << status);
3229 }
3230
3231 if (!ifsWaitTime.IsZero())
3232 {
3233 m_ifsEvent =
3234 Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
3235 }
3236
3239}
3240
3241void
3243{
3244 NS_LOG_FUNCTION(this << status);
3245 // Direct this call through the csmaCa object
3246 m_csmaCa->PlmeCcaConfirm(status);
3247}
3248
3249void
3250LrWpanMac::PlmeEdConfirm(PhyEnumeration status, uint8_t energyLevel)
3251{
3252 NS_LOG_FUNCTION(this << status << energyLevel);
3253
3254 if (energyLevel > m_maxEnergyLevel)
3255 {
3256 m_maxEnergyLevel = energyLevel;
3257 }
3258
3260 Seconds(8.0 / m_phy->GetDataOrSymbolRate(false)))
3261 {
3262 m_phy->PlmeEdRequest();
3263 }
3264}
3265
3266void
3269 Ptr<PhyPibAttributes> attribute)
3270{
3271 NS_LOG_FUNCTION(this << status << id << attribute);
3272}
3273
3274void
3276{
3277 NS_LOG_FUNCTION(this << status);
3278
3279 if (m_macState == MAC_SENDING &&
3280 (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3281 {
3283
3284 // Start sending if we are in state SENDING and the PHY transmitter was enabled.
3288 m_phy->PdDataRequest(m_txPkt->GetSize(), m_txPkt);
3289 }
3290 else if (m_macState == MAC_CSMA &&
3291 (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
3292 {
3293 // Start the CSMA algorithm as soon as the receiver is enabled.
3294 m_csmaCa->Start();
3295 }
3296 else if (m_macState == MAC_IDLE)
3297 {
3299 status == IEEE_802_15_4_PHY_TRX_OFF);
3300
3302 {
3303 // Kick start Energy Detection Scan
3304 m_phy->PlmeEdRequest();
3305 }
3306 else if (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS)
3307 {
3308 // Check if there is not messages to transmit when going idle
3309 CheckQueue();
3310 }
3311 }
3312 else if (m_macState == MAC_ACK_PENDING)
3313 {
3315 }
3316 else
3317 {
3318 // TODO: What to do when we receive an error?
3319 // If we want to transmit a packet, but switching the transceiver on results
3320 // in an error, we have to recover somehow (and start sending again).
3321 NS_FATAL_ERROR("Error changing transceiver state");
3322 }
3323}
3324
3325void
3327{
3328 NS_LOG_FUNCTION(this << status << id);
3330 {
3332 {
3333 // get the first channel to scan from scan channel list
3334 bool channelFound = false;
3335 for (int i = m_channelScanIndex; i <= 26; i++)
3336 {
3338 {
3339 channelFound = true;
3340 break;
3341 }
3343 }
3344
3345 if (channelFound)
3346 {
3347 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
3348 pibAttr->phyCurrentChannel = m_channelScanIndex;
3349 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel,
3350 pibAttr);
3351 }
3352 }
3353 else
3354 {
3356 {
3357 MlmeScanConfirmParams confirmParams;
3358 confirmParams.m_scanType = m_scanParams.m_scanType;
3359 confirmParams.m_chPage = m_scanParams.m_chPage;
3360 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3361 m_mlmeScanConfirmCallback(confirmParams);
3362 }
3363 NS_LOG_ERROR(this << "Channel Scan: Invalid channel page");
3364 }
3365 }
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;
3413 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
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;
3429 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3430 m_mlmeScanConfirmCallback(confirmParams);
3431 }
3432 NS_LOG_ERROR("Channel " << m_channelScanIndex
3433 << " could not be set in the current page");
3434 }
3435 }
3437 {
3439 {
3440 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
3441 pibAttr->phyCurrentChannel = m_startParams.m_logCh;
3442 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3443 }
3444 else
3445 {
3447 {
3448 MlmeStartConfirmParams confirmParams;
3449 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3450 m_mlmeStartConfirmCallback(confirmParams);
3451 }
3452 NS_LOG_ERROR("Invalid page parameter in MLME-start");
3453 }
3454 }
3457 {
3459 {
3461 }
3462 else
3463 {
3465 {
3466 MlmeStartConfirmParams confirmParams;
3467 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3468 m_mlmeStartConfirmCallback(confirmParams);
3469 }
3470 NS_LOG_ERROR("Invalid channel parameter in MLME-start");
3471 }
3472 }
3474 {
3476 {
3477 Ptr<PhyPibAttributes> pibAttr = Create<PhyPibAttributes>();
3478 pibAttr->phyCurrentChannel = m_associateParams.m_chNum;
3479 m_phy->PlmeSetAttributeRequest(PhyPibAttributeIdentifier::phyCurrentChannel, pibAttr);
3480 }
3481 else
3482 {
3483 m_macPanId = 0xffff;
3485 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3488 m_csmaCa->SetUnSlottedCsmaCa();
3491
3493 {
3494 MlmeAssociateConfirmParams confirmParams;
3495 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3496 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3497 m_mlmeAssociateConfirmCallback(confirmParams);
3498 }
3499 NS_LOG_ERROR("Invalid page parameter in MLME-associate");
3500 }
3501 }
3504 {
3506 {
3508 }
3509 else
3510 {
3511 m_macPanId = 0xffff;
3513 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3516 m_csmaCa->SetUnSlottedCsmaCa();
3519
3521 {
3522 MlmeAssociateConfirmParams confirmParams;
3523 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3524 confirmParams.m_status = MacStatus::INVALID_PARAMETER;
3525 m_mlmeAssociateConfirmCallback(confirmParams);
3526 }
3527 NS_LOG_ERROR("Invalid channel parameter in MLME-associate");
3528 }
3529 }
3530}
3531
3532void
3534{
3535 NS_LOG_FUNCTION(this << "mac state = " << macState);
3536
3537 if (macState == MAC_IDLE)
3538 {
3541 {
3542 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3543 }
3544 else
3545 {
3546 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3547 }
3548 }
3549 else if (macState == MAC_ACK_PENDING)
3550 {
3552 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3553 }
3554 else if (macState == MAC_CSMA)
3555 {
3558 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3559 }
3560 else if (m_macState == MAC_CSMA && macState == CHANNEL_IDLE)
3561 {
3562 // Channel is idle, set transmitter to TX_ON
3564 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
3565 }
3566 else if (m_macState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
3567 {
3569
3570 // Cannot find a clear channel, drop the current packet
3571 // and send the proper confirm/indication according to the packet type
3572 NS_LOG_DEBUG(this << " cannot find clear channel");
3573
3575
3576 Ptr<Packet> pkt = m_txPkt->Copy();
3577 LrWpanMacHeader macHdr;
3578 pkt->RemoveHeader(macHdr);
3579
3580 if (macHdr.IsCommand())
3581 {
3582 CommandPayloadHeader cmdPayload;
3583 pkt->RemoveHeader(cmdPayload);
3584
3585 switch (cmdPayload.GetCommandFrameType())
3586 {
3588 m_macPanId = 0xffff;
3590 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3593 m_csmaCa->SetUnSlottedCsmaCa();
3596
3598 {
3599 MlmeAssociateConfirmParams confirmParams;
3600 confirmParams.m_assocShortAddr = Mac16Address("FF:FF");
3602 m_mlmeAssociateConfirmCallback(confirmParams);
3603 }
3604 break;
3605 }
3608 {
3609 MlmeCommStatusIndicationParams commStatusParams;
3610 commStatusParams.m_panId = m_macPanId;
3611 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3612 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3613 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3614 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3616 m_mlmeCommStatusIndicationCallback(commStatusParams);
3617 }
3619 break;
3620 }
3622 m_macPanId = 0xffff;
3624 m_macCoordExtendedAddress = Mac64Address("ff:ff:ff:ff:ff:ff:ff:ed");
3627 m_csmaCa->SetUnSlottedCsmaCa();
3630
3632 {
3633 MlmePollConfirmParams pollConfirmParams;
3634 pollConfirmParams.m_status = MacStatus::CHANNEL_ACCESS_FAILURE;
3635 m_mlmePollConfirmCallback(pollConfirmParams);
3636 }
3637 break;
3638 }
3641 {
3642 MlmeCommStatusIndicationParams commStatusParams;
3643 commStatusParams.m_panId = m_macPanId;
3644 commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
3645 commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
3646 commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
3647 commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
3649 m_mlmeCommStatusIndicationCallback(commStatusParams);
3650 }
3651 break;
3652 }
3655 {
3656 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3657 }
3658 // TODO: Handle orphan notification command during a
3659 // channel access failure when not is not scanning.
3660 break;
3661 }
3663 if (m_scanEvent.IsRunning())
3664 {
3665 m_unscannedChannels.emplace_back(m_phy->GetCurrentChannelNum());
3666 }
3667 // TODO: Handle beacon request command during a
3668 // channel access failure when not scanning.
3669 break;
3670 }
3671 default: {
3672 // TODO: Other commands(e.g. Disassociation notification, etc)
3673 break;
3674 }
3675 }
3677 }
3678 else if (macHdr.IsData())
3679 {
3681 {
3682 McpsDataConfirmParams confirmParams;
3683 confirmParams.m_msduHandle = m_txQueue.front()->txQMsduHandle;
3685 m_mcpsDataConfirmCallback(confirmParams);
3686 }
3687 // remove the copy of the packet that was just sent
3689 }
3690 else
3691 {
3692 // TODO:: specify behavior for other packets
3693 m_txPkt = nullptr;
3694 m_retransmission = 0;
3695 m_numCsmacaRetry = 0;
3696 }
3697
3700 {
3701 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_RX_ON);
3702 }
3703 else
3704 {
3705 m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TRX_OFF);
3706 }
3707 }
3708 else if (m_macState == MAC_CSMA && macState == MAC_CSMA_DEFERRED)
3709 {
3711 m_txPkt = nullptr;
3712 // The MAC is running on beacon mode and the current packet could not be sent in the
3713 // current CAP. The packet will be send on the next CAP after receiving the beacon.
3714 // The PHY state does not change from its current form. The PHY change (RX_ON) will be
3715 // triggered by the scheduled beacon event.
3716
3717 NS_LOG_DEBUG("****** PACKET DEFERRED to the next superframe *****");
3718 }
3719}
3720
3721void
3723{
3725}
3726
3727void
3729{
3731}
3732
3733uint16_t
3735{
3736 return m_macPanId;
3737}
3738
3741{
3743}
3744
3747{
3749}
3750
3751void
3752LrWpanMac::SetPanId(uint16_t panId)
3753{
3754 m_macPanId = panId;
3755}
3756
3757void
3759{
3760 NS_LOG_LOGIC(this << " change lrwpan mac state from " << m_macState << " to " << newState);
3761 m_macStateLogger(m_macState, newState);
3762 m_macState = newState;
3763}
3764
3765uint64_t
3767{
3768 return lrwpan::aUnitBackoffPeriod + lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
3769 ceil(6 * m_phy->GetPhySymbolsPerOctet());
3770}
3771
3772uint8_t
3774{
3775 return m_macMaxFrameRetries;
3776}
3777
3778void
3780{
3781 NS_LOG_DEBUG("Transmit Queue Size: " << m_txQueue.size());
3782}
3783
3784void
3786{
3787 m_macMaxFrameRetries = retries;
3788}
3789
3790bool
3792{
3794 LrWpanMacHeader macHdr;
3795 m_txPkt->PeekHeader(macHdr);
3796
3797 if (m_coor)
3798 {
3799 // The device is its coordinator and the packet is not to itself
3800 return false;
3801 }
3802 else if (m_macCoordShortAddress == macHdr.GetShortDstAddr() ||
3804 {
3805 return true;
3806 }
3807 else
3808 {
3809 NS_LOG_DEBUG("ERROR: Packet not for the coordinator!");
3810 return false;
3811 }
3812}
3813
3816{
3818
3820 {
3821 return m_macSIFSPeriod;
3822 }
3823 else
3824 {
3825 return m_macLIFSPeriod;
3826 }
3827}
3828
3829void
3831{
3833}
3834
3835void
3837{
3839}
3840
3841uint64_t
3843{
3845 // Sync Header (SHR) + 8 bits PHY header (PHR) + PSDU
3846 return (m_phy->GetPhySHRDuration() + 1 * m_phy->GetPhySymbolsPerOctet() +
3847 (m_txPkt->GetSize() * m_phy->GetPhySymbolsPerOctet()));
3848}
3849
3850bool
3852{
3854 LrWpanMacHeader macHdr;
3855 m_txPkt->PeekHeader(macHdr);
3856
3857 return macHdr.IsAckReq();
3858}
3859
3860} // namespace lrwpan
3861} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:571
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
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:278
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:451
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
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
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
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:932
Hold an unsigned integer type.
Definition: uinteger.h:45
Implements the header for the MAC payload beacon frame according to the IEEE 802.15....
void SetSuperframeSpecField(uint16_t sfrmField)
Set the superframe specification field to the beacon payload header.
uint16_t GetSuperframeSpecField() const
Get the superframe specification field from the beacon payload header.
GtsFields GetGtsFields() const
Get the Guaranteed Time Slots (GTS) fields from the beacon payload header.
void SetGtsFields(GtsFields gtsFields)
Set the superframe Guaranteed Time Slot (GTS) fields to the beacon payload header.
PendingAddrFields GetPndAddrFields() const
Get the pending address fields from the beacon payload header.
void SetPndAddrFields(PendingAddrFields pndAddrFields)
Set the superframe Pending Address fields to the beacon payload header.
Implements the header for the MAC payload command frame according to the IEEE 802....
MacCommand GetCommandFrameType() const
Get the command frame type ID.
Mac16Address GetShortAddr() const
Get the Short address assigned by the coordinator (Association Response and Coordinator Realigment co...
uint16_t GetPanId() const
Get the PAN identifier.
void SetPage(uint8_t page)
Set the logical channel page number.
void SetShortAddr(Mac16Address shortAddr)
Set the Short Address Assigned by the coordinator (Association Response and Coordinator Realigment Co...
uint8_t GetCapabilityField() const
Get the Capability Information Field from the command payload header.
void SetCommandFrameType(MacCommand macCmd)
Set the command frame type.
Mac16Address GetCoordShortAddr() const
Get the coordinator short address.
void SetCapabilityField(uint8_t cap)
Set the Capability Information Field to the command payload header (Association Request Command).
void SetCoordShortAddr(Mac16Address addr)
Set the coordinator short address (16 bit address).
@ ASSOCIATION_RESP
Association response (RFD true: Rx)
@ DATA_REQ
Data Request (RFD true: Tx)
@ COOR_REALIGN
Coordinator Realignment (RFD true: Rx)
@ ORPHAN_NOTIF
Orphan Notification (RFD true: Tx)
@ ASSOCIATION_REQ
Association request (RFD true: Tx)
@ BEACON_REQ
Beacon Request (RFD true: none )
void SetAssociationStatus(uint8_t status)
Set status resulting from the association attempt (Association Response Command).
uint8_t GetAssociationStatus() const
Get the status resulting from an association request (Association Response Command).
void SetPanId(uint16_t id)
Get the PAN identifier.
void SetChannel(uint8_t channel)
Set the logical channel number.
Represent the GTS information fields.
bool GetGtsPermit() const
Get the GTS Specification Permit.
Lr-wpan MAC layer abstraction.
MlmeOrphanIndicationCallback m_mlmeOrphanIndicationCallback
This callback is used to indicate the reception of a orphan notification command.
MlmeGetConfirmCallback m_mlmeGetConfirmCallback
This callback is used to report the result of an attribute read request to the upper layers.
MlmeAssociateIndicationCallback m_mlmeAssociateIndicationCallback
This callback is used to indicate the reception of an association request command.
MlmeSetConfirmCallback m_mlmeSetConfirmCallback
This callback is used to report the result of an attribute writing request to the upper layers.
MlmePollConfirmCallback m_mlmePollConfirmCallback
This callback is used to report the status after a device send data command request to the coordinato...
MlmeCommStatusIndicationCallback m_mlmeCommStatusIndicationCallback
This callback is instigated through a response primitive.
McpsDataConfirmCallback m_mcpsDataConfirmCallback
This callback is used to report data transmission request status to the upper layers.
McpsDataIndicationCallback m_mcpsDataIndicationCallback
This callback is used to notify incoming packets to the upper layers.
MlmeScanConfirmCallback m_mlmeScanConfirmCallback
This callback is used to report the result of a scan on a group of channels for the selected channel ...
MlmeAssociateConfirmCallback m_mlmeAssociateConfirmCallback
This callback is used to report the status after a device request an association with a coordinator.
MlmeSyncLossIndicationCallback m_mlmeSyncLossIndicationCallback
This callback is used to indicate the loss of synchronization with a coordinator.
MlmeBeaconNotifyIndicationCallback m_mlmeBeaconNotifyIndicationCallback
This callback is used to notify incoming beacon packets to the upper layers.
MlmeStartConfirmCallback m_mlmeStartConfirmCallback
This callback is used to report the start of a new PAN or the begin of a new superframe configuration...
Represent the Mac Header with the Frame Control and Sequence Number fields.
LrWpanMacType GetType() const
Get the header type.
Mac16Address GetShortSrcAddr() const
Get the Source Short address.
void SetDstAddrMode(uint8_t addrMode)
Set the Destination address mode.
void SetNoAckReq()
Set the Frame Control field "Ack. Request" bit to false.
void SetDstAddrFields(uint16_t panId, Mac16Address addr)
Set Destination address fields.
Mac64Address GetExtSrcAddr() const
Get the Source Extended address.
bool IsData() const
Returns true if the header is a data.
bool IsBeacon() const
Returns true if the header is a beacon.
@ LRWPAN_MAC_ACKNOWLEDGMENT
LRWPAN_MAC_ACKNOWLEDGMENT.
@ LRWPAN_MAC_RESERVED
LRWPAN_MAC_RESERVED.
@ LRWPAN_MAC_COMMAND
LRWPAN_MAC_COMMAND.
@ LRWPAN_MAC_BEACON
LRWPAN_MAC_BEACON.
void SetPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to true.
Mac16Address GetShortDstAddr() const
Get the Destination Short address.
void SetSrcAddrMode(uint8_t addrMode)
Set the Source address mode.
bool IsCommand() const
Returns true if the header is a command.
uint8_t GetSeqNum() const
Get the frame Sequence number.
void SetFrameVer(uint8_t ver)
Set the Frame version.
uint8_t GetFrameVer() const
Get the Frame Version of Frame control field.
void SetSrcAddrFields(uint16_t panId, Mac16Address addr)
Set Source address fields.
uint16_t GetSrcPanId() const
Get the Source PAN ID.
void SetNoPanIdComp()
Set the Frame Control field "PAN ID Compression" bit to false.
uint16_t GetDstPanId() const
Get the Destination PAN ID.
void SetAckReq()
Set the Frame Control field "Ack. Request" bit to true.
bool IsAckReq() const
Check if Ack.
uint8_t GetDstAddrMode() const
Get the Dest.
void SetSecDisable()
Set the Frame Control field "Security Enabled" bit to false.
Mac64Address GetExtDstAddr() const
Get the Destination Extended address.
bool IsAcknowledgment() const
Returns true if the header is an ack.
uint8_t GetSrcAddrMode() const
Get the Source Addressing Mode of Frame control field.
Class that implements the LR-WPAN MAC state machine.
Definition: lr-wpan-mac.h:164
Ptr< Packet > m_rxPkt
The command request packet received.
Definition: lr-wpan-mac.h:1160
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:999
void RemovePendTxQElement(Ptr< Packet > p)
Remove an element from the pending transaction list.
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired for packets successfully received by the device but dropped before being forwa...
Definition: lr-wpan-mac.h:1074
uint8_t m_deviceCapability
Indication of current device capability (FFD or RFD)
Definition: lr-wpan-mac.h:623
void SetExtendedAddress(Mac64Address address)
Set the extended address of this MAC.
Definition: lr-wpan-mac.cc:365
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:1015
Ptr< Packet > m_macBeaconPayload
The contents of the beacon payload.
Definition: lr-wpan-mac.h:527
Ptr< LrWpanPhy > GetPhy()
Get the underlying PHY of the MAC.
uint32_t m_superframeDuration
Indication of the superframe duration in symbols.
Definition: lr-wpan-mac.h:606
void AwaitBeacon()
Called after the end of an INCOMING superframe to start the moment a device waits for a new incoming ...
void EndStartRequest()
Called to end a MLME-START.request after changing the page and channel number.
void MlmeAssociateResponse(MlmeAssociateResponseParams params) override
IEEE 802.15.4-2011, section 6.2.2.3 MLME-ASSOCIATE.response Primitive used to initiate a response to ...
Definition: lr-wpan-mac.cc:760
bool m_macPromiscuousMode
Indicates if MAC sublayer is in receive all mode.
Definition: lr-wpan-mac.h:495
Ptr< LrWpanCsmaCa > m_csmaCa
The CSMA/CA implementation used by this MAC.
Definition: lr-wpan-mac.h:1134
void SendAck(uint8_t seqno)
Send an acknowledgment packet for the given sequence number.
uint8_t m_numCsmacaRetry
The number of CSMA/CA retries used for sending the current packet.
Definition: lr-wpan-mac.h:1249
Ptr< Packet > m_txPkt
The packet which is currently being sent by the MAC layer.
Definition: lr-wpan-mac.h:1154
MlmeStartRequestParams m_startParams
The parameters used during a MLME-START.request.
Definition: lr-wpan-mac.h:1221
void PurgeInd()
Purge expired transactions from the pending transactions list.
void SetCsmaCa(Ptr< LrWpanCsmaCa > csmaCa)
Set the CSMA/CA implementation to be used by the MAC.
EventId m_scanEvent
Scheduler event for the end of an ACTIVE or PASSIVE channel scan.
Definition: lr-wpan-mac.h:1315
void PdDataConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.1.2 Confirm the end of transmission of an MPDU to MAC.
void SendOrphanNotificationCommand()
Called to send a orphan notification command.
Mac64Address m_macExtendedAddress
The extended 64 address (IEEE EUI-64) used by this MAC.
Definition: lr-wpan-mac.h:1172
EventId m_scanEnergyEvent
Scheduler event for the end of a ED channel scan.
Definition: lr-wpan-mac.h:1325
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:508
EventId m_setMacState
Scheduler event for a deferred MAC state change.
Definition: lr-wpan-mac.h:1275
uint32_t m_macBeaconPayloadLength
The length, in octets, of the beacon payload.
Definition: lr-wpan-mac.h:533
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:1114
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:983
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:408
GtsFields GetGtsFields()
Constructs the Guaranteed Time Slots (GTS) Fields from local information.
void SetIndTxQMaxSize(uint32_t queueSize)
Set the max size of the indirect transmit queue (Pending Transaction list)
std::deque< Ptr< IndTxQueueElement > > m_indTxQueue
The indirect transmit queue used by the MAC pending messages (The pending transaction list).
Definition: lr-wpan-mac.h:1183
uint8_t m_incomingSuperframeOrder
Used by all devices that have a parent.
Definition: lr-wpan-mac.h:483
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:1056
uint32_t m_macLIFSPeriod
The minimum time forming a Long InterFrame Spacing (LIFS) period.
Definition: lr-wpan-mac.h:552
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:1065
std::vector< uint8_t > m_unscannedChannels
The list of unscanned channels during a scan operation.
Definition: lr-wpan-mac.h:1209
bool m_macRxOnWhenIdle
Indication of whether the MAC sublayer is to enable its receiver during idle periods.
Definition: lr-wpan-mac.h:546
void PrintTransmitQueueSize()
Print the number of elements in the packet transmit queue.
uint16_t m_channelScanIndex
The channel list index used to obtain the current scanned channel.
Definition: lr-wpan-mac.h:1232
void SendAssocRequestCommand()
Called to send an associate request command.
EventId m_beaconEvent
Scheduler event for generation of one beacon.
Definition: lr-wpan-mac.h:1285
void BeaconSearchTimeout()
Called if the device is unable to locate a beacon in the time set by MLME-SYNC.request.
uint32_t m_macSIFSPeriod
The minimum time forming a Short InterFrame Spacing (SIFS) period.
Definition: lr-wpan-mac.h:558
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets are being sent down to L1.
Definition: lr-wpan-mac.h:1022
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:865
SequenceNumber8 m_macDsn
Sequence number added to transmitted data or MAC command frame, 00-ff.
Definition: lr-wpan-mac.h:514
void ChangeMacState(MacState newState)
Change the current MAC state to the given new state.
Mac16Address m_macCoordShortAddress
The short address of the coordinator through which the device is associated.
Definition: lr-wpan-mac.h:417
Mac64Address GetCoordExtAddress() const
Get the coordinator extended address currently associated to this device.
void MlmeGetRequest(MacPibAttributeIdentifier id) override
IEEE 802.15.4-2006, section 7.1.6.1 MLME-GET.request Request information about a given PIB attribute.
Definition: lr-wpan-mac.cc:964
std::deque< Ptr< TxQueueElement > > m_txQueue
The transmit queue used by the MAC.
Definition: lr-wpan-mac.h:1177
uint8_t m_macSuperframeOrder
Used by a PAN coordinator or coordinator.
Definition: lr-wpan-mac.h:446
TracedValue< SuperframeStatus > m_incSuperframeStatus
The current period of the incoming superframe.
Definition: lr-wpan-mac.h:1144
void SetPanId(uint16_t panId)
Set the PAN id used by this MAC.
void MlmeStartRequest(MlmeStartRequestParams params) override
IEEE 802.15.4-2006, section 7.1.14.1 MLME-START.request Request to allow a PAN coordinator to initiat...
Definition: lr-wpan-mac.cc:586
MlmeScanRequestParams m_scanParams
The parameters used during a MLME-SCAN.request.
Definition: lr-wpan-mac.h:1215
void SetLrWpanMacState(MacState macState)
CSMA-CA algorithm calls back the MAC after executing channel assessment.
void SetShortAddress(Mac16Address address)
Set the short address of this MAC.
Definition: lr-wpan-mac.cc:358
uint8_t m_incomingBeaconOrder
The beaconOrder value of the INCOMING frame.
Definition: lr-wpan-mac.h:475
void PrintTxQueue(std::ostream &os) const
Print the Transmit Queue.
void CheckQueue()
Check the transmission queue.
uint32_t m_incomingSuperframeDuration
Indication of the superframe duration in symbols (e.g.
Definition: lr-wpan-mac.h:618
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:1007
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:1039
void SetMacMaxFrameRetries(uint8_t retries)
Set the macMaxFrameRetries attribute value.
uint16_t m_macTransactionPersistenceTime
The maximum time (in UNIT periods) that a transaction is stored by a coordinator and indicated in its...
Definition: lr-wpan-mac.h:457
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:805
void AckWaitTimeout()
Handle an ACK timeout with a packet retransmission, if there are retransmission left,...
uint32_t m_maxTxQueueSize
The maximum size of the transmit queue.
Definition: lr-wpan-mac.h:1188
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:1047
uint8_t m_retransmission
The number of already used retransmission for the currently transmitted packet.
Definition: lr-wpan-mac.h:1244
LrWpanMac()
Default constructor.
Definition: lr-wpan-mac.cc:204
EventId m_incCfpEvent
Scheduler event for the end of the incoming superframe CFP.
Definition: lr-wpan-mac.h:1305
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:1204
SequenceNumber8 m_macBsn
Sequence number added to transmitted beacon frame, 00-ff.
Definition: lr-wpan-mac.h:520
TracedCallback< MacState, MacState > m_macStateLogger
A trace source that fires when the MAC changes states.
Definition: lr-wpan-mac.h:1124
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:1094
Mac64Address GetExtendedAddress() const
Get the extended address of this MAC.
Definition: lr-wpan-mac.cc:379
void DoDispose() override
Destructor implementation.
Definition: lr-wpan-mac.cc:285
uint8_t m_fnlCapSlot
Indication of the Slot where the CAP portion of the OUTGOING Superframe ends.
Definition: lr-wpan-mac.h:468
MlmeAssociateRequestParams m_associateParams
The parameters used during a MLME-ASSOCIATE.request.
Definition: lr-wpan-mac.h:1227
uint32_t m_incomingBeaconInterval
Indication of the interval a node should receive a superframe expressed in symbols.
Definition: lr-wpan-mac.h:612
bool m_macAssociationPermit
Indication of whether a coordinator is currently allowing association.
Definition: lr-wpan-mac.h:565
static TypeId GetTypeId()
Get the type ID.
Definition: lr-wpan-mac.cc:93
uint64_t GetMacAckWaitDuration() const
Get the macAckWaitDuration attribute value.
void SetTxQMaxSize(uint32_t queueSize)
Set the max size of the transmit queue.
TracedCallback< Time > m_macIfsEndTrace
The trace source is fired at the end of any Interframe Space (IFS).
Definition: lr-wpan-mac.h:971
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:685
bool GetRxOnWhenIdle() const
Check if the receiver will be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:333
void EnqueueInd(Ptr< Packet > p)
Adds a packet to the pending transactions list (Indirect transmissions).
Time m_macBeaconTxTime
The time that the device transmitted its last beacon frame.
Definition: lr-wpan-mac.h:385
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:1199
uint8_t m_maxEnergyLevel
The maximum energy level detected during ED scan on the current channel.
Definition: lr-wpan-mac.h:579
Mac16Address GetShortAddress() const
Get the short address of this MAC.
Definition: lr-wpan-mac.cc:372
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:574
PendingAddrFields GetPendingAddrFields()
Constructs Pending Address Fields from the local information, the Pending Address Fields are part of ...
uint64_t m_rxBeaconSymbols
The total size of the received beacon in symbols.
Definition: lr-wpan-mac.h:463
Ptr< LrWpanPhy > m_phy
The PHY associated with this MAC.
Definition: lr-wpan-mac.h:1129
EventId m_cfpEvent
Scheduler event for the end of the outgoing superframe CFP.
Definition: lr-wpan-mac.h:1295
uint16_t GetPanId() const
Get the PAN id used by this MAC.
TracedCallback< Ptr< const Packet > > m_macTxOkTrace
The trace source fired when packets where successfully transmitted, that is an acknowledgment was rec...
Definition: lr-wpan-mac.h:1031
bool m_panCoor
Indication of whether the current device is the PAN coordinator.
Definition: lr-wpan-mac.h:589
void SendAssocResponseCommand(Ptr< Packet > rxDataReqPkt)
Called to send an associate response command.
Time m_macBeaconRxTime
The time that the device received its last bit of the beacon frame.
Definition: lr-wpan-mac.h:393
void SetAssociatedCoor(Mac16Address mac)
Check if the packet destination is its coordinator.
void StartCFP(SuperframeType superframeType)
Called to begin the Contention Free Period (CFP) in a beacon-enabled mode.
uint16_t m_macPanId
16 bits id of PAN on which this device is operating.
Definition: lr-wpan-mac.h:502
bool PrepareRetransmission()
Check for remaining retransmissions for the packet currently being sent.
void PrintPendingTxQueue(std::ostream &os) const
Print the Pending transaction list.
uint32_t m_ifs
The value of the necessary InterFrame Space after the transmission of a packet.
Definition: lr-wpan-mac.h:584
void MlmeSetRequest(MacPibAttributeIdentifier id, Ptr< MacPibAttributes > attribute) override
IEEE 802.15.4-2011, section 6.2.11.1 MLME-SET.request Attempts to write the given value to the indica...
Definition: lr-wpan-mac.cc:920
bool m_beaconTrackingOn
Indication of whether the current device is tracking incoming beacons.
Definition: lr-wpan-mac.h:628
void SendBeaconRequestCommand()
Called to send a beacon request command.
uint32_t m_maxIndTxQueueSize
The maximum size of the indirect transmit queue (The pending transaction list).
Definition: lr-wpan-mac.h:1193
void IfsWaitTimeout(Time ifsTime)
After a successful transmission of a frame (beacon, data) or an ack frame reception,...
EventId m_ifsEvent
Scheduler event for Interframe spacing wait time.
Definition: lr-wpan-mac.h:1280
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:625
void PdDataIndication(uint32_t psduLength, Ptr< Packet > p, uint8_t lqi)
IEEE 802.15.4-2006 section 6.2.1.3 PD-DATA.indication Indicates the transfer of an MPDU from PHY to M...
uint8_t m_macMaxFrameRetries
The maximum number of retries allowed after a transmission failure.
Definition: lr-wpan-mac.h:539
PendingPrimitiveStatus m_pendPrimitive
Indicates the pending primitive when PLME.SET operation (page or channel switch) is called from withi...
Definition: lr-wpan-mac.h:1238
EventId m_respWaitTimeout
Scheduler event for a response to a request command frame.
Definition: lr-wpan-mac.h:1265
uint16_t GetSuperframeField()
Constructs a Superframe specification field from the local information, the superframe Specification ...
bool IsCoordDest()
Check if the packet destination is its coordinator.
EventId m_ackWaitTimeout
Scheduler event for the ACK timeout of the currently transmitted data packet.
Definition: lr-wpan-mac.h:1260
void StartCAP(SuperframeType superframeType)
Called to begin the Contention Access Period (CAP) in a beacon-enabled mode.
Mac64Address m_macCoordExtendedAddress
The extended address of the coordinator through which the device is associated.
Definition: lr-wpan-mac.h:424
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:386
EventId m_incCapEvent
Scheduler event for the end of the incoming superframe CAP.
Definition: lr-wpan-mac.h:1300
Mac16Address GetCoordShortAddress() const
Get the coordinator short address currently associated to this device.
void SendDataRequestCommand()
Used to send a data request command (i.e.
bool DequeueInd(Mac64Address dst, Ptr< IndTxQueueElement > entry)
Extracts a packet from pending transactions list (Indirect transmissions).
EventId m_trackingEvent
Scheduler event to track the incoming beacons.
Definition: lr-wpan-mac.h:1310
uint64_t GetTxPacketSymbols()
Obtain the number of symbols in the packet which is currently being sent by the MAC layer.
uint32_t m_beaconInterval
Indication of the Interval used by the coordinator to transmit beacon frames expressed in symbols.
Definition: lr-wpan-mac.h:600
Mac16Address m_shortAddress
The short address (16 bit address) used by this MAC.
Definition: lr-wpan-mac.h:1167
EventId m_assocResCmdWaitTimeout
Scheduler event for the lost of a association response command frame.
Definition: lr-wpan-mac.h:1270
void PlmeGetAttributeConfirm(PhyEnumeration status, PhyPibAttributeIdentifier id, Ptr< PhyPibAttributes > attribute)
IEEE 802.15.4-2006 section 6.2.2.6 PLME-GET.confirm Get attributes per definition from Table 23 in se...
uint8_t m_macBeaconOrder
Used by a PAN coordinator or coordinator.
Definition: lr-wpan-mac.h:438
void SetPhy(Ptr< LrWpanPhy > phy)
Set the underlying PHY for the MAC.
void MlmePollRequest(MlmePollRequestParams params) override
IEEE 802.15.4-2011, section 6.2.14.2 MLME-POLL.request Prompts the device to request data from the co...
Definition: lr-wpan-mac.cc:905
void RemoveFirstTxQElement()
Remove the tip of the transmission queue, including clean up related to the last packet transmission.
TracedValue< SuperframeStatus > m_outSuperframeStatus
The current period of the outgoing superframe.
Definition: lr-wpan-mac.h:1149
void SetRxOnWhenIdle(bool rxOnWhenIdle)
Set if the receiver should be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:339
void PlmeCcaConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
void PlmeSetAttributeConfirm(PhyEnumeration status, PhyPibAttributeIdentifier id)
IEEE 802.15.4-2006 section 6.2.2.10 PLME-SET.confirm Set attributes per definition from Table 23 in s...
EventId m_scanOrphanEvent
Scheduler event for the end of an ORPHAN channel scan.
Definition: lr-wpan-mac.h:1320
void StartInactivePeriod(SuperframeType superframeType)
Start the Inactive Period in a beacon-enabled mode.
uint32_t GetIfsSize()
Get the size of the Interframe Space according to MPDU size (m_txPkt).
EventId m_capEvent
Scheduler event for the end of the outgoing superframe CAP.
Definition: lr-wpan-mac.h:1290
void PlmeSetTRXStateConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.8 PLME-SET-TRX-STATE.confirm Set PHY state.
TracedValue< MacState > m_macState
The current state of the MAC layer.
Definition: lr-wpan-mac.h:1139
void EndChannelEnergyScan()
Called at the end of one ED channel scan.
uint8_t m_incomingFnlCapSlot
Indication of the Slot where the CAP portion of the INCOMING Superframe ends.
Definition: lr-wpan-mac.h:488
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:991
uint8_t m_numLostBeacons
The number of consecutive loss beacons in a beacon tracking operation.
Definition: lr-wpan-mac.h:633
uint8_t GetMacMaxFrameRetries() const
Get the macMaxFrameRetries attribute value.
bool IsTxAckReq()
Check if the packet to transmit requires acknowledgment.
void SendOneBeacon()
Called to send a single beacon frame.
void EnqueueTxQElement(Ptr< TxQueueElement > txQElement)
Add an element to the transmission queue.
void LostAssocRespCommand()
Called after m_assocRespCmdWaitTime timeout while waiting for an association response command.
void PlmeEdConfirm(PhyEnumeration status, uint8_t energyLevel)
IEEE 802.15.4-2006 section 6.2.2.4 PLME-ED.confirm status and energy level.
bool m_coor
Indicates if the current device is a coordinator type.
Definition: lr-wpan-mac.h:594
uint8_t m_lastRxFrameLqi
Keep track of the last received frame Link Quality Indicator.
Definition: lr-wpan-mac.h:1254
void EndChannelScan()
Called at the end of the current channel scan (Active or Passive) for a given duration.
void EndAssociateRequest()
Called to end an MLME-ASSOCIATE.request after changing the page and channel number.
Definition: lr-wpan-mac.cc:740
uint64_t m_macResponseWaitTime
The maximum time, in multiples of aBaseSuperframeDuration, a device shall wait for a response command...
Definition: lr-wpan-mac.h:400
void DoInitialize() override
Initialize() implementation.
Definition: lr-wpan-mac.cc:270
Represent the Mac Trailer with the Frame Check Sequence field.
void EnableFcs(bool enable)
Enable or disable FCS calculation for this trailer.
void SetFcs(Ptr< const Packet > p)
Calculate and set the FCS value based on the given packet.
bool CheckFcs(Ptr< const Packet > p)
Check the FCS of a given packet against the FCS value stored in the trailer.
Represent the Pending Address Specification field.
Represent the Superframe Specification information field.
void SetPanCoor(bool panCoor)
Set the Superframe Specification PAN coordinator field.
uint8_t GetFinalCapSlot() const
Get the the Final CAP Slot.
void SetAssocPermit(bool assocPermit)
Set the Superframe Specification Association Permit field.
void SetBattLifeExt(bool battLifeExt)
Set the Superframe Specification Battery Life Extension (BLE).
bool IsBattLifeExt() const
Check if the Battery Life Extension bit is enabled.
uint8_t GetBeaconOrder() const
Get the Superframe Specification Beacon Order field.
uint8_t GetFrameOrder() const
Get the Superframe Specification Frame Order field.
uint16_t GetSuperframe() const
Get the Superframe specification information field.
void SetFinalCapSlot(uint8_t capSlot)
Set the superframe specification Final CAP slot field.
void SetBeaconOrder(uint8_t bcnOrder)
Set the superframe specification Beacon Order field.
void SetSuperframeOrder(uint8_t frmOrder)
Set the superframe specification Superframe Order field.
constexpr uint32_t aMaxSIFSFrameSize
The maximum size of an MPDU, in octets, that can be followed by a Short InterFrame Spacing (SIFS) per...
constexpr uint32_t aMaxLostBeacons
The number of consecutive lost beacons that will cause the MAC sublayer of a receiving device to decl...
constexpr uint32_t aMaxBeaconPayloadLength
The maximum size, in octets, of a beacon payload.
constexpr uint32_t aMaxPhyPacketSize
The maximum packet size accepted by the PHY.
constexpr uint32_t aUnitBackoffPeriod
Number of symbols per CSMA/CA time unit, default 20 symbols.
constexpr uint32_t aTurnaroundTime
The turnaround time in symbol periods for switching the transceiver from RX to TX or vice-versa.
constexpr uint32_t aBaseSuperframeDuration
Length of a superframe in symbols.
constexpr uint32_t aMinMPDUOverhead
The minimum number of octets added by the MAC sublayer to the PSDU.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h: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 ",...
MacPibAttributeIdentifier
IEEE 802.15.4-2006 PHY and MAC PIB Attribute Identifiers Table 23 and Table 86.
MacState
MAC states.
Definition: lr-wpan-mac.h:75
SuperframeType
Superframe type.
Definition: lr-wpan-mac.h:116
PhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
Definition: lr-wpan-phy.h:115
MacStatus
The status of a confirm or an indication primitive as a result of a previous request.
PhyPibAttributeIdentifier
IEEE802.15.4-2006 PHY PIB Attribute Identifiers Table 23 in section 6.4.2.
Definition: lr-wpan-phy.h:167
@ macPanId
The 16-bit identifier of the Personal Area Network (PAN).
@ pCurrentChannel
RF channel used for transmissions and receptions.
@ macShortAddress
The short address of the device (16 bit address).
@ macBeaconPayloadLength
The length in octets of the beacon payload.
@ pCurrentPage
The current channel page.
@ macExtendedAddress
The extended address of the device (64 bit address).
@ macBeaconPayload
The contents of the beacon payload.
@ MAC_CSMA
MAC_CSMA.
Definition: lr-wpan-mac.h:77
@ MAC_GTS
MAC_GTS.
Definition: lr-wpan-mac.h:83
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition: lr-wpan-mac.h:80
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition: lr-wpan-mac.h:81
@ SET_PHY_TX_ON
SET_PHY_TX_ON.
Definition: lr-wpan-mac.h:82
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition: lr-wpan-mac.h:85
@ MAC_IDLE
MAC_IDLE.
Definition: lr-wpan-mac.h:76
@ MAC_INACTIVE
MAC_INACTIVE.
Definition: lr-wpan-mac.h:84
@ MAC_SENDING
MAC_SENDING.
Definition: lr-wpan-mac.h:78
@ MAC_ACK_PENDING
MAC_ACK_PENDING.
Definition: lr-wpan-mac.h:79
@ BEACON
The Beacon transmission or reception Period.
Definition: lr-wpan-mac.h:104
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition: lr-wpan-mac.h:107
@ CAP
Contention Access Period.
Definition: lr-wpan-mac.h:105
@ CFP
Contention Free Period.
Definition: lr-wpan-mac.h:106
@ MLME_SCAN_REQ
Pending MLME-SCAN.request primitive.
Definition: lr-wpan-mac.h:130
@ MLME_NONE
No pending primitive.
Definition: lr-wpan-mac.h:128
@ MLME_START_REQ
Pending MLME-START.request primitive.
Definition: lr-wpan-mac.h:129
@ MLME_ASSOC_REQ
Pending MLME-ASSOCIATION.request primitive.
Definition: lr-wpan-mac.h:131
@ FFD
Full Functional Device (FFD)
@ INCOMING
Incoming Superframe.
Definition: lr-wpan-mac.h:118
@ OUTGOING
Outgoing Superframe.
Definition: lr-wpan-mac.h:117
@ IEEE_802_15_4_PHY_RX_ON
Definition: lr-wpan-phy.h:122
@ IEEE_802_15_4_PHY_TRX_OFF
Definition: lr-wpan-phy.h:124
@ IEEE_802_15_4_PHY_TX_ON
Definition: lr-wpan-phy.h:125
@ IEEE_802_15_4_PHY_SUCCESS
Definition: lr-wpan-phy.h:123
@ IEEE_802_15_4_PHY_UNSPECIFIED
Definition: lr-wpan-phy.h:128
@ TX_OPTION_GTS
TX_OPTION_GTS.
Definition: lr-wpan-mac.h:65
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:64
@ TX_OPTION_INDIRECT
TX_OPTION_INDIRECT.
Definition: lr-wpan-mac.h:66
@ 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.
#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:1319
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
std::ostream & operator<<(std::ostream &os, const SuperframeField &superframeField)
Stream insertion operator.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
MacStatus m_status
The status of the last MSDU transmission.
MCPS-DATA.indication params.
MLME-ASSOCIATE.confirm params.
Mac16Address m_assocShortAddr
The short address used in the association request.
MacStatus m_status
The status of a MLME-associate.request.
MLME-ASSOCIATE.indication params.
uint8_t lqi
The link quality indicator of the received associate request command (Not officially supported in the...
Mac64Address m_extDevAddr
The extended address of the device requesting association.
uint8_t capabilityInfo
The operational capabilities of the device requesting association.
MLME-ASSOCIATE.request params.
Mac64Address m_coordExtAddr
The extended address of the coordinator with which to associate.
uint8_t m_coordAddrMode
The coordinator addressing mode for this primitive and subsequent MPDU.
uint8_t m_capabilityInfo
Specifies the operational capabilities of the associating device (bitmap).
Mac16Address m_coordShortAddr
The short address of the coordinator with which to associate.
uint8_t m_chNum
The channel number on which to attempt association.
uint16_t m_coordPanId
The identifier of the PAN with which to associate.
MLME-ASSOCIATE.response params.
MLME-BEACON-NOTIFY.indication params.
PanDescriptor m_panDescriptor
The PAN descriptor for the received beacon.
uint32_t m_sduLength
The number of octets contained in the beacon payload.
uint8_t m_bsn
The beacon sequence number.
Ptr< Packet > m_sdu
The set of octets comprising the beacon payload.
MLME-COMM-STATUS.indication params.
uint8_t m_dstAddrMode
The destination addressing mode for this primitive.
uint16_t m_panId
The PAN identifier of the device from which the frame was received or to which the frame was being se...
Mac64Address m_srcExtAddr
The extended address of the entity from which the frame causing the error originated.
MacStatus m_status
The communication status.
Mac16Address m_srcShortAddr
The short address of the entity from which the frame causing the error originated.
Mac16Address m_dstShortAddr
The short address of the device for which the frame was intended.
uint8_t m_srcAddrMode
The source addressing mode for this primitive.
Mac64Address m_dstExtAddr
The extended address of the device for which the frame was intended.
MLME-ORPHAN.indication params.
Mac64Address m_orphanAddr
The address of the orphaned device.
MLME-ORPHAN.response params.
MLME-START.confirm params.
MacStatus m_status
The confirmation status resulting from a MLME-poll.request.
std::vector< uint8_t > m_unscannedCh
A list of channels given in the request which were not scanned (Not valid for ED scans).
uint32_t m_chPage
The channel page on which the scan was performed.
std::vector< uint8_t > m_energyDetList
A list of energy measurements, one for each channel searched during ED scan (Not valid for Active,...
MacStatus m_status
The status of the scan request.
std::vector< PanDescriptor > m_panDescList
A list of PAN descriptor, one for each beacon found (Not valid for ED and Orphan scans).
uint8_t m_resultListSize
The number of elements returned in the appropriate result list.
uint8_t m_scanType
Indicates the type of scan performed (ED,ACTIVE,PASSIVE,ORPHAN).
MlmeScanType m_scanType
Indicates the type of scan performed as described in IEEE 802.15.4-2011 (5.1.2.1).
uint32_t m_scanChannels
The channel numbers to be scanned.
uint8_t m_scanDuration
The factor (0-14) used to calculate the length of time to spend scanning.
uint32_t m_chPage
The channel page on which to perform scan.
MacStatus m_status
The result of the request to write the PIB attribute.
MacPibAttributeIdentifier id
The id of the PIB attribute that was written.
MLME-START.confirm params.
MacStatus m_status
The status of a MLME-start.request.
MLME-START.request params.
bool m_battLifeExt
Flag indicating whether or not the Battery life extension (BLE) features are used.
uint8_t m_logCh
Logical channel on which to start using the new superframe configuration.
uint32_t m_logChPage
Logical channel page on which to start using the new superframe configuration.
bool m_coorRealgn
True if a realignment request command is to be transmitted prior changing the superframe.
uint8_t m_bcnOrd
Beacon Order, Used to calculate the beacon interval, a value of 15 indicates no periodic beacons will...
bool m_panCoor
On true this device will become coordinator.
uint8_t m_sfrmOrd
Superframe Order, indicates the length of the CAP in time slots.
uint16_t m_PanId
Pan Identifier used by the device.
MLME-SYNC-LOSS.indication params.
uint16_t m_panId
The PAN identifier with which the device lost synchronization or to which it was realigned.
MacStatus m_lossReason
The reason for the lost of synchronization.
PAN Descriptor, Table 17 IEEE 802.15.4-2011.
uint16_t m_coorPanId
The PAN ID of the coordinator as specified in the received beacon frame.
uint8_t m_logCh
The current channel number occupied by the network.
Time m_timeStamp
Beacon frame reception time.
bool m_gtsPermit
TRUE if the beacon is from the PAN coordinator that is accepting GTS requests.
Mac16Address m_coorShortAddr
The coordinator short address as specified in the coordinator address mode.
uint16_t m_superframeSpec
The superframe specification as specified in the received beacon frame.
AddressMode m_coorAddrMode
The coordinator addressing mode corresponding to the received beacon frame.
uint8_t m_linkQuality
The LQI at which the network beacon was received.
uint8_t m_logChPage
The current channel page occupied by the network.
Mac64Address m_coorExtAddr
The coordinator extended address as specified in the coordinator address mode.
std::ofstream queueSize