A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lr-wpan-mac.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 The Boeing Company
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors:
19  * Gary Pei <guangyu.pei@boeing.com>
20  * kwong yin <kwong-sang.yin@boeing.com>
21  * Tom Henderson <thomas.r.henderson@boeing.com>
22  * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
23  * Erwan Livolant <erwan.livolant@inria.fr>
24  */
25 #include "lr-wpan-mac.h"
26 #include "lr-wpan-csmaca.h"
27 #include "lr-wpan-mac-header.h"
28 #include "lr-wpan-mac-trailer.h"
29 #include <ns3/simulator.h>
30 #include <ns3/log.h>
31 #include <ns3/uinteger.h>
32 #include <ns3/node.h>
33 #include <ns3/packet.h>
34 #include <ns3/random-variable-stream.h>
35 #include <ns3/double.h>
36 
37 NS_LOG_COMPONENT_DEFINE ("LrWpanMac");
38 
39 #undef NS_LOG_APPEND_CONTEXT
40 #define NS_LOG_APPEND_CONTEXT \
41  std::clog << "[address " << m_shortAddress << "] ";
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (LrWpanMac);
46 
47 const uint32_t LrWpanMac::aMinMPDUOverhead = 9; // Table 85
48 
49 TypeId
51 {
52  static TypeId tid = TypeId ("ns3::LrWpanMac")
53  .SetParent<Object> ()
54  .AddConstructor<LrWpanMac> ()
55  .AddAttribute ("PanId", "16-bit identifier of the associated PAN",
56  UintegerValue (),
57  MakeUintegerAccessor (&LrWpanMac::m_macPanId),
58  MakeUintegerChecker<uint16_t> ())
59  .AddTraceSource ("MacTxEnqueue",
60  "Trace source indicating a packet has was enqueued in the transaction queue",
62  .AddTraceSource ("MacTxDequeue",
63  "Trace source indicating a packet has was dequeued from the transaction queue",
65  .AddTraceSource ("MacTx",
66  "Trace source indicating a packet has arrived for transmission by this device",
68  .AddTraceSource ("MacTxOk",
69  "Trace source indicating a packet has been successfully sent",
71  .AddTraceSource ("MacTxDrop",
72  "Trace source indicating a packet has been dropped during transmission",
74  .AddTraceSource ("MacPromiscRx",
75  "A packet has been received by this device, has been passed up from the physical layer "
76  "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
78  .AddTraceSource ("MacRx",
79  "A packet has been received by this device, has been passed up from the physical layer "
80  "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
82  .AddTraceSource ("MacRxDrop",
83  "Trace source indicating a packet was received, but dropped before being forwarded up the stack",
85  .AddTraceSource ("Sniffer",
86  "Trace source simulating a non-promiscuous packet sniffer attached to the device",
88  .AddTraceSource ("PromiscSniffer",
89  "Trace source simulating a promiscuous packet sniffer attached to the device",
91  .AddTraceSource ("MacState",
92  "The state of LrWpan Mac",
94  .AddTraceSource ("MacSentPkt",
95  "Trace source reporting some information about the sent packet",
97  ;
98  return tid;
99 }
100 
102 {
103 
104  // First set the state to a known value, call ChangeMacState to fire trace source.
107 
108  m_macRxOnWhenIdle = true;
109  m_macPanId = 0;
112  m_macPromiscuousMode = false;
114  m_retransmission = 0;
115  m_numCsmacaRetry = 0;
116  m_txPkt = 0;
117 
118  Ptr<UniformRandomVariable> uniformVar = CreateObject<UniformRandomVariable> ();
119  uniformVar->SetAttribute ("Min", DoubleValue (0.0));
120  uniformVar->SetAttribute ("Max", DoubleValue (255.0));
121  m_macDsn = SequenceNumber8 (uniformVar->GetValue ());
122  m_shortAddress = Mac16Address ("00:00");
123 }
124 
126 {
127 }
128 
129 void
131 {
132  if (m_macRxOnWhenIdle)
133  {
134  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
135  }
136  else
137  {
138  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
139  }
140 
142 }
143 
144 void
146 {
147  if (m_csmaCa != 0)
148  {
149  m_csmaCa->Dispose ();
150  m_csmaCa = 0;
151  }
152  m_txPkt = 0;
153  for (uint32_t i = 0; i < m_txQueue.size (); i++)
154  {
155  m_txQueue[i]->txQPkt = 0;
156  delete m_txQueue[i];
157  }
158  m_txQueue.clear ();
159  m_phy = 0;
160  m_mcpsDataIndicationCallback = MakeNullCallback< void, McpsDataIndicationParams, Ptr<Packet> > ();
161  m_mcpsDataConfirmCallback = MakeNullCallback< void, McpsDataConfirmParams > ();
162 
164 }
165 
166 bool
168 {
169  return m_macRxOnWhenIdle;
170 }
171 
172 void
173 LrWpanMac::SetRxOnWhenIdle (bool rxOnWhenIdle)
174 {
175  NS_LOG_FUNCTION (this << rxOnWhenIdle);
176  m_macRxOnWhenIdle = rxOnWhenIdle;
177 
178  if (m_lrWpanMacState == MAC_IDLE)
179  {
180  if (m_macRxOnWhenIdle)
181  {
182  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
183  }
184  else
185  {
186  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
187  }
188  }
189 }
190 
191 void
193 {
194  //NS_LOG_FUNCTION (this << address);
196 }
197 
198 void
200 {
201  //NS_LOG_FUNCTION (this << address);
202  m_selfExt = address;
203 }
204 
205 
208 {
209  NS_LOG_FUNCTION (this);
210  return m_shortAddress;
211 }
212 
215 {
216  NS_LOG_FUNCTION (this);
217  return m_selfExt;
218 }
219 void
221 {
222  NS_LOG_FUNCTION (this << p);
223 
224  McpsDataConfirmParams confirmParams;
225  confirmParams.m_msduHandle = params.m_msduHandle;
226 
227  // TODO: We need a drop trace for the case that the packet is too large or the request parameters are maleformed.
228  // The current tx drop trace is not suitable, because packets dropped using this trace carry the mac header
229  // and footer, while packets being dropped here do not have them.
230 
232  m_macDsn++;
233 
235  {
236  // Note, this is just testing maximum theoretical frame size per the spec
237  // The frame could still be too large once headers are put on
238  // in which case the phy will reject it instead
239  NS_LOG_ERROR (this << " packet too big: " << p->GetSize ());
240  confirmParams.m_status = IEEE_802_15_4_FRAME_TOO_LONG;
242  {
243  m_mcpsDataConfirmCallback (confirmParams);
244  }
245  return;
246  }
247 
248  if ((params.m_srcAddrMode == NO_PANID_ADDR)
249  && (params.m_dstAddrMode == NO_PANID_ADDR))
250  {
251  NS_LOG_ERROR (this << " Can not send packet with no Address field" );
252  confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS;
254  {
255  m_mcpsDataConfirmCallback (confirmParams);
256  }
257  return;
258  }
259  switch (params.m_srcAddrMode)
260  {
261  case NO_PANID_ADDR:
262  macHdr.SetSrcAddrMode (params.m_srcAddrMode);
263  macHdr.SetNoPanIdComp ();
264  break;
265  case ADDR_MODE_RESERVED:
266  macHdr.SetSrcAddrMode (params.m_srcAddrMode);
267  break;
268  case SHORT_ADDR:
269  macHdr.SetSrcAddrMode (params.m_srcAddrMode);
270  macHdr.SetSrcAddrFields (GetPanId (), GetShortAddress ());
271  break;
272  case EXT_ADDR:
273  macHdr.SetSrcAddrMode (params.m_srcAddrMode);
274  macHdr.SetSrcAddrFields (GetPanId (), GetExtendedAddress ());
275  break;
276  default:
277  NS_LOG_ERROR (this << " Can not send packet with incorrect Source Address mode = " << params.m_srcAddrMode);
278  confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS;
280  {
281  m_mcpsDataConfirmCallback (confirmParams);
282  }
283  return;
284  }
285 
286  macHdr.SetDstAddrMode (params.m_dstAddrMode);
287  // TODO: Add field for EXT_ADDR destination address (and use it here).
288  macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstAddr);
289  macHdr.SetSecDisable ();
290  //extract the last 3 bits in TxOptions and map to macHdr
291  int b0 = params.m_txOptions & TX_OPTION_ACK;
292  int b1 = params.m_txOptions & TX_OPTION_GTS;
293  int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
294  if (b0 == TX_OPTION_ACK)
295  {
296  // Set AckReq bit only if the destination is not the broadcast address.
297  if (!(macHdr.GetDstAddrMode () == SHORT_ADDR && macHdr.GetShortDstAddr () == "ff:ff"))
298  {
299  macHdr.SetAckReq ();
300  }
301  }
302  else if (b0 == 0)
303  {
304  macHdr.SetNoAckReq ();
305  }
306  else
307  {
309  NS_LOG_ERROR (this << "Incorrect TxOptions bit 0 not 0/1");
311  {
312  m_mcpsDataConfirmCallback (confirmParams);
313  }
314  return;
315  }
316 
317  //if is Slotted CSMA means its beacon enabled
318  if (m_csmaCa->IsSlottedCsmaCa ())
319  {
320  if (b1 == TX_OPTION_GTS)
321  {
322  //TODO:GTS Transmission
323  }
324  else if (b1 == 0)
325  {
326  //TODO:CAP Transmission
327  }
328  else
329  {
330  NS_LOG_ERROR (this << "Incorrect TxOptions bit 1 not 0/1");
333  {
334  m_mcpsDataConfirmCallback (confirmParams);
335  }
336  return;
337  }
338  }
339  else
340  {
341  if (b1 != 0)
342  {
343  NS_LOG_ERROR (this << "for non-beacon-enables PAN, bit 1 should always be set to 0");
346  {
347  m_mcpsDataConfirmCallback (confirmParams);
348  }
349  return;
350  }
351  }
352 
353  if (b2 == TX_OPTION_INDIRECT)
354  {
355  //TODO :indirect tx
356  }
357  else if (b2 == 0)
358  {
359  //TODO :direct tx
360  }
361  else
362  {
363  NS_LOG_ERROR (this << "Incorrect TxOptions bit 2 not 0/1");
366  {
367  m_mcpsDataConfirmCallback (confirmParams);
368  }
369  return;
370  }
371 
372  p->AddHeader (macHdr);
373 
374  LrWpanMacTrailer macTrailer;
375  // Calculate FCS if the global attribute ChecksumEnable is set.
376  if (Node::ChecksumEnabled ())
377  {
378  macTrailer.EnableFcs (true);
379  macTrailer.SetFcs (p);
380  }
381  p->AddTrailer (macTrailer);
382 
384 
385  TxQueueElement *txQElement = new TxQueueElement;
386  txQElement->txQMsduHandle = params.m_msduHandle;
387  txQElement->txQPkt = p;
388  m_txQueue.push_back (txQElement);
389 
390  CheckQueue ();
391 }
392 
393 void
395 {
396  NS_LOG_FUNCTION (this);
397 
398  // Pull a packet from the queue and start sending, if we are not already sending.
399  if (m_lrWpanMacState == MAC_IDLE && !m_txQueue.empty () && m_txPkt == 0 && !m_setMacState.IsRunning ())
400  {
401  TxQueueElement *txQElement = m_txQueue.front ();
402  m_txPkt = txQElement->txQPkt;
404  }
405 }
406 
407 void
409 {
410  m_csmaCa = csmaCa;
411 }
412 
413 void
415 {
416  m_phy = phy;
417 }
418 
421 {
422  return m_phy;
423 }
424 
425 void
427 {
429 }
430 
431 void
433 {
435 }
436 
437 void
438 LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
439 {
441 
442  NS_LOG_FUNCTION (this << psduLength << p << lqi);
443 
444  bool acceptFrame;
445 
446  // from sec 7.5.6.2 Reception and rejection, Std802.15.4-2006
447  // level 1 filtering, test FCS field and reject if frame fails
448  // level 2 filtering if promiscuous mode pass frame to higher layer otherwise perform level 3 filtering
449  // level 3 filtering accept frame
450  // if Frame type and version is not reserved, and
451  // if there is a dstPanId then dstPanId=m_macPanId or broadcastPanI, and
452  // if there is a shortDstAddr then shortDstAddr =shortMacAddr or broadcastAddr, and
453  // if beacon frame then srcPanId = m_macPanId
454  // if only srcAddr field in Data or Command frame,accept frame if srcPanId=m_macPanId
455 
456  Ptr<Packet> originalPkt = p->Copy (); // because we will strip headers
457 
458  m_promiscSnifferTrace (originalPkt);
459 
460  m_macPromiscRxTrace (originalPkt);
461  // XXX no rejection tracing (to macRxDropTrace) being performed below
462 
463  LrWpanMacTrailer receivedMacTrailer;
464  p->RemoveTrailer (receivedMacTrailer);
465  if (Node::ChecksumEnabled ())
466  {
467  receivedMacTrailer.EnableFcs (true);
468  }
469 
470  // level 1 filtering
471  if (!receivedMacTrailer.CheckFcs (p))
472  {
473  m_macRxDropTrace (originalPkt);
474  }
475  else
476  {
477  LrWpanMacHeader receivedMacHdr;
478  p->RemoveHeader (receivedMacHdr);
479 
481  params.m_dsn = receivedMacHdr.GetSeqNum ();
482  params.m_mpduLinkQuality = lqi;
483  params.m_srcPanId = receivedMacHdr.GetSrcPanId ();
484  params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode ();
485  // TODO: Add field for EXT_ADDR source address.
486  if (params.m_srcAddrMode == SHORT_ADDR)
487  {
488  params.m_srcAddr = receivedMacHdr.GetShortSrcAddr ();
489  }
490  params.m_dstPanId = receivedMacHdr.GetDstPanId ();
491  params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode ();
492  // TODO: Add field for EXT_ADDR destination address.
493  if (params.m_dstAddrMode == SHORT_ADDR)
494  {
495  params.m_dstAddr = receivedMacHdr.GetShortDstAddr ();
496  }
497 
498  NS_LOG_DEBUG ("Packet from " << params.m_srcAddr << " to " << params.m_dstAddr);
499 
501  {
502  //level 2 filtering
504  {
505  NS_LOG_DEBUG ("promiscuous mode, forwarding up");
506  m_mcpsDataIndicationCallback (params, p);
507  }
508  else
509  {
510  NS_LOG_ERROR (this << " Data Indication Callback not initialised");
511  }
512  }
513  else
514  {
515  //level 3 frame filtering
516  acceptFrame = (receivedMacHdr.GetType () != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
517 
518  if (acceptFrame)
519  {
520  acceptFrame = (receivedMacHdr.GetFrameVer () <= 1);
521  }
522 
523  if (acceptFrame
524  && (receivedMacHdr.GetDstAddrMode () > 1))
525  {
526  acceptFrame = receivedMacHdr.GetDstPanId () == m_macPanId
527  || receivedMacHdr.GetDstPanId () == 0xffff;
528  }
529 
530  if (acceptFrame
531  && (receivedMacHdr.GetDstAddrMode () == 2))
532  {
533  acceptFrame = receivedMacHdr.GetShortDstAddr () == m_shortAddress
534  || receivedMacHdr.GetShortDstAddr () == Mac16Address ("ff:ff"); // check for broadcast addrs
535  }
536 
537  if (acceptFrame
538  && (receivedMacHdr.GetDstAddrMode () == 3))
539  {
540  acceptFrame = (receivedMacHdr.GetExtDstAddr () == m_selfExt);
541  }
542 
543  if (acceptFrame
544  && (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_BEACON))
545  {
546  if (m_macPanId == 0xffff)
547  {
548  // TODO: Accept only if the frame version field is valid
549  acceptFrame = true;
550  }
551  else
552  {
553  acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId;
554  }
555  }
556 
557  if (acceptFrame
558  && ((receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_DATA)
559  || (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_COMMAND))
560  && (receivedMacHdr.GetSrcAddrMode () > 1))
561  {
562  acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId; // \todo need to check if PAN coord
563  }
564 
565  if (acceptFrame)
566  {
567  m_macRxTrace (originalPkt);
568  // \todo: What should we do if we receive a frame while waiting for an ACK?
569  // Especially if this frame has the ACK request bit set, should we reply with an ACK, possibly missing the pending ACK?
570 
571  // If the received frame is a frame with the ACK request bit set, we immediately send back an ACK.
572  // If we are currently waiting for a pending ACK, we assume the ACK was lost and trigger a retransmission after sending the ACK.
573  if ((receivedMacHdr.IsData () || receivedMacHdr.IsCommand ()) && receivedMacHdr.IsAckReq ()
574  && !(receivedMacHdr.GetDstAddrMode () == SHORT_ADDR && receivedMacHdr.GetShortDstAddr () == "ff:ff"))
575  {
576  // If this is a data or mac command frame, which is not a broadcast,
577  // with ack req set, generate and send an ack frame.
578  // If there is a CSMA medium access in progress we cancel the medium access
579  // for sending the ACK frame. A new transmission attempt will be started
580  // after the ACK was send.
582  {
585  }
586  else if (m_lrWpanMacState == MAC_CSMA)
587  {
588  // \todo: If we receive a packet while doing CSMA/CA, should we drop the packet because of channel busy,
589  // or should we restart CSMA/CA for the packet after sending the ACK?
590  // Currently we simply restart CSMA/CA after sending the ACK.
591  m_csmaCa->Cancel ();
592  }
593  // Cancel any pending MAC state change, ACKs have higher priority.
597  }
598 
599  if (receivedMacHdr.IsData () && !m_mcpsDataIndicationCallback.IsNull ())
600  {
601  // If it is a data frame, push it up the stack.
602  NS_LOG_DEBUG ("PdDataIndication(): Packet is for me; forwarding up");
603  m_mcpsDataIndicationCallback (params, p);
604  }
605  else if (receivedMacHdr.IsAcknowledgment () && m_txPkt && m_lrWpanMacState == MAC_ACK_PENDING)
606  {
607  LrWpanMacHeader macHdr;
608  m_txPkt->PeekHeader (macHdr);
609  if (receivedMacHdr.GetSeqNum () == macHdr.GetSeqNum ())
610  {
612  // If it is an ACK with the expected sequence number, finish the transmission
613  // and notify the upper layer.
616  {
617  TxQueueElement *txQElement = m_txQueue.front ();
618  McpsDataConfirmParams confirmParams;
619  confirmParams.m_msduHandle = txQElement->txQMsduHandle;
620  confirmParams.m_status = IEEE_802_15_4_SUCCESS;
621  m_mcpsDataConfirmCallback (confirmParams);
622  }
626  }
627  else
628  {
629  // If it is an ACK with an unexpected sequence number, mark the current transmission as failed and start a retransmit. (cf 7.5.6.4.3)
631  if (!PrepareRetransmission ())
632  {
635  }
636  else
637  {
640  }
641  }
642  }
643  }
644  else
645  {
646  m_macRxDropTrace (originalPkt);
647  }
648  }
649  }
650 }
651 
652 void
653 LrWpanMac::SendAck (uint8_t seqno)
654 {
655  NS_LOG_FUNCTION (this << static_cast<uint32_t> (seqno));
656 
658 
659  // Generate a corresponding ACK Frame.
661  LrWpanMacTrailer macTrailer;
662  Ptr<Packet> ackPacket = Create<Packet> (0);
663  ackPacket->AddHeader (macHdr);
664  // Calculate FCS if the global attribute ChecksumEnable is set.
665  if (Node::ChecksumEnabled ())
666  {
667  macTrailer.EnableFcs (true);
668  macTrailer.SetFcs (ackPacket);
669  }
670  ackPacket->AddTrailer (macTrailer);
671 
672  // Enqueue the ACK packet for further processing
673  // when the transmitter is activated.
674  m_txPkt = ackPacket;
675 
676  // Switch transceiver to TX mode. Proceed sending the Ack on confirm.
678  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TX_ON);
679 }
680 
681 void
683 {
684  TxQueueElement *txQElement = m_txQueue.front ();
685  Ptr<const Packet> p = txQElement->txQPkt;
686  m_numCsmacaRetry += m_csmaCa->GetNB () + 1;
687 
688  Ptr<Packet> pkt = p->Copy ();
689  LrWpanMacHeader hdr;
690  pkt->RemoveHeader (hdr);
691  if (hdr.GetShortDstAddr () != Mac16Address ("ff:ff"))
692  {
694  }
695 
696  txQElement->txQPkt = 0;
697  delete txQElement;
698  m_txQueue.pop_front ();
699  m_txPkt = 0;
700  m_retransmission = 0;
701  m_numCsmacaRetry = 0;
703 }
704 
705 void
707 {
708  NS_LOG_FUNCTION (this);
709 
710  // TODO: If we are a PAN coordinator and this was an indirect transmission,
711  // we will not initiate a retransmission. Instead we wait for the data
712  // being extracted after a new data request command.
713  if (!PrepareRetransmission ())
714  {
716  }
717  else
718  {
720  }
721 }
722 
723 bool
725 {
726  NS_LOG_FUNCTION (this);
727 
729  {
730  // Maximum number of retransmissions has been reached.
731  // remove the copy of the packet that was just sent
732  TxQueueElement *txQElement = m_txQueue.front ();
733  m_macTxDropTrace (txQElement->txQPkt);
735  {
736  McpsDataConfirmParams confirmParams;
737  confirmParams.m_msduHandle = txQElement->txQMsduHandle;
738  confirmParams.m_status = IEEE_802_15_4_NO_ACK;
739  m_mcpsDataConfirmCallback (confirmParams);
740  }
742  return false;
743  }
744  else
745  {
747  m_numCsmacaRetry += m_csmaCa->GetNB () + 1;
748  // Start next CCA process for this packet.
749  return true;
750  }
751 }
752 
753 void
755 {
757 
758  NS_LOG_FUNCTION (this << status << m_txQueue.size ());
759 
760  LrWpanMacHeader macHdr;
761  m_txPkt->PeekHeader (macHdr);
762  if (status == IEEE_802_15_4_PHY_SUCCESS)
763  {
764  if (!macHdr.IsAcknowledgment ())
765  {
766  // We have just send a regular data packet, check if we have to wait
767  // for an ACK.
768  if (macHdr.IsAckReq ())
769  {
770  // wait for the ack or the next retransmission timeout
771  // start retransmission timer
772  Time waitTime = MicroSeconds (GetMacAckWaitDuration () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false));
777  return;
778  }
779  else
780  {
782  // remove the copy of the packet that was just sent
784  {
785  McpsDataConfirmParams confirmParams;
786  NS_ASSERT_MSG (m_txQueue.size () > 0, "TxQsize = 0");
787  TxQueueElement *txQElement = m_txQueue.front ();
788  confirmParams.m_msduHandle = txQElement->txQMsduHandle;
789  confirmParams.m_status = IEEE_802_15_4_SUCCESS;
790  m_mcpsDataConfirmCallback (confirmParams);
791  }
793  }
794  }
795  else
796  {
797  // We have send an ACK. Clear the packet buffer.
798  m_txPkt = 0;
799  }
800  }
801  else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
802  {
803 
804  if (!macHdr.IsAcknowledgment ())
805  {
806  NS_ASSERT_MSG (m_txQueue.size () > 0, "TxQsize = 0");
807  TxQueueElement *txQElement = m_txQueue.front ();
808  m_macTxDropTrace (txQElement->txQPkt);
810  {
811  McpsDataConfirmParams confirmParams;
812  confirmParams.m_msduHandle = txQElement->txQMsduHandle;
813  confirmParams.m_status = IEEE_802_15_4_FRAME_TOO_LONG;
814  m_mcpsDataConfirmCallback (confirmParams);
815  }
817  }
818  else
819  {
820  NS_LOG_ERROR ("Unable to send ACK");
821  }
822  }
823  else
824  {
825  // Something went really wrong. The PHY is not in the correct state for
826  // data transmission.
827  NS_FATAL_ERROR ("Transmission attempt failed with PHY status " << status);
828  }
829 
832 }
833 
834 void
836 {
837  NS_LOG_FUNCTION (this << status);
838  // Direct this call through the csmaCa object
839  m_csmaCa->PlmeCcaConfirm (status);
840 }
841 
842 void
843 LrWpanMac::PlmeEdConfirm (LrWpanPhyEnumeration status, uint8_t energyLevel)
844 {
845  NS_LOG_FUNCTION (this << status << energyLevel);
846 
847 }
848 
849 void
852  LrWpanPhyPibAttributes* attribute)
853 {
854  NS_LOG_FUNCTION (this << status << id << attribute);
855 }
856 
857 void
859 {
860  NS_LOG_FUNCTION (this << status);
861 
863  {
864  NS_ASSERT (m_txPkt);
865 
866  // Start sending if we are in state SENDING and the PHY transmitter was enabled.
870  m_phy->PdDataRequest (m_txPkt->GetSize (), m_txPkt);
871  }
872  else if (m_lrWpanMacState == MAC_CSMA && (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
873  {
874  // Start the CSMA algorithm as soon as the receiver is enabled.
875  m_csmaCa->Start ();
876  }
877  else if (m_lrWpanMacState == MAC_IDLE)
878  {
880  // Do nothing special when going idle.
881  }
882  else if (m_lrWpanMacState == MAC_ACK_PENDING)
883  {
885  }
886  else
887  {
888  // TODO: What to do when we receive an error?
889  // If we want to transmit a packet, but switching the transceiver on results
890  // in an error, we have to recover somehow (and start sending again).
891  NS_FATAL_ERROR ("Error changing transceiver state");
892  }
893 }
894 
895 void
898 {
899  NS_LOG_FUNCTION (this << status << id);
900 }
901 
902 void
904 {
905  NS_LOG_FUNCTION (this << "mac state = " << macState);
906 
907  McpsDataConfirmParams confirmParams;
908 
909  if (macState == MAC_IDLE)
910  {
912 
913  if (m_macRxOnWhenIdle)
914  {
915  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
916  }
917  else
918  {
919  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
920  }
921 
922  CheckQueue ();
923  }
924  else if (macState == MAC_ACK_PENDING)
925  {
927  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
928  }
929  else if (macState == MAC_CSMA)
930  {
932 
934  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
935  }
936  else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_IDLE)
937  {
938  // Channel is idle, set transmitter to TX_ON
940  m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TX_ON);
941  }
942  else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
943  {
944  NS_ASSERT (m_txPkt);
945 
946  // cannot find a clear channel, drop the current packet.
947  NS_LOG_DEBUG ( this << " cannot find clear channel");
948  confirmParams.m_msduHandle = m_txQueue.front ()->txQMsduHandle;
952  {
953  m_mcpsDataConfirmCallback (confirmParams);
954  }
955  // remove the copy of the packet that was just sent
957 
959  }
960 }
961 
964 {
965  return m_associationStatus;
966 }
967 
968 void
970 {
971  m_associationStatus = status;
972 }
973 
974 uint16_t
976 {
977  return m_macPanId;
978 }
979 
980 void
981 LrWpanMac::SetPanId (uint16_t panId)
982 {
983  m_macPanId = panId;
984 }
985 
986 void
988 {
989  NS_LOG_LOGIC (this << " change lrwpan mac state from "
990  << m_lrWpanMacState << " to "
991  << newState);
993  m_lrWpanMacState = newState;
994 }
995 
996 uint64_t
998 {
999  return m_csmaCa->GetUnitBackoffPeriod () + m_phy->aTurnaroundTime + m_phy->GetPhySHRDuration ()
1000  + ceil (6 * m_phy->GetPhySymbolsPerOctet ());
1001 }
1002 
1003 uint8_t
1005 {
1006  return m_macMaxFrameRetries;
1007 }
1008 
1009 void
1011 {
1012  m_macMaxFrameRetries = retries;
1013 }
1014 
1015 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void EnableFcs(bool enable)
Enable or disable FCS calculation for this trailer.
LrWpanMacState
Definition: lr-wpan-mac.h:55
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
LrWpanAssociationStatus
table 83 of 802.15.4
Definition: lr-wpan-mac.h:80
void CheckQueue(void)
Check the transmission queue.
Definition: lr-wpan-mac.cc:394
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
void PlmeGetAttributeConfirm(LrWpanPhyEnumeration status, LrWpanPibAttributeIdentifier id, LrWpanPhyPibAttributes *attribute)
IEEE 802.15.4-2006 section 6.2.2.6 PLME-GET.confirm Get attributes per definition from Table 23 in se...
Definition: lr-wpan-mac.cc:850
void RemoveFirstTxQElement()
Remove the tip of the transmission queue, including clean up related to the last packet transmission...
Definition: lr-wpan-mac.cc:682
virtual ~LrWpanMac(void)
Definition: lr-wpan-mac.cc:125
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:578
LrWpanAssociationStatus GetAssociationStatus(void) const
Get the current association status.
Definition: lr-wpan-mac.cc:963
static bool ChecksumEnabled(void)
Definition: node.cc:268
McpsDataConfirmCallback m_mcpsDataConfirmCallback
This callback is used to report data transmission request status to the upper layers.
Definition: lr-wpan-mac.h:682
std::deque< TxQueueElement * > m_txQueue
The transmit queue used by the MAC.
Definition: lr-wpan-mac.h:715
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1018
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
LrWpanMacState m_lrWpanMacState
The current state of the MAC layer.
Definition: lr-wpan-mac.h:687
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
LrWpanAssociationStatus m_associationStatus
The current association status of the MAC layer.
Definition: lr-wpan-mac.h:692
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: lr-wpan-mac.cc:145
TracedCallback< LrWpanMacState, LrWpanMacState > m_macStateLogger
Definition: lr-wpan-mac.h:659
void SetShortAddress(Mac16Address address)
Set the short address of this MAC.
Definition: lr-wpan-mac.cc:192
bool IsRunning(void) const
This method is syntactic sugar for the ns3::Simulator::isExpired method.
Definition: event-id.cc:59
Doxygen introspection did not find any typical Config paths.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
IEEE802.15.4-2006 PHY PIB Attributes Table 23 in section 6.4.2.
Definition: lr-wpan-phy.h:128
McpsDataIndicationCallback m_mcpsDataIndicationCallback
This callback is used to notify incoming packets to the upper layers.
Definition: lr-wpan-mac.h:675
void SetMcpsDataConfirmCallback(McpsDataConfirmCallback c)
Set the callback for the confirmation of a data transmission request.
Definition: lr-wpan-mac.cc:432
void McpsDataRequest(McpsDataRequestParams params, Ptr< Packet > p)
IEEE 802.15.4-2006, section 7.1.1.1 MCPS-DATA.request Request to transfer a MSDU. ...
Definition: lr-wpan-mac.cc:220
uint8_t m_numCsmacaRetry
The number of CSMA/CA retries used for sending the current packet.
Definition: lr-wpan-mac.h:726
Mac16Address GetShortSrcAddr(void) const
static const uint32_t aMaxPhyPacketSize
The maximum packet size accepted by the PHY.
Definition: lr-wpan-phy.h:219
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets are being sent down to L1.
Definition: lr-wpan-mac.h:569
an EUI-64 address
Definition: mac64-address.h:41
Ptr< Packet > m_txPkt
The packet which is currently being sent by the MAC layer.
Definition: lr-wpan-mac.h:697
bool IsData(void) const
bool GetRxOnWhenIdle(void)
Check if the receiver will be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:167
void SetLrWpanMacState(LrWpanMacState macState)
CSMA-CA algorithm calls back the MAC after executing channel assessment.
Definition: lr-wpan-mac.cc:903
Mac64Address GetExtendedAddress(void) const
Get the extended address of this MAC.
Definition: lr-wpan-mac.cc:214
void SetMacMaxFrameRetries(uint8_t retries)
Set the macMaxFrameRetries attribute value.
void PlmeEdConfirm(LrWpanPhyEnumeration status, uint8_t energyLevel)
IEEE 802.15.4-2006 section 6.2.2.4 PLME-ED.confirm status and energy level.
Definition: lr-wpan-mac.cc:843
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:653
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:554
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:604
SequenceNumber< uint8_t, int8_t > SequenceNumber8
bool PrepareRetransmission(void)
Check for remaining retransmissions for the packet currently being sent.
Definition: lr-wpan-mac.cc:724
void PlmeCcaConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
Definition: lr-wpan-mac.cc:835
Hold an unsigned integer type.
Definition: uinteger.h:46
EventId m_ackWaitTimeout
Scheduler event for the ACK timeout of the currently transmitted data packet.
Definition: lr-wpan-mac.h:732
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:586
Mac64Address GetExtDstAddr(void) const
EventId m_setMacState
Scheduler event for a deferred MAC state change.
Definition: lr-wpan-mac.h:737
Helper structure for managing transmission queue elements.
Definition: lr-wpan-mac.h:489
bool m_macRxOnWhenIdle
Indication of whether the MAC sublayer is to enable its receiver during idle periods.
Definition: lr-wpan-mac.h:457
void PdDataConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.1.2 Confirm the end of transmission of an MPDU to MAC.
Definition: lr-wpan-mac.cc:754
bool IsAckReq(void) const
void SetPhy(Ptr< LrWpanPhy > phy)
Set the underlying PHY for the MAC.
Definition: lr-wpan-mac.cc:414
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
void SetFcs(Ptr< const Packet > p)
Calculate and set the FCS value based on the given packet.
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:546
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...
Definition: lr-wpan-mac.cc:438
LrWpanMcpsDataConfirmStatus m_status
Definition: lr-wpan-mac.h:130
LrWpanAddressMode m_srcAddrMode
Definition: lr-wpan-mac.h:119
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:277
uint8_t m_retransmission
The number of already used retransmission for the currently transmitted packet.
Definition: lr-wpan-mac.h:721
Mac64Address m_selfExt
The extended address used by this MAC.
Definition: lr-wpan-mac.h:710
uint8_t GetSrcAddrMode(void) const
LrWpanAddressMode m_dstAddrMode
Definition: lr-wpan-mac.h:120
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:284
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
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:613
bool IsAcknowledgment(void) const
Mac16Address GetShortDstAddr(void) const
void SetRxOnWhenIdle(bool rxOnWhenIdle)
Set if the receiver should be enabled when the MAC is idle.
Definition: lr-wpan-mac.cc:173
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:300
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:595
uint16_t GetSrcPanId(void) const
bool m_macPromiscuousMode
Indicates if MAC sublayer is in receive all mode.
Definition: lr-wpan-mac.h:431
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:986
This class can contain 16 bit addresses.
Definition: mac16-address.h:39
LrWpanMac(void)
Default constructor.
Definition: lr-wpan-mac.cc:101
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:633
void SetExtendedAddress(Mac64Address address)
Set the extended address of this MAC.
Definition: lr-wpan-mac.cc:199
uint8_t m_macMaxFrameRetries
The maximum number of retries allowed after a transmission failure.
Definition: lr-wpan-mac.h:450
static TypeId GetTypeId(void)
Get the type ID.
Definition: lr-wpan-mac.cc:50
uint8_t GetFrameVer(void) const
#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:84
Represent the Mac Trailer with the Frame Check Sequence field.
Ptr< LrWpanPhy > m_phy
The PHY associated with this MAC.
Definition: lr-wpan-mac.h:664
SequenceNumber8 m_macDsn
Sequence number added to transmitted data or MAC command frame, 00-ff.
Definition: lr-wpan-mac.h:444
static const uint32_t aMinMPDUOverhead
The minimum number of octets added by the MAC sublayer to the PSDU.
Definition: lr-wpan-mac.h:177
void ChangeMacState(LrWpanMacState newState)
Change the current MAC state to the given new state.
Definition: lr-wpan-mac.cc:987
bool IsCommand(void) const
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:213
uint8_t GetMacMaxFrameRetries(void) const
Get the macMaxFrameRetries attribute value.
Ptr< LrWpanCsmaCa > m_csmaCa
The CSMA/CA implementation used by this MAC.
Definition: lr-wpan-mac.h:669
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Definition: event-id.cc:47
Mac16Address GetShortAddress(void) const
Get the short address of this MAC.
Definition: lr-wpan-mac.cc:207
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:562
uint8_t GetSeqNum(void) const
uint16_t m_macPanId
16 bits id of PAN on which this device is operating.
Definition: lr-wpan-mac.h:438
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
void PlmeSetTRXStateConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.8 PLME-SET-TRX-STATE.confirm Set PHY state.
Definition: lr-wpan-mac.cc:858
enum LrWpanMacType GetType(void) const
void SendAck(uint8_t seqno)
Send an acknowledgment packet for the given sequence number.
Definition: lr-wpan-mac.cc:653
bool CheckFcs(Ptr< const Packet > p)
Check the FCS of a given packet against the FCS value stored in the trailer.
a base class which provides memory management and object aggregation
Definition: object.h:64
tuple address
Definition: first.py:37
uint16_t GetPanId(void) const
Get the PAN id used by this MAC.
Definition: lr-wpan-mac.cc:975
void AckWaitTimeout(void)
Handle an ACK timeout with a packet retransmission, if there are retransmission left, or a packet drop.
Definition: lr-wpan-mac.cc:706
Hold a floating point type.
Definition: double.h:41
Ptr< LrWpanPhy > GetPhy(void)
Get the underlying PHY of the MAC.
Definition: lr-wpan-mac.cc:420
Mac16Address m_shortAddress
The short address used by this MAC.
Definition: lr-wpan-mac.h:704
void SetAttribute(std::string name, const AttributeValue &value)
Definition: object-base.cc:176
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::isExpired method.
Definition: event-id.cc:53
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void SetCsmaCa(Ptr< LrWpanCsmaCa > csmaCa)
Set the CSMA/CA implementation to be used by the MAC.
Definition: lr-wpan-mac.cc:408
uint8_t GetDstAddrMode(void) const
void SetPanId(uint16_t panId)
Set the PAN id used by this MAC.
Definition: lr-wpan-mac.cc:981
void PlmeSetAttributeConfirm(LrWpanPhyEnumeration status, LrWpanPibAttributeIdentifier id)
IEEE 802.15.4-2006 section 6.2.2.10 PLME-SET.confirm Set attributes per definition from Table 23 in s...
Definition: lr-wpan-mac.cc:896
virtual void DoInitialize(void)
This method is called only once by Object::Initialize.
Definition: lr-wpan-mac.cc:130
static Mac64Address Allocate(void)
Allocate a new Mac64Address.
uint16_t GetDstPanId(void) const
uint64_t GetMacAckWaitDuration(void) const
Get the macAckWaitDuration attribute value.
Definition: lr-wpan-mac.cc:997
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
virtual void DoInitialize(void)
This method is called only once by Object::Initialize.
Definition: object.cc:342
LrWpanPhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
Definition: lr-wpan-phy.h:93
void SetAssociationStatus(LrWpanAssociationStatus status)
Set the current association status.
Definition: lr-wpan-mac.cc:969
LrWpanPibAttributeIdentifier
IEEE802.15.4-2006 PHY PIB Attribute Identifiers Table 23 in section 6.4.2.
Definition: lr-wpan-phy.h:113
void SetMcpsDataIndicationCallback(McpsDataIndicationCallback c)
Set the callback for the indication of an incoming data packet.
Definition: lr-wpan-mac.cc:426