A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
zigbee-nwk.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Tokushima University, Japan
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors:
7 *
8 * Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
9 * Ryo Okuda <c611901200@tokushima-u.ac.jp>
10 */
11
12#include "zigbee-nwk.h"
13
14#include "zigbee-nwk-tables.h"
15
16#include "ns3/log.h"
17#include "ns3/packet.h"
18#include "ns3/simulator.h"
19
20using namespace ns3::lrwpan;
21
22#undef NS_LOG_APPEND_CONTEXT
23#define NS_LOG_APPEND_CONTEXT \
24 std::clog << "[" << m_nwkNetworkAddress << " | " << m_nwkIeeeAddress << "] ";
25
26namespace ns3
27{
28namespace zigbee
29{
30
31NS_LOG_COMPONENT_DEFINE("ZigbeeNwk");
33
36{
37 static TypeId tid =
38 TypeId("ns3::zigbee::ZigbeeNwk")
40 .SetGroupName("Zigbee")
41 .AddConstructor<ZigbeeNwk>()
42 .AddAttribute("NwkcCoordinatorCapable",
43 "[Constant] Indicates whether the device is capable of becoming a"
44 "Zigbee coordinator.",
45 BooleanValue(true),
48 .AddAttribute("NwkcProtocolVersion",
49 "[Constant] The version of the Zigbee NWK protocol in"
50 "the device (placeholder)",
51 UintegerValue(0x02),
54 .AddAttribute("NwkcRouteDiscoveryTime",
55 "[Constant] The duration until a route discovery expires",
56 TimeValue(MilliSeconds(0x2710)),
59 .AddAttribute("NwkcInitialRREQRetries",
60 "[Constant] The number of times the first broadcast transmission"
61 "of a RREQ cmd frame is retried.",
62 UintegerValue(0x03),
65 .AddAttribute("NwkcRREQRetries",
66 "[Constant] The number of times the broadcast transmission of a"
67 "RREQ cmd frame is retried on relay by intermediate router or"
68 "coordinator.",
69 UintegerValue(0x02),
72 .AddAttribute("NwkcRREQRetryInterval",
73 "[Constant] The duration between retries of a broadcast RREQ "
74 "cmd frame.",
78 .AddAttribute("NwkcMinRREQJitter",
79 "[Constant] The minimum jitter for broadcast retransmission "
80 "of a RREQ (msec)",
81 DoubleValue(2),
84 .AddAttribute("NwkcMaxRREQJitter",
85 "[Constant] The duration between retries of a broadcast RREQ (msec)",
86 DoubleValue(128),
89 .AddAttribute("NwkcMaxBroadcastJitter",
90 "[Constant] The duration between retries of a broadcast RREQ (msec)",
91 DoubleValue(40),
94 .AddAttribute("nwkMaxBroadcastRetries",
95 "The maximum number of retries allowed after a broadcast "
96 "transmission failure.",
97 UintegerValue(0x03),
100 .AddAttribute("NwkPassiveAckTimeout",
101 "The maximum time duration in milliseconds allowed for the parent "
102 "all the child devices to retransmit a broadcast message.",
106 .AddAttribute("MaxPendingTxQueueSize",
107 "The maximum size of the table storing pending packets awaiting "
108 "to be transmitted after discovering a route to the destination.",
109 UintegerValue(10),
112 .AddTraceSource("RreqRetriesExhausted",
113 "Trace source indicating when a node has "
114 "reached the maximum allowed number of RREQ retries during a "
115 "route discovery request",
117 "ns3::zigbee::ZigbeeNwk::RreqRetriesExhaustedTracedCallback");
118 return tid;
119}
120
125
126void
128{
129 NS_LOG_FUNCTION(this);
130
133 m_uniformRandomVariable->SetAttribute("Min", DoubleValue(0.0));
134 m_uniformRandomVariable->SetAttribute("Max", DoubleValue(255.0));
135
137
138 m_netFormParams = {};
139 m_netFormParamsGen = nullptr;
140 m_beaconPayload = nullptr;
142 m_nwkPanId = 0xffff;
143 m_nwkExtendedPanId = 0xffffffffffffffff;
145
148 m_nwkMaxDepth = 5;
149 m_nwkMaxChildren = 20;
150 m_nwkMaxRouters = 6;
152 m_nwkUseTreeRouting = false;
153
155 m_nwkSymLink = false;
156
158
159 m_nwkIsConcentrator = false;
162
163 // TODO, set according to equation 3.5.2.1?
165
170
172 m_rreqJitter->SetAttribute("Min", DoubleValue(m_nwkcMinRREQJitter));
173 m_rreqJitter->SetAttribute("Max", DoubleValue(m_nwkcMaxRREQJitter));
174
176 m_bcstJitter->SetAttribute("Min", DoubleValue(0));
178
180}
181
186
187void
193
194void
226
227void
232
233void
238
241{
242 return m_mac;
243}
244
245void
247{
248 std::ostream* os = stream->GetStream();
249 std::ios oldState(nullptr);
250 oldState.copyfmt(*os);
251
252 std::ostringstream nwkAddr;
253 std::ostringstream ieeeAddr;
254
255 nwkAddr << m_nwkNetworkAddress;
256 ieeeAddr << m_nwkIeeeAddress;
257
258 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
259 *os << "[" << ieeeAddr.str() << " | " << nwkAddr.str() << "] | ";
260 *os << "Time: " << Simulator::Now().As(Time::S) << " | ";
261 m_nwkRoutingTable.Print(stream);
262}
263
264void
266{
267 std::ostream* os = stream->GetStream();
268 std::ios oldState(nullptr);
269 oldState.copyfmt(*os);
270
271 std::ostringstream nwkAddr;
272 std::ostringstream ieeeAddr;
273
274 nwkAddr << m_nwkNetworkAddress;
275 ieeeAddr << m_nwkIeeeAddress;
276
277 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
278 *os << "[" << ieeeAddr.str() << " | " << nwkAddr.str() << "] | ";
279 *os << "Time: " << Simulator::Now().As(Time::S) << " | ";
280 m_nwkRouteDiscoveryTable.Print(stream);
281}
282
283void
285{
286 std::ostream* os = stream->GetStream();
287 std::ios oldState(nullptr);
288 oldState.copyfmt(*os);
289
290 std::ostringstream nwkAddr;
291 std::ostringstream ieeeAddr;
292
293 nwkAddr << m_nwkNetworkAddress;
294 ieeeAddr << m_nwkIeeeAddress;
295
296 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
297 *os << "[" << ieeeAddr.str() << " | " << nwkAddr.str() << "] | ";
298 *os << "Time: " << Simulator::Now().As(Time::S) << " | ";
299 m_nwkNeighborTable.Print(stream);
300}
301
302void
304{
305 std::ostream* os = stream->GetStream();
306 std::ios oldState(nullptr);
307 oldState.copyfmt(*os);
308
309 std::ostringstream nwkAddr;
310 std::ostringstream ieeeAddr;
311
312 nwkAddr << m_nwkNetworkAddress;
313 ieeeAddr << m_nwkIeeeAddress;
314
315 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
316 *os << "[" << ieeeAddr.str() << " | " << nwkAddr.str() << "] | ";
317 *os << "Time: " << Simulator::Now().As(Time::S) << " | ";
318 m_rreqRetryTable.Print(stream);
319}
320
323{
324 Ptr<NeighborTableEntry> neighborEntry;
325 if (m_nwkNeighborTable.LookUpEntry(dst, neighborEntry))
326 {
327 neighbor = true;
328 return dst;
329 }
330
332 if (m_nwkRoutingTable.LookUpEntry(dst, entry))
333 {
334 if (entry->GetStatus() == ROUTE_ACTIVE)
335 {
336 neighbor = false;
337 return entry->GetNextHopAddr();
338 }
339 }
340
341 neighbor = false;
342 return Mac16Address("FF:FF"); // route not found
343}
344
350
353{
354 return m_nwkIeeeAddress;
355}
356
357void
359{
360 NS_LOG_FUNCTION(this);
361
362 ZigbeeNwkHeader nwkHeader;
363 msdu->RemoveHeader(nwkHeader);
364
365 // Decrease the radius in the network header as it might be retransmitted
366 // to a next hop.
367 uint8_t radius = nwkHeader.GetRadius();
368 nwkHeader.SetRadius(radius - 1);
369
370 // Check if the received frame is from a neighbor and update LQI if necessary
371 Ptr<NeighborTableEntry> neighborEntry;
372 if (m_nwkNeighborTable.LookUpEntry(nwkHeader.GetSrcAddr(), neighborEntry))
373 {
374 neighborEntry->SetLqi(params.m_mpduLinkQuality);
375 neighborEntry->SetOutgoingCost(GetLQINonLinearValue(params.m_mpduLinkQuality));
376 }
377
378 switch (nwkHeader.GetFrameType())
379 {
380 case DATA: {
381 if (nwkHeader.IsMulticast())
382 {
383 // DATA MULTICAST
384 if (nwkHeader.GetMulticastMode() == MulticastMode::MEMBER)
385 {
386 // Mcst Member Mode,Zigbee specification r22.1.0 Section 3.6.6.3
387 ReceiveMulticastMemberFrame(nwkHeader, msdu, params);
388 }
389 else
390 {
391 // Mcst Non-Member Mode,Zigbee specification r22.1.0 Section 3.6.6.4
392 if (m_nwkGroupIdTable->IsGroupMember(nwkHeader.GetDstAddr().ConvertToInt()))
393 {
394 // Treat frame as a multicast member
396 ReceiveMulticastMemberFrame(nwkHeader, msdu, params);
397 }
398 else
399 {
400 ReceiveMulticastNonMemberFrame(nwkHeader, msdu, params);
401 }
402 }
403 }
404 else if (IsBroadcastAddress(nwkHeader.GetDstAddr()))
405 {
406 // DATA BROADCAST
407
409 if (m_btt.LookUpEntry(nwkHeader.GetSeqNum(), btr))
410 {
411 return;
412 }
413
414 // Check the capabilities of the current device
415 CapabilityInformation capability;
417
418 bool rebroadcastFlag = false;
419
420 if (nwkHeader.GetDstAddr() == 0xFFFF ||
421 (nwkHeader.GetDstAddr() == 0xFFFD && capability.IsReceiverOnWhenIdle()) ||
422 (nwkHeader.GetDstAddr() == 0xFFFC && capability.GetDeviceType() != ENDDEVICE))
423 {
424 rebroadcastFlag = true;
425 }
426 else if (nwkHeader.GetDstAddr() == 0xFFFB)
427 {
428 NS_FATAL_ERROR("Broadcast to low power routers not supported");
429 return;
430 }
431
432 if (rebroadcastFlag && nwkHeader.GetRadius() > 0)
433 {
434 Ptr<Packet> rebroadcastPkt = msdu->Copy();
435 rebroadcastPkt->AddHeader(nwkHeader);
436 SendDataBcst(rebroadcastPkt, 0);
437 }
438
439 // Add a new broadcast transaction record to the
440 // broadcasst transaction table
442 nwkHeader.GetSeqNum(),
445 m_btt.AddEntry(btr);
446
447 if (!m_nldeDataIndicationCallback.IsNull())
448 {
449 NldeDataIndicationParams dataParams;
450 dataParams.m_srcAddr = nwkHeader.GetSrcAddr();
451 dataParams.m_dstAddr = nwkHeader.GetDstAddr();
452 dataParams.m_dstAddrMode = UCST_BCST;
453 dataParams.m_linkQuality = params.m_mpduLinkQuality;
454 dataParams.m_nsduLength = msdu->GetSize();
455 dataParams.m_rxTime = Simulator::Now();
456 dataParams.m_securityUse = false;
457 m_nldeDataIndicationCallback(dataParams, msdu);
458 }
459 }
460 else
461 {
462 // DATA UNICAST
463 if (nwkHeader.GetDstAddr() == m_nwkNetworkAddress)
464 {
465 // Zigbee specification r22.1.0 Sections 3.6.2.2 and 3.6.3.3
466 if (!m_nldeDataIndicationCallback.IsNull())
467 {
468 NldeDataIndicationParams dataParams;
469 dataParams.m_srcAddr = nwkHeader.GetSrcAddr();
470 dataParams.m_dstAddr = nwkHeader.GetDstAddr();
471 dataParams.m_dstAddrMode = UCST_BCST;
472 dataParams.m_linkQuality = params.m_mpduLinkQuality;
473 dataParams.m_nsduLength = msdu->GetSize();
474 dataParams.m_rxTime = Simulator::Now();
475 dataParams.m_securityUse = false;
476 m_nldeDataIndicationCallback(dataParams, msdu);
477 }
478 }
479 else
480 {
481 // This is not the packet destination,
482 // Add again the network header to the DATA packet and
483 // route the packet to the next hop
484 msdu->AddHeader(nwkHeader);
485 SendDataUcst(msdu, 0);
486 }
487 }
488 break;
489 }
490 case NWK_COMMAND: {
491 ZigbeePayloadType payloadType;
492 msdu->RemoveHeader(payloadType);
493
494 if (payloadType.GetCmdType() == ROUTE_REQ_CMD || payloadType.GetCmdType() == ROUTE_REP_CMD)
495 {
496 CapabilityInformation capability;
498 if (capability.GetDeviceType() != ROUTER)
499 {
500 // Received RREQ or RREP but the device
501 // has no routing capabilities
502 return;
503 }
504 }
505 // NOTE: this cover the cases for MESH routing
506 // TREE routing is not supported
507 uint8_t linkCost = GetLinkCost(params.m_mpduLinkQuality);
508
509 if (payloadType.GetCmdType() == ROUTE_REQ_CMD)
510 {
512 msdu->RemoveHeader(payload);
513 // Zigbee specification r22.1.0 Section 3.6.3.5.2
514 ReceiveRREQ(params.m_srcAddr, linkCost, nwkHeader, payload);
515 }
516 else if (payloadType.GetCmdType() == ROUTE_REP_CMD)
517 {
519 msdu->RemoveHeader(payload);
520 // Zigbee specification r22.1.0 Section 3.6.3.5.3
521 ReceiveRREP(params.m_srcAddr, linkCost, nwkHeader, payload);
522 }
523 break;
524 }
525 case INTER_PAN:
526 NS_LOG_ERROR("Inter PAN frame received but not supported");
527 break;
528 default:
529 NS_LOG_ERROR("Unknown frame received in NWK layer");
530 }
531}
532
533void
535 uint8_t linkCost,
536 ZigbeeNwkHeader nwkHeader,
538{
539 NS_LOG_FUNCTION(this);
540
541 if (nwkHeader.GetSrcAddr() == m_nwkNetworkAddress)
542 {
543 // I am the original initiator of the RREQ, ignore request
544 return;
545 }
546
547 // Calculate the pathcost on the RREQ receiving device
548 uint8_t pathCost = linkCost + payload.GetPathCost();
549
550 // Many-to-one routing
551
553 {
554 RouteDiscoveryStatus routeStatus =
555 ProcessManyToOneRoute(macSrcAddr, pathCost, nwkHeader, payload);
556
557 // Update the path cost of the RREQ
558 payload.SetPathCost(pathCost);
559
560 // Note: At this point we already have the updated radius, which was updated as soon
561 // as the frame was received (i.e. In the MCPS-DATA.indication).
562
563 if (routeStatus == MANY_TO_ONE_ROUTE || routeStatus == ROUTE_UPDATED)
564 {
567 this,
568 nwkHeader,
569 payload,
570 0);
573 }
574 return;
575 }
576
577 // Mesh Routing (Unicast or Multicast Group)
578
579 Mac16Address nextHop;
580 RouteDiscoveryStatus nextHopStatus =
581 FindNextHop(macSrcAddr, pathCost, nwkHeader, payload, nextHop);
582
583 if (payload.GetDstAddr() == m_nwkNetworkAddress || nextHopStatus == ROUTE_FOUND)
584 {
585 // RREQ is for this device or its children
586 NS_LOG_DEBUG("RREQ is for me or my children, sending a RREP to [" << macSrcAddr << "]");
587
588 SendRREP(macSrcAddr,
589 nwkHeader.GetSrcAddr(),
590 payload.GetDstAddr(),
591 payload.GetRouteReqId(),
592 pathCost);
593 }
594 else if (nextHopStatus == ROUTE_NOT_FOUND || nextHopStatus == ROUTE_UPDATED)
595 {
596 NS_LOG_DEBUG("Route for device [" << payload.GetDstAddr()
597 << "] not found, forwarding RREQ");
598
599 // Update path cost and resend the RREQ
600 payload.SetPathCost(pathCost);
603 this,
604 nwkHeader,
605 payload,
607 }
608}
609
610void
612 uint8_t linkCost,
613 ZigbeeNwkHeader nwkHeader,
615{
616 NS_LOG_FUNCTION(this);
617
618 // RREP received, cancel any ongoing RREQ retry events for that
619 // RREQ ID and remove entry from RREQ retry table.
620 Ptr<RreqRetryTableEntry> rreqRetryTableEntry;
621 if (m_rreqRetryTable.LookUpEntry(payload.GetRouteReqId(), rreqRetryTableEntry))
622 {
623 rreqRetryTableEntry->GetRreqEventId().Cancel();
624 m_rreqRetryTable.Delete(payload.GetRouteReqId());
625 }
626
627 uint8_t pathCost = linkCost + payload.GetPathCost();
628
629 if (payload.GetOrigAddr() == m_nwkNetworkAddress)
630 {
631 // The RREP is destined for this device
633 if (m_nwkRouteDiscoveryTable.LookUpEntry(payload.GetRouteReqId(),
634 payload.GetOrigAddr(),
635 discEntry))
636 {
637 Ptr<RoutingTableEntry> routeEntry;
638 if (m_nwkRoutingTable.LookUpEntry(payload.GetRespAddr(), routeEntry))
639 {
640 if (routeEntry->GetStatus() == ROUTE_DISCOVERY_UNDERWAY)
641 {
642 if (routeEntry->IsGroupIdPresent())
643 {
644 routeEntry->SetStatus(ROUTE_VALIDATION_UNDERWAY);
645 }
646 else
647 {
648 routeEntry->SetStatus(ROUTE_ACTIVE);
649 }
650 routeEntry->SetNextHopAddr(macSrcAddr);
651 discEntry->SetResidualCost(pathCost);
652 }
653 else if (routeEntry->GetStatus() == ROUTE_VALIDATION_UNDERWAY ||
654 routeEntry->GetStatus() == ROUTE_ACTIVE)
655 {
656 if (pathCost < discEntry->GetResidualCost())
657 {
658 routeEntry->SetNextHopAddr(macSrcAddr);
659 discEntry->SetResidualCost(pathCost);
660 }
661 }
662
663 NS_LOG_DEBUG("RREP from source [" << payload.GetRespAddr()
664 << "] is for me; received from last hop ["
665 << macSrcAddr << "]");
666
668 {
669 // We only report the result of the route discovery request
670 // with the first RREP received.
673 {
674 NlmeRouteDiscoveryConfirmParams routeDiscConfirmParams;
675 routeDiscConfirmParams.m_status = NwkStatus::SUCCESS;
676 m_nlmeRouteDiscoveryConfirmCallback(routeDiscConfirmParams);
677 }
678 }
679
681 if (!m_pendingTxQueue.empty() &&
682 DequeuePendingTx(payload.GetRespAddr(), pendingTxPkt))
683 {
684 // Buffer a copy of the DATA packet that will be transmitted
685 // for handling after transmission (i.e. NSDE-DATA.confirm)
686 BufferTxPkt(pendingTxPkt->txPkt->Copy(),
687 m_macHandle.GetValue(),
688 pendingTxPkt->nsduHandle);
689
690 // There is a pending packet awaiting to be transmitted
691 // to the next hop, send it.
692 McpsDataRequestParams mcpsDataparams;
693 mcpsDataparams.m_txOptions = 0x01; // Acknowledment on.
694 mcpsDataparams.m_dstPanId = m_nwkPanId;
695 mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
696 mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
697 mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
698 mcpsDataparams.m_dstAddr = routeEntry->GetNextHopAddr();
699 m_macHandle++;
700
702 m_mac,
703 mcpsDataparams,
704 pendingTxPkt->txPkt);
705 }
706 }
707 else
708 {
709 m_nwkRouteDiscoveryTable.Delete(payload.GetRouteReqId(), payload.GetOrigAddr());
710 }
711 }
712 }
713 else
714 {
715 // The RREP is NOT destined for this device
717 if (m_nwkRouteDiscoveryTable.LookUpEntry(payload.GetRouteReqId(),
718 payload.GetOrigAddr(),
719 discEntry))
720 {
721 if (payload.GetPathCost() < discEntry->GetResidualCost())
722 {
723 Ptr<RoutingTableEntry> routeEntry;
724 if (m_nwkRoutingTable.LookUpEntry(payload.GetRespAddr(), routeEntry))
725 {
726 routeEntry->SetNextHopAddr(macSrcAddr);
727 routeEntry->SetStatus(ROUTE_ACTIVE);
728 discEntry->SetResidualCost(pathCost);
729 // Forward route reply to the next hop back to the original route requester
730 SendRREP(discEntry->GetSenderAddr(),
731 payload.GetOrigAddr(),
732 payload.GetRespAddr(),
733 payload.GetRouteReqId(),
734 pathCost);
735 }
736 else
737 {
738 NS_LOG_ERROR("Route discovery entry detected but no corresponding routing "
739 "table entry found");
740 }
741 }
742 }
743 }
744}
745
746void
748 Ptr<Packet> msdu,
750{
751 NS_LOG_FUNCTION(this);
752
753 // As described in Zigbee specification r22.1.0 Section 3.6.6.3
754
755 // Drop if we've already seen this multicast frame
757 if (m_btt.LookUpEntry(nwkHeader.GetSeqNum(), btr))
758 {
759 return;
760 }
761
762 // Add new record to BTT
765 nwkHeader.GetSeqNum(),
767
768 if (!m_btt.AddEntry(newBtr))
769 {
770 return;
771 }
772
773 // Verify if the device is capable of relaying multicast frames
774 // (i.e., not an end device)
776 bool canRelay = (capability.GetDeviceType() != MacDeviceType::ENDDEVICE);
777
778 // Case 1: Group Member — process and optionally retransmit
779
780 if (m_nwkGroupIdTable->IsGroupMember(nwkHeader.GetDstAddr().ConvertToInt()))
781 {
782 // Push the multicast frame to the APS layer
783 if (!m_nldeDataIndicationCallback.IsNull())
784 {
785 NldeDataIndicationParams dataParams;
786 dataParams.m_srcAddr = nwkHeader.GetSrcAddr();
787 dataParams.m_dstAddr = nwkHeader.GetDstAddr();
788 dataParams.m_dstAddrMode = AddressMode::MCST;
789 dataParams.m_linkQuality = params.m_mpduLinkQuality;
790 dataParams.m_nsduLength = msdu->GetSize();
791 dataParams.m_rxTime = Simulator::Now();
792 dataParams.m_securityUse = false;
793 m_nldeDataIndicationCallback(dataParams, msdu->Copy());
794 }
795 // TODO: Add Rx Trace here
796
797 if (canRelay)
798 {
800 nwkHeader.SetNonMemberRadius(nwkHeader.GetMaxNonMemberRadius());
801 msdu->AddHeader(nwkHeader);
804 this,
805 msdu,
806 0);
807 }
808 return;
809 }
810
811 // Case 2: Non Group Member — forward if non-zero radius
812
813 uint8_t radius = nwkHeader.GetNonMemberRadius();
814 if (radius == 0)
815 {
816 m_btt.Delete(nwkHeader.GetSeqNum());
817 return;
818 }
819
820 // Decrement radius and retransmit if allowed
821 nwkHeader.SetNonMemberRadius(radius - 1);
822
823 if (radius != 0 && canRelay)
824 {
825 msdu->AddHeader(nwkHeader);
828 this,
829 msdu,
830 0);
831 }
832}
833
834void
836 Ptr<Packet> msdu,
838{
839 NS_LOG_FUNCTION(this);
840
841 NS_ASSERT_MSG(!nwkHeader.GetDstAddr().IsBroadcast(),
842 "Error: Non-member multicast frame should have a Group ID address");
843
844 // As described in Zigbee specification r22.1.0 Section 3.6.6.4
845 // If the GROUP ID (destination address) is in our routing table,
846 // our non member multicast frame is transmitted as a unicast frame
847 // to the next hop in the routing table, otherwise it is discarded.
849 if (m_nwkRoutingTable.LookUpEntry(nwkHeader.GetDstAddr(), entry))
850 {
851 if (entry->GetStatus() == RouteStatus::ROUTE_VALIDATION_UNDERWAY)
852 {
853 entry->SetStatus(RouteStatus::ROUTE_ACTIVE);
854 }
855
856 if ((entry->GetStatus() == ROUTE_ACTIVE))
857 {
858 msdu->AddHeader(nwkHeader);
859 McpsDataRequestParams mcpsDataparams;
860 mcpsDataparams.m_dstPanId = m_nwkPanId;
861 mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
862 mcpsDataparams.m_txOptions = 0x01; // Acknowledment on for Non-Member Multicast
863 mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
864 mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
865 mcpsDataparams.m_dstAddr = entry->GetNextHopAddr();
866 m_macHandle++;
868 }
869 }
870}
871
872bool
874{
875 return address == "FF:FF" || address == "FF:FD" || address == "FF:FC" || address == "FF:FB";
876}
877
880 uint8_t pathCost,
881 ZigbeeNwkHeader nwkHeader,
883 Mac16Address& nextHop)
884{
885 NS_LOG_FUNCTION(this);
886
887 if (payload.GetMulticastField() &&
888 m_nwkGroupIdTable->IsGroupMember(payload.GetDstAddr().ConvertToInt()))
889 {
890 // If the destination is a group member, we can directly return the next hop
891 // as the destination address.
892 nextHop = payload.GetDstAddr();
893 return ROUTE_FOUND;
894 }
895
896 // Mesh routing
897
898 // Check if I am the destination
899 if (payload.GetDstAddr() == m_nwkNetworkAddress)
900 {
901 // I am the destination, return myself as next hop
902 nextHop = m_nwkNetworkAddress;
903 return ROUTE_FOUND;
904 }
905
906 // Check if the destination is our neighbor
907 Ptr<NeighborTableEntry> neighborEntry;
908 if (m_nwkNeighborTable.LookUpEntry(payload.GetDstAddr(), neighborEntry))
909 {
910 nextHop = payload.GetDstAddr();
911 return ROUTE_FOUND;
912 }
913
915 if (m_nwkRoutingTable.LookUpEntry(payload.GetDstAddr(), entry))
916 {
917 if (!(entry->GetStatus() == ROUTE_ACTIVE) &&
918 !(entry->GetStatus() == ROUTE_VALIDATION_UNDERWAY))
919 {
920 // Entry found but is not valid
921 entry->SetStatus(ROUTE_DISCOVERY_UNDERWAY);
922 }
923 else
924 {
925 // Entry found
926 nextHop = entry->GetNextHopAddr();
927 return ROUTE_FOUND;
928 }
929 }
931 {
932 // Check that the max routing capacity has not been reached. If the capacity was reached,
933 // attempt to delete the first found expired entry, if the table persist to be full
934 // then send a route error.
935 if (m_nwkRoutingTable.GetSize() >= m_nwkRoutingTable.GetMaxTableSize())
936 {
937 m_nwkRoutingTable.DeleteExpiredEntry();
938
939 if (m_nwkRoutingTable.GetSize() >= m_nwkRoutingTable.GetMaxTableSize())
940 {
942 {
944 confirmParams.m_status = ROUTE_ERROR;
947 }
948 return TABLE_FULL;
949 }
950 }
951
952 // Entry not found, create a new routing entry
953 Ptr<RoutingTableEntry> newRoutingEntry =
956 true, // TODO no route cache
957 false, // Many to one
958 false, // TODO: Route record
959 payload.GetMulticastField(), // Group id
960 Mac16Address("FF:FF"));
961 newRoutingEntry->SetLifeTime(Simulator::Now() + m_routeExpiryTime);
962
963 m_nwkRoutingTable.AddEntry(newRoutingEntry);
964 }
965 else
966 {
968 {
970 confirmParams.m_status = ROUTE_ERROR;
973 }
974 return NO_DISCOVER_ROUTE;
975 }
976
977 // 2- Find entry in DISCOVERY TABLE
979 if (m_nwkRouteDiscoveryTable.LookUpEntry(payload.GetRouteReqId(),
980 nwkHeader.GetSrcAddr(),
981 discEntry))
982 {
983 // Entry Found
984 if (pathCost < discEntry->GetForwardCost())
985 {
986 // More optimal route found, update route discovery values.
987 discEntry->SetSenderAddr(macSrcAddr);
988 discEntry->SetForwardCost(pathCost);
989 discEntry->SetExpTime(Simulator::Now() + m_nwkcRouteDiscoveryTime);
990 return ROUTE_UPDATED;
991 }
992 else
993 {
994 return DISCOVER_UNDERWAY;
995 }
996 }
997 else
998 {
999 // Entry NOT found, add NEW entry to route discovery table.
1000 Ptr<RouteDiscoveryTableEntry> newDiscEntry =
1002 nwkHeader.GetSrcAddr(),
1003 macSrcAddr, // macSrcAddr,
1004 pathCost, // payload.GetPathCost(), // Forward cost
1005 0xff, // Residual cost
1007
1008 if (!m_nwkRouteDiscoveryTable.AddEntry(newDiscEntry))
1009 {
1010 return TABLE_FULL;
1011 }
1012 }
1013 return ROUTE_NOT_FOUND;
1014}
1015
1018 uint8_t pathCost,
1019 ZigbeeNwkHeader nwkHeader,
1021{
1023 if (m_nwkRouteDiscoveryTable.LookUpEntry(payload.GetRouteReqId(),
1024 nwkHeader.GetSrcAddr(),
1025 discEntry))
1026 {
1027 Ptr<RoutingTableEntry> routeEntry;
1028 if (m_nwkRoutingTable.LookUpEntry(nwkHeader.GetSrcAddr(), routeEntry))
1029 {
1030 if (routeEntry->GetStatus() == ROUTE_VALIDATION_UNDERWAY ||
1031 routeEntry->GetStatus() == ROUTE_ACTIVE)
1032 {
1033 if (pathCost < discEntry->GetForwardCost())
1034 {
1035 // Update with a better route.
1036 routeEntry->SetNextHopAddr(macSrcAddr);
1037 discEntry->SetForwardCost(pathCost);
1038 discEntry->SetExpTime(Simulator::Now() + m_nwkcRouteDiscoveryTime);
1039 return ROUTE_UPDATED;
1040 }
1041 return NO_ROUTE_CHANGE;
1042 }
1043 }
1044 else
1045 {
1046 NS_LOG_ERROR("Entry found in the discovery table but not the routing table");
1047 return NO_ROUTE_CHANGE;
1048 }
1049 }
1050 else
1051 {
1052 // Entry NOT found, add NEW entry to route discovery table.
1053 Ptr<RouteDiscoveryTableEntry> newDiscEntry =
1055 nwkHeader.GetSrcAddr(),
1056 macSrcAddr, // previous hop address
1057 pathCost, // Forward cost
1058 0xff, // Residual cost (not used by Many-to-One)
1060
1061 // TODO: what to do if route discovery table is full?
1062 m_nwkRouteDiscoveryTable.AddEntry(newDiscEntry);
1063
1064 // Define the type of Many-To-One routing (with or without route record)
1065 bool routeRecord = false;
1067 {
1068 routeRecord = true;
1069 }
1070
1071 Ptr<RoutingTableEntry> routeEntry;
1072 if (m_nwkRoutingTable.LookUpEntry(nwkHeader.GetSrcAddr(), routeEntry))
1073 {
1074 if (routeEntry->GetStatus() == ROUTE_VALIDATION_UNDERWAY ||
1075 routeEntry->GetStatus() == ROUTE_ACTIVE)
1076 {
1077 // The entry exist in routing table but it was not in discovery table
1078 // Refresh the Route
1079 routeEntry->SetNextHopAddr(macSrcAddr);
1080 // TODO: other parameters
1081 return ROUTE_UPDATED;
1082 }
1083 return NO_ROUTE_CHANGE;
1084 }
1085 else
1086 {
1087 // New routing table entry
1088 // Check that the max routing capacity has not been reached. If the capacity was
1089 // reached, attempt to delete the first found expired entry, if the table persist to be
1090 // full then send a route error.
1091 if (m_nwkRoutingTable.GetSize() >= m_nwkRoutingTable.GetMaxTableSize())
1092 {
1093 m_nwkRoutingTable.DeleteExpiredEntry();
1094
1095 if (m_nwkRoutingTable.GetSize() >= m_nwkRoutingTable.GetMaxTableSize())
1096 {
1098 {
1099 NlmeRouteDiscoveryConfirmParams confirmParams;
1100 confirmParams.m_status = ROUTE_ERROR;
1103 }
1104 return TABLE_FULL;
1105 }
1106 }
1107
1108 Ptr<RoutingTableEntry> newRoutingEntry =
1111 true, // TODO no route cache
1112 true, // Many to one
1113 routeRecord, // TODO: Route record
1114 false, // TODO: Group id
1115 macSrcAddr);
1116
1117 newRoutingEntry->SetLifeTime(Simulator::Now() + m_routeExpiryTime);
1118
1119 m_nwkRoutingTable.AddEntry(newRoutingEntry);
1120 return MANY_TO_ONE_ROUTE;
1121 }
1122 }
1123 return NO_ROUTE_CHANGE;
1124}
1125
1126void
1127ZigbeeNwk::SendDataUcst(Ptr<Packet> packet, uint8_t nwkHandle)
1128{
1129 NS_LOG_FUNCTION(this);
1130
1131 // Obtain information from the DATA packet
1132 ZigbeeNwkHeader nwkHeaderData;
1133 packet->PeekHeader(nwkHeaderData);
1134
1135 // Construct a RREQ network header and payload for possible
1136 // route discovery request
1137
1138 ZigbeeNwkHeader nwkHeaderRreq;
1139 nwkHeaderRreq.SetFrameType(NWK_COMMAND);
1141 nwkHeaderRreq.SetDiscoverRoute(nwkHeaderData.GetDiscoverRoute());
1142 // See r22.1.0, Table 3-69
1143 // Set destination to broadcast (all routers and coordinator)
1144 nwkHeaderRreq.SetDstAddr(Mac16Address("FF:FC"));
1145 nwkHeaderRreq.SetSrcAddr(m_nwkNetworkAddress);
1146 nwkHeaderRreq.SetSeqNum(m_nwkSequenceNumber.GetValue());
1147
1148 // see Zigbee specification 3.2.2.33.3
1149 if (nwkHeaderData.GetRadius() == 0)
1150 {
1151 nwkHeaderRreq.SetRadius(m_nwkMaxDepth * 2);
1152 }
1153 else
1154 {
1155 nwkHeaderRreq.SetRadius(nwkHeaderData.GetRadius());
1156 }
1157
1159 payloadRreq.SetRouteReqId(m_routeRequestId.GetValue());
1160 payloadRreq.SetDstAddr(nwkHeaderData.GetDstAddr());
1161 payloadRreq.SetPathCost(0);
1162
1163 // If the original Data packet is marked as multicast,
1164 // then set the multicast field in the RREQ payload
1165 // In essence, this will initiate a multicast route discovery
1166 // if necessary
1167 if (nwkHeaderData.IsMulticast())
1168 {
1169 payloadRreq.SetMulticastField(true);
1170 }
1171
1172 Mac16Address nextHop;
1173 RouteDiscoveryStatus nextHopStatus =
1174 FindNextHop(m_nwkNetworkAddress, 0, nwkHeaderRreq, payloadRreq, nextHop);
1175
1176 if (nextHopStatus == ROUTE_FOUND)
1177 {
1178 // Buffer a copy of the DATA packet that will be transmitted
1179 // for handling after transmission (i.e. NSDE-DATA.confirm)
1180 BufferTxPkt(packet->Copy(), m_macHandle.GetValue(), nwkHandle);
1181
1182 // Parameters as described in Section 3.6.3.3
1183 McpsDataRequestParams mcpsDataparams;
1184 mcpsDataparams.m_dstPanId = m_nwkPanId;
1185 mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
1186 mcpsDataparams.m_txOptions = 0x01; // Acknowledment on.
1187 mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
1188 mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
1189 mcpsDataparams.m_dstAddr = nextHop;
1190 m_macHandle++;
1192 }
1193 else if (nextHopStatus == ROUTE_NOT_FOUND)
1194 {
1195 // Route not found. Route marked as DISCOVER UNDERWAY,
1196 // packet added to pending Tx Queue and we initiate route
1197 // discovery
1198
1199 EnqueuePendingTx(packet, nwkHandle);
1200
1203 this,
1204 nwkHeaderRreq,
1205 payloadRreq,
1207
1210 }
1211}
1212
1213void
1214ZigbeeNwk::SendDataBcst(Ptr<Packet> packet, uint8_t nwkHandle)
1215{
1216 // Buffer a copy of the DATA packet that will be transmitted
1217 // for handling after transmission (i.e. NSDE-DATA.confirm)
1218 BufferTxPkt(packet->Copy(), m_macHandle.GetValue(), nwkHandle);
1219
1220 // Parameters as described in Section 3.6.5
1221 // TxOptions = 0 by default, i.e. no acknowledgment
1222 McpsDataRequestParams mcpsDataparams;
1223 mcpsDataparams.m_dstPanId = m_nwkPanId;
1224 mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
1225 mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
1226 mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
1227 mcpsDataparams.m_dstAddr = Mac16Address("FF:FF");
1228 m_macHandle++;
1230}
1231
1232void
1234{
1235 Ptr<TxPkt> bufferedElement;
1236 if (RetrieveTxPkt(params.m_msduHandle, bufferedElement))
1237 {
1238 ZigbeeNwkHeader nwkHeader;
1239 bufferedElement->txPkt->PeekHeader(nwkHeader);
1240
1241 if (nwkHeader.GetFrameType() != NwkType::DATA)
1242 {
1243 NS_LOG_ERROR("Received DATA.confirm for a non-DATA packet");
1244 return;
1245 }
1246
1247 if (IsBroadcastAddress(nwkHeader.GetDstAddr()) || nwkHeader.IsMulticast())
1248 {
1249 if (params.m_status != MacStatus::SUCCESS)
1250 {
1251 // Broadcast or Multicast failed, retry sending the packet.
1252 // Zigbee specification r22.1.0 Section 3.6.6.3
1254 if (m_btt.LookUpEntry(nwkHeader.GetSeqNum(), btr))
1255 {
1256 btr->SetBcstRetryCount(btr->GetBcstRetryCount() + 1);
1257 if (btr->GetBcstRetryCount() <= m_nwkMaxBroadcastRetries)
1258 {
1259 // Retry sending the Broadcast or Multicast packet
1260
1263 this,
1264 bufferedElement->txPkt,
1265 bufferedElement->nwkHandle);
1266 }
1267 else
1268 {
1269 // Broadcast retries exhausted, silently discard the packet
1270 NS_LOG_WARN("Broadcast or Multicast packet retries exhausted for packet"
1271 " with sequence number "
1272 << nwkHeader.GetSeqNum());
1273 }
1274 }
1275 }
1276 }
1277 else if (nwkHeader.GetSrcAddr() == m_nwkNetworkAddress)
1278 {
1279 // Send the confirmation to next layer after the packet transmission,
1280 // only if packet transmitted was in the initiator of the NLDE-DATA.request
1281
1282 if (!m_nldeDataConfirmCallback.IsNull())
1283 {
1284 // Zigbee Specification r22.1.0, End of Section 3.2.1.1.3
1285 // Report the the results of a request to a transmission of a packet
1286 NldeDataConfirmParams nldeDataConfirmParams;
1287 // nldeDataConfirmParams.m_status =
1288 // static_cast<ZigbeeNwkStatus>(params.m_status);
1289 nldeDataConfirmParams.m_nsduHandle = bufferedElement->nwkHandle;
1290 m_nldeDataConfirmCallback(nldeDataConfirmParams);
1291 }
1292 }
1293 }
1294}
1295
1296void
1298{
1299 NS_LOG_FUNCTION(this);
1300
1301 if (m_pendPrimitiveNwk == NLME_NETWORK_FORMATION && params.m_scanType == MLMESCAN_ED)
1302 {
1303 if (params.m_status != MacStatus::SUCCESS)
1304 {
1306 m_netFormParams = {};
1307 m_netFormParamsGen = nullptr;
1308
1309 // See Zigbee specification r22.1.0, Section 3.2.2.5.3, (6.b.i)
1311 {
1313 confirmParams.m_status = GetNwkStatus(params.m_status);
1315 }
1316 }
1317 else
1318 {
1319 // TODO: Continue energy detection (ED) scan in other interfaces if supported.
1320
1321 // See Zigbee specification r22.1.0, Section 3.2.2.5.3, (6.b.ii)
1322 // Pick the list of acceptable channels on which to continue doing an ACTIVE scan
1323 std::vector<uint8_t> energyList = params.m_energyDetList;
1324 uint32_t channelMask = m_netFormParams.m_scanChannelList.channelsField[0];
1325
1326 NS_LOG_DEBUG("[NLME-NETWORK-FORMATION.request]: \n "
1327 << "EnergyThreshold: " << m_scanEnergyThreshold << " | ChannelMask: 0x"
1328 << std::hex << channelMask << std::dec << " | EnergyList: " << energyList);
1329
1331 uint32_t countAcceptableChannels = 0;
1332 uint8_t energyListPos = 0;
1333 for (uint32_t i = 0; i < 32; i++)
1334 {
1335 // check if the i position exist in the ChannelMask
1336 if (channelMask & (1 << i))
1337 {
1338 if (energyList[energyListPos] <= m_scanEnergyThreshold)
1339 {
1340 m_filteredChannelMask |= (1 << i);
1341 countAcceptableChannels++;
1342 }
1343 energyListPos++;
1344 }
1345 }
1346
1347 NS_LOG_DEBUG("[NLME-NETWORK-FORMATION.request]:\n "
1348 << "Energy scan complete, " << countAcceptableChannels
1349 << " acceptable channels found : 0x" << std::hex << m_filteredChannelMask
1350 << std::dec);
1351
1352 if (countAcceptableChannels == 0)
1353 {
1355 m_netFormParams = {};
1356 m_netFormParamsGen = nullptr;
1357
1359 {
1361 confirmParams.m_status = NwkStatus::STARTUP_FAILURE;
1363 }
1364 }
1365 else
1366 {
1367 // See Zigbee specification r22.1.0, Section 3.2.2.5.3, (6.c)
1368 MlmeScanRequestParams mlmeParams;
1369 mlmeParams.m_chPage = (m_filteredChannelMask >> 27) & (0x01F);
1371 mlmeParams.m_scanDuration = m_netFormParams.m_scanDuration;
1372 mlmeParams.m_scanType = MLMESCAN_ACTIVE;
1374 }
1375 }
1376 }
1377 else if (m_pendPrimitiveNwk == NLME_NETWORK_FORMATION && params.m_scanType == MLMESCAN_ACTIVE)
1378 {
1379 if (params.m_status == MacStatus::NO_BEACON || params.m_status == MacStatus::SUCCESS)
1380 {
1381 // TODO: We should ACTIVE scan channels on each interface
1382 // (only possible when more interfaces (nwkMacInterfaceTable) are supported)
1383 // for now, only a single interface is considered.
1384
1385 // See Zigbee specification r22.1.0, (3.2.2.5.3, 6.d.ii)
1386 // Check results of an ACTIVE scan an select a different PAN ID and channel:
1387 // Choose a random PAN ID
1388 // Page is always 0 until more interfaces supported
1389 uint8_t channel = 0;
1390 uint8_t page = 0;
1391 uint16_t panId = m_uniformRandomVariable->GetInteger(1, 0xFFF7);
1392
1393 std::vector<uint8_t> pansPerChannel(27);
1394 uint32_t secondFilteredChannelMask = m_filteredChannelMask;
1395 for (const auto& panDescriptor : params.m_panDescList)
1396 {
1397 // Clear all the bit positions of channels with active PAN networks
1398 // (The channels with PAN descriptors received)
1399 secondFilteredChannelMask &= ~(1 << panDescriptor.m_logCh);
1400 // Add to the number of PAN detected in this channel
1401 pansPerChannel[panDescriptor.m_logCh] += 1;
1402 }
1403
1404 for (uint32_t i = 0; i < 32; i++)
1405 {
1406 // Pick the first channel in the list that does not contain
1407 // any PAN network
1408 if (secondFilteredChannelMask & (1 << i))
1409 {
1410 channel = i;
1411 break;
1412 }
1413 }
1414
1415 if (channel < 11 || channel > 26)
1416 {
1417 // Extreme case: All the channels in the previous step contained PAN networks
1418 // therefore choose the channel with the least PAN networks.
1419 uint8_t channelIndex = 0;
1420 uint8_t lowestPanNum = 99;
1421 for (const auto& numPans : pansPerChannel)
1422 {
1423 if (numPans != 0 && numPans <= lowestPanNum)
1424 {
1425 channel = channelIndex;
1426 lowestPanNum = numPans;
1427 }
1428 channelIndex++;
1429 }
1430
1431 NS_ASSERT_MSG(channel < 11 || channel > 26,
1432 "Invalid channel in PAN descriptor list during ACTIVE scan");
1433 }
1434
1435 // store the chosen page, channel and pan Id.
1437 m_netFormParamsGen->page = page;
1438 m_netFormParamsGen->channel = channel;
1439 m_netFormParamsGen->panId = panId;
1440
1441 NS_LOG_DEBUG("[NLME-NETWORK-FORMATION.request]:\n "
1442 << "Active scan complete, page " << std::dec << page << ", channel "
1443 << std::dec << channel << " and PAN ID 0x" << std::hex << panId << std::dec
1444 << " chosen.");
1445
1446 // Set the device short address (3.2.2.5.3 , 6.f)
1448 if (m_netFormParams.m_distributedNetwork)
1449 {
1450 pibAttr->macShortAddress = m_netFormParams.m_distributedNetworkAddress;
1451 m_nwkNetworkAddress = m_netFormParams.m_distributedNetworkAddress;
1452 }
1453 else
1454 {
1455 pibAttr->macShortAddress = Mac16Address("00:00");
1457 }
1458 // Set Short Address and continue with beacon payload afterwards.
1460 m_mac,
1462 pibAttr);
1463 }
1464 else
1465 {
1466 // Error occurred during network formation active scan
1467 // report to higher layer (Section 3.2.2.5.3, 6.d)
1468
1470 m_netFormParams = {};
1471 m_netFormParamsGen = nullptr;
1472
1474 {
1476 confirmParams.m_status = GetNwkStatus(params.m_status);
1478 }
1479 }
1480 }
1481 else if (m_pendPrimitiveNwk == NLME_NET_DISCV && params.m_scanType == MLMESCAN_ACTIVE)
1482 {
1483 NlmeNetworkDiscoveryConfirmParams netDiscConfirmParams;
1485
1486 if (params.m_status == MacStatus::SUCCESS)
1487 {
1488 NS_LOG_DEBUG("[NLME-NETWORK-DISCOVERY.request]:\n "
1489 << "Active scan, " << m_networkDescriptorList.size()
1490 << " PARENT capable device(s) found");
1491
1492 netDiscConfirmParams.m_netDescList = m_networkDescriptorList;
1493 netDiscConfirmParams.m_networkCount = m_networkDescriptorList.size();
1494 netDiscConfirmParams.m_status = NwkStatus::SUCCESS;
1496 }
1497 else
1498 {
1499 NS_LOG_DEBUG("[NLME-NETWORK-DISCOVERY.request]: Active scan failed with"
1500 " status: "
1501 << GetNwkStatus(params.m_status));
1502 netDiscConfirmParams.m_status = GetNwkStatus(params.m_status);
1503 }
1504
1506 {
1507 m_nlmeNetworkDiscoveryConfirmCallback(netDiscConfirmParams);
1508 }
1509 }
1510 else if (m_pendPrimitiveNwk == NLME_JOIN && params.m_scanType == MLMESCAN_ORPHAN)
1511 {
1512 // TODO: Add macInterfaceIndex and channelListStructure params when supported
1513 if (params.m_status == MacStatus::SUCCESS)
1514 {
1515 // Orphan scan was successful (Join success), first update the extended
1516 // PAN id and the capability information, then the
1517 // the nwkNetworkAddress with the macShortAddress, this
1518 // will be followed by an update of the m_nwkPanId with macPanId
1519 // and finally the join confirmation
1520 m_nwkExtendedPanId = m_joinParams.m_extendedPanId;
1521 m_nwkCapabilityInformation = m_joinParams.m_capabilityInfo;
1523 m_mac,
1525 }
1526 else
1527 {
1529 m_joinParams = {};
1530 NS_LOG_DEBUG("[NLME-JOIN.request]: Orphan scan completed but no networks found");
1531
1532 if (!m_nlmeJoinConfirmCallback.IsNull())
1533 {
1534 NlmeJoinConfirmParams joinConfirmParams;
1535 joinConfirmParams.m_status = NwkStatus::NO_NETWORKS;
1536 m_nlmeJoinConfirmCallback(joinConfirmParams);
1537 }
1538 }
1539 }
1540}
1541
1542void
1544{
1545 NS_LOG_FUNCTION(this);
1546
1548 {
1549 NlmeJoinConfirmParams joinConfirmParams;
1550 joinConfirmParams.m_extendedPanId = m_joinParams.m_extendedPanId;
1551 joinConfirmParams.m_enhancedBeacon = false; // hardcoded, no support
1552 joinConfirmParams.m_macInterfaceIndex = 0; // hardcoded, no support
1553 joinConfirmParams.m_networkAddress = params.m_assocShortAddr;
1554
1556
1557 if (params.m_status == MacStatus::SUCCESS)
1558 {
1559 joinConfirmParams.m_status = NwkStatus::SUCCESS;
1560 joinConfirmParams.m_networkAddress = params.m_assocShortAddr;
1561
1562 // Update NWK NIB values
1563 m_nwkNetworkAddress = params.m_assocShortAddr;
1564 m_nwkExtendedPanId = m_joinParams.m_extendedPanId;
1565 m_nwkPanId = m_associateParams.m_coordPanId;
1566
1567 // Update relationship
1568 if (m_associateParams.m_coordAddrMode == lrwpan::AddressMode::EXT_ADDR)
1569 {
1570 if (m_nwkNeighborTable.LookUpEntry(m_associateParams.m_coordExtAddr, entry))
1571 {
1572 entry->SetRelationship(NBR_PARENT);
1573
1574 NS_LOG_DEBUG("[NLME-JOIN.request]:\n "
1575 << "Status: " << joinConfirmParams.m_status << " | PAN ID: 0x"
1576 << std::hex << m_nwkPanId << " | Extended PAN ID: 0x"
1577 << m_nwkExtendedPanId << std::dec);
1578 }
1579 else
1580 {
1581 NS_LOG_ERROR("Entry not found while updating relationship");
1582 }
1583 }
1584 else
1585 {
1586 if (m_nwkNeighborTable.LookUpEntry(m_associateParams.m_coordShortAddr, entry))
1587 {
1588 entry->SetRelationship(NBR_PARENT);
1589
1590 NS_LOG_DEBUG("[NLME-JOIN.request]:\n "
1591 << "Status: " << joinConfirmParams.m_status << " | PAN ID: 0x"
1592 << std::hex << m_nwkPanId << " | Extended PAN ID: 0x"
1593 << m_nwkExtendedPanId << std::dec);
1594 }
1595 else
1596 {
1597 NS_LOG_ERROR("Entry not found while updating relationship");
1598 }
1599 }
1600
1601 // TODO:m_nwkUpdateId
1602 }
1603 else
1604 {
1605 if (params.m_status == MacStatus::FULL_CAPACITY)
1606 {
1607 // Discard neighbor as potential parent
1608 if (m_associateParams.m_coordAddrMode == lrwpan::AddressMode::EXT_ADDR)
1609 {
1610 if (m_nwkNeighborTable.LookUpEntry(m_associateParams.m_coordExtAddr, entry))
1611 {
1612 entry->SetPotentialParent(false);
1613 }
1614 else
1615 {
1616 NS_LOG_ERROR("Neighbor not found when discarding as potential parent");
1617 }
1618 }
1619 else
1620 {
1621 if (m_nwkNeighborTable.LookUpEntry(m_associateParams.m_coordShortAddr, entry))
1622 {
1623 entry->SetPotentialParent(false);
1624 }
1625 else
1626 {
1627 NS_LOG_ERROR("Neighbor not found when discarding as potential parent");
1628 }
1629 }
1630
1631 joinConfirmParams.m_status = NwkStatus::NEIGHBOR_TABLE_FULL;
1632 }
1633 else
1634 {
1635 joinConfirmParams.m_status = GetNwkStatus(params.m_status);
1636 }
1637 }
1638
1640 m_joinParams = {};
1641 m_associateParams = {};
1642
1643 if (!m_nlmeJoinConfirmCallback.IsNull())
1644 {
1645 m_nlmeJoinConfirmCallback(joinConfirmParams);
1646 }
1647 }
1648}
1649
1650void
1652{
1653 NS_LOG_FUNCTION(this);
1654
1655 NwkStatus nwkConfirmStatus;
1656 nwkConfirmStatus = GetNwkStatus(params.m_status);
1657
1658 if (nwkConfirmStatus != NwkStatus::SUCCESS)
1659 {
1660 m_nwkExtendedPanId = 0xffffffffffffffed;
1662 m_nwkPanId = 0xffff;
1663 }
1664
1666 {
1667 NS_LOG_DEBUG("[NLME-NETWORK-FORMATION.request]:\n "
1668 << "Status: " << nwkConfirmStatus << " | PAN ID:" << std::hex << m_nwkPanId
1669 << " | Extended PAN ID: 0x" << m_nwkExtendedPanId << std::dec);
1670
1672 m_netFormParams = {};
1673 m_netFormParamsGen = nullptr;
1674
1676 {
1678 confirmParams.m_status = nwkConfirmStatus;
1680 }
1681 }
1683 {
1684 NS_LOG_DEBUG("[NLME-START-ROUTER.request]:\n "
1685 << "Status: " << nwkConfirmStatus << " | PAN ID: 0x" << std::hex << m_nwkPanId
1686 << " | Extended PAN ID: 0x" << m_nwkExtendedPanId << std::dec);
1687
1688 if (nwkConfirmStatus != NwkStatus::SUCCESS)
1689 {
1693 {
1694 NlmeStartRouterConfirmParams confirmParams;
1695 confirmParams.m_status = nwkConfirmStatus;
1696 m_nlmeStartRouterConfirmCallback(confirmParams);
1697 }
1698 }
1699 else
1700 {
1702 }
1703 }
1704}
1705
1706void
1708{
1709 NS_LOG_FUNCTION(this << params.id);
1710
1712 {
1713 if (params.m_status == MacStatus::SUCCESS &&
1715 {
1716 // Section (3.2.2.5.3 , 6.g)
1717 // Getting this device MAC extended address using MLME-GET
1719 m_mac,
1721 }
1722 else if (params.m_status == MacStatus::SUCCESS &&
1724 {
1725 // Finalize Network Formation (Start network)
1726 MlmeStartRequestParams startParams;
1727 startParams.m_logCh = m_netFormParamsGen->channel;
1728 startParams.m_logChPage = m_netFormParamsGen->page;
1729 startParams.m_PanId = m_netFormParamsGen->panId;
1730 startParams.m_bcnOrd = m_netFormParams.m_beaconOrder;
1731 startParams.m_sfrmOrd = m_netFormParams.m_superFrameOrder;
1732 startParams.m_battLifeExt = m_netFormParams.m_batteryLifeExtension;
1733 startParams.m_coorRealgn = false;
1734 startParams.m_panCoor = true;
1736 }
1737 else if (params.m_status == MacStatus::SUCCESS &&
1739 {
1741 }
1742 else
1743 {
1745 m_netFormParams = {};
1746 m_netFormParamsGen = nullptr;
1747
1749 {
1751 confirmParams.m_status = NwkStatus::STARTUP_FAILURE;
1753 }
1754 }
1755 }
1757 {
1758 if (params.m_status == MacStatus::SUCCESS &&
1760 {
1762 }
1763 else
1764 {
1766
1768 m_joinIndParams = {};
1769
1770 if (!m_nlmeJoinIndicationCallback.IsNull())
1771 {
1772 m_nlmeJoinIndicationCallback(joinIndParams);
1773 }
1774 }
1775 }
1777 {
1778 if (params.m_status == MacStatus::SUCCESS &&
1780 {
1782 }
1783 else if (params.m_status == MacStatus::SUCCESS &&
1785 {
1789 {
1790 NlmeStartRouterConfirmParams confirmParams;
1791 confirmParams.m_status = NwkStatus::SUCCESS;
1792 m_nlmeStartRouterConfirmCallback(confirmParams);
1793 }
1794 }
1795 else
1796 {
1797 NS_LOG_ERROR("Beacon payload update failed during a NLME-START-ROUTER.request");
1798 }
1799 }
1800}
1801
1802void
1805 Ptr<MacPibAttributes> attribute)
1806{
1807 NS_LOG_FUNCTION(this);
1808
1809 // Update the values of attributes in the network layer
1810 if (status == MacStatus::SUCCESS)
1811 {
1813 {
1814 m_nwkIeeeAddress = attribute->macExtendedAddress;
1815 }
1817 {
1818 m_nwkNetworkAddress = attribute->macShortAddress;
1819 }
1821 {
1822 m_nwkPanId = attribute->macPanId;
1823 }
1825 {
1826 m_currentChannel = attribute->pCurrentChannel;
1827 }
1828 }
1829
1831 {
1833 {
1834 // Section (3.2.2.5.3 , 6.g)
1835 // Set nwkExtendedPanId and m_nwkIeeeAddress and nwkPanId
1836 m_nwkExtendedPanId = m_nwkIeeeAddress.ConvertToInt();
1838
1839 // Configure the capability information of the PAN coordinator
1840 CapabilityInformation capaInfo;
1843
1844 // Set Beacon payload size followed by the beacon payload content
1845 // before starting a network
1846 // See Figure 3-37 Establishing a Network
1847 // See also 3.6.7.
1849 }
1850 else
1851 {
1853 m_netFormParams = {};
1854 m_netFormParamsGen = nullptr;
1855
1857 {
1859 confirmParams.m_status = NwkStatus::STARTUP_FAILURE;
1861 }
1862 }
1863 }
1865 {
1867 {
1869 m_mac,
1871 }
1873 {
1874 NlmeJoinConfirmParams joinConfirmParams;
1875 joinConfirmParams.m_channelList = m_joinParams.m_scanChannelList;
1876 joinConfirmParams.m_status = NwkStatus::SUCCESS;
1877 joinConfirmParams.m_networkAddress = m_nwkNetworkAddress;
1878 joinConfirmParams.m_extendedPanId = m_nwkExtendedPanId;
1879 joinConfirmParams.m_enhancedBeacon = false;
1880
1882 m_joinParams = {};
1883
1884 if (!m_nlmeJoinConfirmCallback.IsNull())
1885 {
1886 m_nlmeJoinConfirmCallback(joinConfirmParams);
1887 }
1888 }
1889 }
1891 status == MacStatus::SUCCESS)
1892 {
1894 {
1895 // TODO: MLME-START.request should be issue sequentially to all the interfaces in the
1896 // nwkMacInterfaceTable (currently not supported), for the moment only a single
1897 // interface is supported.
1898 MlmeStartRequestParams startParams;
1899 startParams.m_logCh = m_currentChannel;
1900 startParams.m_logChPage = 0; // In zigbee, only page 0 is supported.
1901 startParams.m_PanId = m_nwkPanId;
1902 startParams.m_bcnOrd = m_startRouterParams.m_beaconOrder;
1903 startParams.m_sfrmOrd = m_startRouterParams.m_superframeOrder;
1904 startParams.m_battLifeExt = m_startRouterParams.m_batteryLifeExt;
1905 startParams.m_coorRealgn = false;
1906 startParams.m_panCoor = false;
1907
1909 }
1910 }
1911}
1912
1913void
1915{
1916 NS_LOG_FUNCTION(this);
1917
1919 MlmeOrphanResponseParams respParams;
1920
1921 if (m_nwkNeighborTable.LookUpEntry(params.m_orphanAddr, entry))
1922 {
1923 respParams.m_assocMember = true;
1924 respParams.m_orphanAddr = params.m_orphanAddr;
1925 respParams.m_shortAddr = entry->GetNwkAddr();
1926
1927 // Temporarily store the NLME-JOIN.indications parameters that will be
1928 // returned after the DIRECT_JOIN process concludes.
1929 // (after MLME-COMM-STATUS.indication is received)
1930 CapabilityInformation capability;
1931 capability.SetReceiverOnWhenIdle(entry->IsRxOnWhenIdle());
1932
1933 if (entry->GetDeviceType() == NwkDeviceType::ZIGBEE_ROUTER)
1934 {
1936 }
1937 else if (entry->GetDeviceType() == NwkDeviceType::ZIGBEE_ENDDEVICE)
1938 {
1940 }
1941 m_joinIndParams.m_capabilityInfo = capability.GetCapability();
1942 m_joinIndParams.m_extendedAddress = params.m_orphanAddr;
1943 m_joinIndParams.m_networkAddress = entry->GetNwkAddr();
1944 m_joinIndParams.m_rejoinNetwork = DIRECT_OR_REJOIN;
1945
1946 NS_LOG_DEBUG("[NLME-JOIN.request]: ["
1947 << params.m_orphanAddr << " | " << entry->GetNwkAddr()
1948 << "] found in neighbor table, responding to orphaned device");
1949
1951 }
1952}
1953
1954void
1956{
1957 NS_LOG_FUNCTION(this);
1958
1959 // Return the results to the next layer of the router or coordinator
1960 // only after a SUCCESSFUL join to the network.
1961 if (params.m_status == MacStatus::SUCCESS)
1962 {
1963 if (params.m_dstExtAddr == m_joinIndParams.m_extendedAddress &&
1964 m_joinIndParams.m_rejoinNetwork == DIRECT_OR_REJOIN)
1965 {
1967 m_joinIndParams = {};
1968
1969 if (!m_nlmeJoinIndicationCallback.IsNull())
1970 {
1971 m_nlmeJoinIndicationCallback(joinIndParams);
1972 }
1973 }
1974 else if (params.m_dstExtAddr == m_joinIndParams.m_extendedAddress &&
1975 m_joinIndParams.m_rejoinNetwork == ASSOCIATION)
1976 {
1979 }
1980 }
1981
1982 // TODO: Handle other situations for MlmeCommStatusIndication according
1983 // to the status and primitive in use.
1984}
1985
1986void
1988{
1989 NS_LOG_FUNCTION(this);
1990
1991 // Zigbee specification Section 3.6.1.3
1992 // Update Neighbor Table with information of the beacon payload
1993 // during a network-discovery
1994
1995 if ((params.m_sdu->GetSize() == 0) ||
1996 (params.m_panDescriptor.m_coorAddrMode != lrwpan::AddressMode::SHORT_ADDR))
1997 {
1998 // The beacon do not contain beacon payload or is for a different network
1999 // stop any further process.
2000 return;
2001 }
2002
2003 ZigbeeBeaconPayload beaconPayload;
2004 params.m_sdu->RemoveHeader(beaconPayload);
2005
2006 if (beaconPayload.GetProtocolId() != 0)
2007 {
2008 return;
2009 }
2010
2011 // TODO: Add a Permit to join, stack profile , update id and capability check
2012
2014 {
2015 // Keep a network descriptor list from the information in the beacon
2016 // to later on pass to the next higher layer when the network-discovery
2017 // process is over (NLME-NETWORK-DISCOVERY.confirm)
2018 NetworkDescriptor descriptor;
2019 descriptor.m_extPanId = beaconPayload.GetExtPanId();
2020 descriptor.m_panId = params.m_panDescriptor.m_coorPanId;
2021 descriptor.m_updateId = 0; // TODO: unknown
2022 descriptor.m_logCh = params.m_panDescriptor.m_logCh;
2023 descriptor.m_stackProfile = static_cast<StackProfile>(beaconPayload.GetStackProfile());
2024 descriptor.m_zigbeeVersion = beaconPayload.GetProtocolId();
2025
2026 SuperframeInformation superframe(params.m_panDescriptor.m_superframeSpec);
2027 descriptor.m_beaconOrder = superframe.GetBeaconOrder();
2028 descriptor.m_superframeOrder = superframe.GetFrameOrder();
2029 descriptor.m_permitJoining = superframe.IsAssocPermit();
2030
2031 descriptor.m_routerCapacity = beaconPayload.GetRouterCapacity();
2032 descriptor.m_endDeviceCapacity = beaconPayload.GetEndDevCapacity();
2033 m_networkDescriptorList.emplace_back(descriptor);
2034
2035 // Keep track of the pan id (16 bits) and the extended PAN id for
2036 // future join (association) procedures.
2037 m_panIdTable.AddEntry(descriptor.m_extPanId, descriptor.m_panId);
2038 // NOTE: In Zigbee all PAN coordinators or routers work with a
2039 // SOURCE short address addressing mode, therefore the PAN descriptors only
2040 // contain the short address.
2041 NS_LOG_DEBUG("Received beacon frame from [" << params.m_panDescriptor.m_coorShortAddr
2042 << "]");
2043 }
2044
2046 if (m_nwkNeighborTable.LookUpEntry(params.m_panDescriptor.m_coorShortAddr, entry))
2047 {
2048 // Update Neighbor table with the info of the received beacon
2049
2050 entry->SetNwkAddr(params.m_panDescriptor.m_coorShortAddr);
2051 entry->SetTimeoutCounter(Seconds(15728640));
2053 entry->SetLqi(params.m_panDescriptor.m_linkQuality);
2054 entry->SetOutgoingCost(GetLQINonLinearValue(params.m_panDescriptor.m_linkQuality));
2055 // m_nwkNeighborTable.Update(params.m_panDescriptor.m_coorShortAddr, entry);
2056 // TODO: Update other fields if necessary and
2057 // Additional and optional fields.
2058 }
2059 else
2060 {
2061 // Add a new entry to the neighbor table, information comes from
2062 // the MAC PAN descriptor and the beacon payload received.
2063 NwkDeviceType devType;
2064 if (params.m_panDescriptor.m_coorShortAddr == Mac16Address("00:00"))
2065 {
2067 }
2068 else
2069 {
2071 }
2072
2073 // Create neighbor table entry with the basic fields
2074 Ptr<NeighborTableEntry> newEntry =
2075 Create<NeighborTableEntry>(Mac64Address("FF:FF:FF:FF:FF:FF:FF:FF"),
2076 params.m_panDescriptor.m_coorShortAddr,
2077 devType,
2078 true,
2079 0,
2080 Seconds(15728640),
2082 NBR_NONE,
2083 0,
2084 params.m_panDescriptor.m_linkQuality,
2085 GetLQINonLinearValue(params.m_panDescriptor.m_linkQuality),
2086 0,
2087 false,
2088 0);
2089
2090 // If necessary add information to the
2091 // additional and optional fields. Currently only 2 additional fields are added:
2092 newEntry->SetExtPanId(beaconPayload.GetExtPanId());
2093 newEntry->SetLogicalCh(params.m_panDescriptor.m_logCh);
2094
2095 m_nwkNeighborTable.AddEntry(newEntry);
2096 }
2097}
2098
2099void
2101{
2102 NS_LOG_FUNCTION(this);
2103
2104 // Joining Procedure through Association (Parent procedure)
2105 // Zigbee Specification 3.6.1.4.1
2106
2107 CapabilityInformation receivedCapability(params.capabilityInfo);
2108 auto devType = static_cast<NwkDeviceType>(receivedCapability.GetDeviceType());
2109
2111 if (m_nwkNeighborTable.LookUpEntry(params.m_extDevAddr, entry))
2112 {
2113 if (entry->GetDeviceType() == devType)
2114 {
2115 MlmeAssociateResponseParams responseParams;
2116 responseParams.m_status = MacStatus::SUCCESS;
2117 responseParams.m_assocShortAddr = entry->GetNwkAddr();
2118 responseParams.m_extDevAddr = entry->GetExtAddr();
2120 }
2121 else
2122 {
2123 m_nwkNeighborTable.Delete(params.m_extDevAddr);
2125 }
2126 }
2127 else
2128 {
2129 // Device currently do not exist in coordinator,
2130 // allocate an address and add to neighbor table.
2131
2132 Mac16Address allocatedAddr;
2133 if (receivedCapability.IsAllocateAddrOn())
2134 {
2135 allocatedAddr = AllocateNetworkAddress();
2136 }
2137 else
2138 {
2139 // The device is associated but it will only use its
2140 // extended address (EUI-64 also known as IEEE Address)
2141 allocatedAddr = Mac16Address("FF:FE");
2142 }
2143
2144 CapabilityInformation capability(params.capabilityInfo);
2145
2146 Ptr<NeighborTableEntry> newEntry =
2147 Create<NeighborTableEntry>(params.m_extDevAddr,
2148 allocatedAddr,
2149 devType,
2150 capability.IsReceiverOnWhenIdle(),
2151 0,
2152 Seconds(15728640),
2154 NBR_CHILD,
2155 0,
2156 params.lqi,
2157 0,
2158 0,
2159 true,
2160 0);
2161 // Optional parameters
2162 newEntry->SetExtPanId(m_nwkExtendedPanId);
2163
2164 MlmeAssociateResponseParams responseParams;
2165 responseParams.m_extDevAddr = params.m_extDevAddr;
2166
2167 if (m_nwkNeighborTable.AddEntry(newEntry))
2168 {
2169 responseParams.m_status = MacStatus::SUCCESS;
2170 responseParams.m_assocShortAddr = allocatedAddr;
2171
2172 // Temporarily store the NLME-JOIN.indications parameters that will be
2173 // returned after the association process concludes.
2174 // (after MLME-COMM-STATUS.indication received and beacon payload updated)
2175 m_joinIndParams.m_capabilityInfo = receivedCapability.GetCapability();
2176 m_joinIndParams.m_extendedAddress = params.m_extDevAddr;
2177 m_joinIndParams.m_networkAddress = allocatedAddr;
2178 m_joinIndParams.m_rejoinNetwork = ASSOCIATION;
2179 }
2180 else
2181 {
2182 responseParams.m_status = MacStatus::FULL_CAPACITY;
2183 responseParams.m_assocShortAddr = Mac16Address("FF:FF");
2184 }
2185
2186 NS_LOG_DEBUG("\n "
2187 << "Storing an Associate response command with the allocated address "
2188 << "[" << responseParams.m_assocShortAddr << "]");
2189
2191 }
2192}
2193
2194void
2196{
2197 NS_LOG_FUNCTION(this << packet);
2198
2199 if (params.m_dstAddr == m_nwkNetworkAddress)
2200 {
2201 NS_LOG_WARN("The source and the destination of the route request are the same!");
2202 return;
2203 }
2204
2205 // Zigbee specification r22.1.0, Section 3.2.1.1.3 and Section 3.6.2.1
2206 // check that we are associated
2207 if (m_nwkNetworkAddress == "FF:FF")
2208 {
2209 NS_LOG_WARN("Cannot send data, the device is not currently associated");
2210
2211 if (!m_nldeDataConfirmCallback.IsNull())
2212 {
2213 NldeDataConfirmParams confirmParams;
2214 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2215 confirmParams.m_txTime = Simulator::Now();
2216 confirmParams.m_nsduHandle = params.m_nsduHandle;
2217 m_nldeDataConfirmCallback(confirmParams);
2218 }
2219 return;
2220 }
2221
2222 // Constructing the NPDU (Zigbee specification r22.1.0, Section 3.2.1.1.3 and Section 3.6.2.1)
2223 ZigbeeNwkHeader nwkHeader;
2224 nwkHeader.SetFrameType(DATA);
2225 nwkHeader.SetProtocolVer(3);
2226 nwkHeader.SetDiscoverRoute(static_cast<DiscoverRouteType>(params.m_discoverRoute));
2227 nwkHeader.SetDstAddr(params.m_dstAddr);
2228
2229 if (params.m_useAlias && params.m_dstAddrMode != AddressMode::MCST)
2230 {
2231 nwkHeader.SetSrcAddr(params.m_aliasSrcAddr);
2232 nwkHeader.SetSeqNum(params.m_aliasSeqNumber.GetValue());
2233 }
2234 else
2235 {
2237 nwkHeader.SetSeqNum(m_nwkSequenceNumber.GetValue());
2238 }
2239
2240 if (params.m_radius == 0)
2241 {
2242 nwkHeader.SetRadius(m_nwkMaxDepth * 2);
2243 }
2244 else
2245 {
2246 nwkHeader.SetRadius(params.m_radius);
2247 }
2248
2249 if (params.m_securityEnable)
2250 {
2251 // TODO: Secure processing (Section 3.6.2.1)
2252 NS_ABORT_MSG("Security processing is currently not supported");
2253 }
2254
2255 // Check the current device capabilities
2256 CapabilityInformation capability;
2258
2259 if (capability.GetDeviceType() == MacDeviceType::ENDDEVICE)
2260 {
2261 nwkHeader.SetEndDeviceInitiator();
2262 }
2263
2264 // CASE 1: The destination is a multicast address (Group address)
2265 // See Sections 3.6.6.2 and 3.2.1.1.3
2266 if (params.m_dstAddrMode == AddressMode::MCST)
2267 {
2268 if (nwkHeader.GetEndDeviceInitiator())
2269 {
2270 NS_LOG_WARN("EndDevices cannot send multicast packets, dropping the packet");
2271 if (!m_nldeDataConfirmCallback.IsNull())
2272 {
2273 NldeDataConfirmParams confirmParams;
2274 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2275 confirmParams.m_txTime = Simulator::Now();
2276 confirmParams.m_nsduHandle = params.m_nsduHandle;
2277 m_nldeDataConfirmCallback(confirmParams);
2278 }
2279 return;
2280 // TODO: Add trace here.
2281 }
2282
2283 nwkHeader.SetMulticast();
2284 nwkHeader.SetNonMemberRadius(params.m_nonMemberRadius);
2285 nwkHeader.SetMaxNonMemberRadius(params.m_nonMemberRadius);
2286
2287 // Check if the current device is member of the multicast Group (dstAddr)
2288 bool groupMember = m_nwkGroupIdTable->IsGroupMember(params.m_dstAddr.ConvertToInt());
2289
2290 if (groupMember)
2291 {
2293
2294 // Add an entry to the Broadcast Transaction Table (BTT)
2296 nwkHeader.GetSrcAddr(),
2297 nwkHeader.GetSeqNum(),
2299
2300 if (!m_btt.AddEntry(btr))
2301 {
2302 NS_LOG_DEBUG("Broadcast Transaction Table is full, dropping the packet");
2303 // TODO: Add multicast packet trace here
2304 if (!m_nldeDataConfirmCallback.IsNull())
2305 {
2306 NldeDataConfirmParams confirmParams;
2307 confirmParams.m_status = NwkStatus::BT_TABLE_FULL;
2308 confirmParams.m_txTime = Simulator::Now();
2309 confirmParams.m_nsduHandle = params.m_nsduHandle;
2310 m_nldeDataConfirmCallback(confirmParams);
2311 }
2312 return;
2313 }
2314 }
2315 else
2316 {
2318 }
2319
2320 packet->AddHeader(nwkHeader);
2321
2322 if (groupMember)
2323 {
2324 // See 3.6.6.2.1: Group Members initiate the transmission
2325 // using a broadcast (MAC level)
2326 SendDataBcst(packet, params.m_nsduHandle);
2327 }
2328 else
2329 {
2330 // See 3.6.6.2.2: Non-Group member initiate the transmission
2331 // using a unicast (MAC level) and search for the next hop
2332 // in its routing table if necessary.
2333 SendDataUcst(packet, params.m_nsduHandle);
2334 }
2335 return;
2336 }
2337
2338 // CASE 2: The destination is a unicast address, a broadcast address
2339 // or has no address (Many to one routing)
2340
2341 packet->AddHeader(nwkHeader);
2342
2343 if (capability.GetDeviceType() == MacDeviceType::ROUTER)
2344 {
2345 if (IsBroadcastAddress(params.m_dstAddr))
2346 {
2347 // The destination is BROADCAST (See 3.6.5)
2348 SendDataBcst(packet, params.m_nsduHandle);
2349 }
2350 else
2351 {
2352 // The destination is UNICAST (See 3.6.3.3)
2353 SendDataUcst(packet, params.m_nsduHandle);
2354 }
2355 }
2356 else
2357 {
2358 // The device is an END DEVICE
2359 // direct message to its Parent device (Coordinator)
2361 if (m_nwkNeighborTable.GetParent(entry))
2362 {
2363 // Buffer a copy of the DATA packet that will be transmitted
2364 // for handling after transmission (i.e. NSDE-DATA.confirm)
2365 BufferTxPkt(packet->Copy(), m_macHandle.GetValue(), params.m_nsduHandle);
2366
2367 McpsDataRequestParams mcpsDataparams;
2368 mcpsDataparams.m_txOptions = 0x01; // Acknowledment on.
2369 mcpsDataparams.m_dstPanId = m_nwkPanId;
2370 mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
2371 mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
2372 mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
2373 mcpsDataparams.m_dstAddr = entry->GetNwkAddr();
2374 m_macHandle++;
2376 }
2377 else
2378 {
2379 // Section 3.6.3.7.1
2380 // Link failure with Parent device
2381 // TODO
2382 /*
2383 if (!m_nlmeNwkStatusIndicationCallback.IsNull())
2384 {
2385 NlmeNetworkStatusIndication indicationParams;
2386
2387 m_networkStatusCode = PARENT_LINK_FAILURE;
2388 m_nlmeNwkStatusIndicationCallback(confirmParams);
2389 }
2390 */
2391 }
2392 }
2394}
2395
2396void
2398{
2399 NS_LOG_FUNCTION(this);
2400
2401 NS_ASSERT_MSG(m_netFormParams.m_scanChannelList.channelPageCount ==
2402 m_netFormParams.m_scanChannelList.channelsField.size(),
2403 "channelsField and its channelPageCount size do not match "
2404 "in networkFormationParams");
2405
2407 {
2409 m_netFormParams = {};
2410 m_netFormParamsGen = nullptr;
2411
2413 {
2415 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2417 }
2418 return;
2419 }
2420
2421 if (params.m_distributedNetwork)
2422 {
2423 // Zigbee Specification r22.1.0, 3.2.2.5 , 3)
2424 // Verify Distributed Network Address is in a valid range.
2425 // TODO: Verify the address is not > 0xFFF7
2426 if (params.m_distributedNetwork == Mac16Address("00:00"))
2427 {
2429 m_netFormParams = {};
2430 m_netFormParamsGen = nullptr;
2431
2433 {
2435 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2437 }
2438 return;
2439 }
2440 }
2441
2442 // 4. On receipt of this primitive the NLME shall first validate the
2443 // ChannelListStructure parameter according to section 3.2.2.2.2.
2444 // (if nwkMacInterfaceTable support is added)
2445 // If validation fails the NLME-NETWORK-FORMATION.confirm
2446 // primitive shall be issued with a Status parameter set to INVALID_PARAMETER.
2447
2448 if (params.m_scanChannelList.channelPageCount != 1)
2449 {
2450 NS_FATAL_ERROR("Multi page scanning not supported");
2451 }
2452
2453 // Only page 0 is supported (O-QPSK 250 kbps)
2454 // Take 5 MSB bits: b27-b31 to check the page
2455 uint32_t page = (params.m_scanChannelList.channelsField[0] >> 27) & (0x01F);
2456
2457 if (page != 0)
2458 {
2459 NS_FATAL_ERROR("PHY band not supported (Only page 0 is supported)");
2460 }
2461
2462 uint8_t channelsCount = 0;
2463 for (int i = 11; i <= 26; i++)
2464 {
2465 channelsCount += (params.m_scanChannelList.channelsField[0] >> i) & 1;
2466 }
2467
2469 m_netFormParams = params;
2470
2471 if (channelsCount == 1)
2472 {
2473 // There is only 1 channel, skip energy scan and go directly to
2474 // active scan instead
2475 MlmeScanRequestParams mlmeParams;
2476 mlmeParams.m_chPage = page;
2477 mlmeParams.m_scanChannels = params.m_scanChannelList.channelsField[0];
2478 mlmeParams.m_scanDuration = params.m_scanDuration;
2479 mlmeParams.m_scanType = MLMESCAN_ACTIVE;
2481 }
2482 else if (channelsCount > 1)
2483 {
2484 MlmeScanRequestParams mlmeParams;
2485 mlmeParams.m_chPage = page;
2486 mlmeParams.m_scanChannels = params.m_scanChannelList.channelsField[0];
2487 mlmeParams.m_scanDuration = params.m_scanDuration;
2488 mlmeParams.m_scanType = MLMESCAN_ED;
2490 }
2491}
2492
2493void
2495{
2496 NS_LOG_FUNCTION(this);
2497
2498 if (params.m_dstAddr == m_nwkNetworkAddress && params.m_dstAddrMode == UCST_BCST)
2499 {
2500 NS_FATAL_ERROR("The source and the destination of the route request are the same!");
2501 return;
2502 }
2503
2504 // (See 3.2.2.33.3)
2505 // - Check the device has routing capacity
2506 // - Check the device dstAddrMode != NO_ADDRESS && dst != Broadcast address
2507 if (params.m_dstAddrMode != NO_ADDRESS && IsBroadcastAddress(params.m_dstAddr))
2508 {
2510 {
2511 NlmeRouteDiscoveryConfirmParams confirmParams;
2512 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2514 }
2515
2516 NS_LOG_WARN("The destination address is a broadcast address, or the destination "
2517 "address mode is NO_ADDRESS, cannot send route discovery request");
2518
2519 return;
2520 }
2521
2522 CapabilityInformation capability;
2524 if (capability.GetDeviceType() != ROUTER && params.m_dstAddrMode != NO_ADDRESS)
2525 {
2527 {
2528 NlmeRouteDiscoveryConfirmParams confirmParams;
2529 confirmParams.m_status = NwkStatus::ROUTE_ERROR;
2532 }
2533
2534 NS_LOG_WARN("Device does not have routing capacity, cannot send route discovery request");
2535
2536 return;
2537 }
2538
2540
2541 ZigbeeNwkHeader nwkHeader;
2542 nwkHeader.SetFrameType(NWK_COMMAND);
2545 // See r22.1.0, Table 3-69
2546 // Set destination to broadcast (all routers and coordinator)
2547 nwkHeader.SetDstAddr(Mac16Address("FF:FC"));
2549 nwkHeader.SetSeqNum(m_nwkSequenceNumber.GetValue());
2550
2552 payload.SetRouteReqId(m_routeRequestId.GetValue());
2553 payload.SetPathCost(0);
2554
2555 if (params.m_dstAddrMode == AddressMode::UCST_BCST || params.m_dstAddrMode == AddressMode::MCST)
2556 {
2557 // Set the rest of the nwkHeader and command payload (RREQ) parameters
2558 // as described in Zigbee specification r22.1.0, Section 3.2.2.33.3
2559
2560 if (params.m_radius == 0)
2561 {
2562 nwkHeader.SetRadius(m_nwkMaxDepth * 2);
2563 }
2564 else
2565 {
2566 nwkHeader.SetRadius(params.m_radius);
2567 }
2568
2569 payload.SetDstAddr(params.m_dstAddr);
2570
2571 if (params.m_dstAddrMode == AddressMode::MCST)
2572 {
2573 // Set the Multicast flag and proceed with the
2574 // multicast destination route discovery
2575 payload.SetMulticastField(true);
2576 }
2577
2578 Mac16Address nextHop;
2579 RouteDiscoveryStatus routeStatus =
2580 FindNextHop(m_nwkNetworkAddress, 0, nwkHeader, payload, nextHop);
2581
2582 if (routeStatus == ROUTE_FOUND)
2583 {
2585 {
2586 NlmeRouteDiscoveryConfirmParams confirmParams;
2587 confirmParams.m_status = NwkStatus::SUCCESS;
2589 }
2590 }
2591 else if (routeStatus == ROUTE_NOT_FOUND)
2592 {
2593 // Route not found. Route marked as DISCOVER UNDERWAY,
2594 // we initiate route discovery.
2597 this,
2598 nwkHeader,
2599 payload,
2601
2604 }
2605 }
2606 else if (params.m_dstAddrMode == NO_ADDRESS)
2607 {
2608 // Many-to-one route discovery.
2609 // (See Last paragraph of Zigbee Specification, Section 3.6.3.5.1)
2610 m_nwkIsConcentrator = true;
2611
2613
2614 payload.SetDstAddr(Mac16Address("FF:FF"));
2615 if (params.m_noRouteCache)
2616 {
2618 }
2619 else
2620 {
2622 }
2623
2624 RouteDiscoveryStatus routeStatus =
2625 ProcessManyToOneRoute(m_nwkNetworkAddress, 0, nwkHeader, payload);
2626
2627 if (routeStatus == MANY_TO_ONE_ROUTE || routeStatus == ROUTE_UPDATED)
2628 {
2629 // TODO if nwkConcentratorDiscoveryTime != 0, schedule
2630 // RREQ every nwkConcentratorDiscovery time.
2631
2634 this,
2635 nwkHeader,
2636 payload,
2637 0);
2640 }
2641 }
2642}
2643
2644void
2646{
2647 NS_LOG_FUNCTION(this);
2648
2649 if (params.m_scanDuration > 14)
2650 {
2651 NS_FATAL_ERROR("Scan duration must be an int between 0 and 14");
2652 }
2653
2654 if (params.m_scanChannelList.channelPageCount != params.m_scanChannelList.channelsField.size())
2655 {
2656 NS_FATAL_ERROR("In scanChannelList parameter, channelPageCount "
2657 "and the channelsField structure size does not match");
2658 }
2659
2660 // TODO: Add support to scan other MAC interfaces, for the moment
2661 // only a single interface and only Page 0 is supported (PHY O-QPSK 250 kbps)
2662
2663 if (params.m_scanChannelList.channelsField.size() != 1)
2664 {
2665 NS_FATAL_ERROR("Only a single MAC interface supported");
2666 }
2667
2668 uint8_t page = (params.m_scanChannelList.channelsField[0] >> 27) & (0x01F);
2669 if (page != 0)
2670 {
2671 NS_FATAL_ERROR("Only Page 0 (O-QPSK 250 kbps) is supported.");
2672 }
2673
2675
2676 MlmeScanRequestParams scanParams;
2677 scanParams.m_chPage = 0; // Only page 0 is supported.
2678 scanParams.m_scanChannels = params.m_scanChannelList.channelsField[0];
2679 scanParams.m_scanDuration = params.m_scanDuration;
2680 scanParams.m_scanType = MLMESCAN_ACTIVE;
2681
2682 NS_LOG_DEBUG("Active scanning started, "
2683 << " on page " << page << " and channels 0x" << std::hex
2684 << params.m_scanChannelList.channelsField[0] << std::dec);
2685
2687}
2688
2689void
2691{
2692 NS_LOG_FUNCTION(this);
2693
2694 // TODO: Check the device is router or coordinator, send invalid_request
2695 // status otherwise. See 3.6.1.4.3.
2696
2698 if (m_nwkNeighborTable.LookUpEntry(params.m_deviceAddr, entry))
2699 {
2700 NS_LOG_WARN("[NLME-DIRECT-JOIN.request]: "
2701 "Device already present in neighbor table. ");
2702
2703 if (!m_nlmeDirectJoinConfirmCallback.IsNull())
2704 {
2705 NlmeDirectJoinConfirmParams confirmParams;
2706 confirmParams.m_status = NwkStatus::ALREADY_PRESENT;
2707 confirmParams.m_deviceAddr = params.m_deviceAddr;
2708 m_nlmeDirectJoinConfirmCallback(confirmParams);
2709 }
2710 }
2711 else
2712 {
2713 CapabilityInformation capaInfo;
2714 capaInfo.SetCapability(params.m_capabilityInfo);
2715
2716 Mac16Address allocatedAddr;
2717 if (capaInfo.IsAllocateAddrOn())
2718 {
2719 allocatedAddr = AllocateNetworkAddress();
2720 }
2721 else
2722 {
2723 // The device is associated but it will only use its
2724 // extended address (EUI-64 also known as IEEE Address)
2725 allocatedAddr = Mac16Address("FF:FE");
2726 }
2727
2728 NwkDeviceType devType;
2729 if (capaInfo.GetDeviceType() == MacDeviceType::ROUTER)
2730 {
2732 }
2733 else
2734 {
2736 }
2737
2738 Ptr<NeighborTableEntry> newEntry =
2739 Create<NeighborTableEntry>(params.m_deviceAddr,
2740 allocatedAddr,
2741 devType,
2742 capaInfo.IsReceiverOnWhenIdle(),
2743 0,
2744 Seconds(15728640),
2746 NBR_CHILD,
2747 0,
2748 255,
2749 0,
2750 0,
2751 true,
2752 0);
2753
2754 NlmeDirectJoinConfirmParams confirmParams;
2755
2756 if (m_nwkNeighborTable.AddEntry(newEntry))
2757 {
2758 NS_LOG_DEBUG("Device added to neighbor table (" << m_nwkNeighborTable.GetSize()
2759 << ") with address [" << allocatedAddr
2760 << " | " << params.m_deviceAddr << "]");
2761 if (!m_nlmeDirectJoinConfirmCallback.IsNull())
2762 {
2763 confirmParams.m_status = NwkStatus::SUCCESS;
2764 confirmParams.m_deviceAddr = params.m_deviceAddr;
2765 m_nlmeDirectJoinConfirmCallback(confirmParams);
2766 }
2767 }
2768 else
2769 {
2770 NS_LOG_WARN("Error, neighbor table is full");
2771 if (!m_nlmeDirectJoinConfirmCallback.IsNull())
2772 {
2774 confirmParams.m_deviceAddr = params.m_deviceAddr;
2775 m_nlmeDirectJoinConfirmCallback(confirmParams);
2776 }
2777 }
2778 }
2779}
2780
2781void
2783{
2784 NS_LOG_FUNCTION(this);
2785
2786 if (params.m_scanDuration > 14)
2787 {
2788 NS_FATAL_ERROR("Scan duration must be an int between 0 and 14");
2789 }
2790
2791 if (params.m_scanChannelList.channelPageCount != params.m_scanChannelList.channelsField.size())
2792 {
2793 NS_FATAL_ERROR("In scanChannelList parameter, channelPageCount "
2794 "and the channelsField structure size does not match");
2795 }
2796
2797 // TODO: Add support to scan other MAC interfaces, for the moment
2798 // only a single interface and only Page 0 is supported (PHY O-QPSK 250 kbps)
2799
2800 // TODO: Only devices who have not join another network can call JOIN.
2801
2802 if (params.m_scanChannelList.channelsField.size() != 1)
2803 {
2804 NS_FATAL_ERROR("Only a single MAC interface supported");
2805 }
2806
2807 uint8_t page = (params.m_scanChannelList.channelsField[0] >> 27) & (0x01F);
2808 if (page != 0)
2809 {
2810 NS_FATAL_ERROR("Only Page 0 (O-QPSK 250 kbps) is supported.");
2811 }
2812
2814 m_joinParams = params;
2815
2816 if (params.m_rejoinNetwork == DIRECT_OR_REJOIN)
2817 {
2818 // Zigbee specification r22.1.0 Section 3.6.1.4.3.1,
2819 // Child procedure for joining or re-joining a network through
2820 // orphaning (DIRECT JOIN procedure).
2821
2822 MlmeScanRequestParams scanParams;
2823 scanParams.m_chPage = page;
2824 scanParams.m_scanChannels = params.m_scanChannelList.channelsField[0];
2825
2826 // Note: Scan duration is fixed to a macResponseWaitTime in an Orphan scan
2827 // (i.e. It does not use the scanDuration parameter)
2828 scanParams.m_scanType = MLMESCAN_ORPHAN;
2829 NS_LOG_DEBUG("Orphan scanning started, sending orphan notifications on page "
2830 << page << " and channels " << std::hex
2831 << params.m_scanChannelList.channelsField[0]);
2832
2834 }
2835 else if (params.m_rejoinNetwork == ASSOCIATION)
2836 {
2837 // Check if we have the MAC pan id info recorded during the discovery process
2838 uint16_t panId;
2839 if (!m_panIdTable.GetEntry(params.m_extendedPanId, panId))
2840 {
2841 NS_LOG_ERROR("Error PAN id of neighbor device not found");
2842 }
2843
2844 // Zigbee specification r22.1.0 Section 3.6.1.4.1
2845 // Child procedure for joining a network through ASSOCIATION.
2846
2847 NlmeJoinConfirmParams joinConfirmParams;
2848 Ptr<NeighborTableEntry> bestParentEntry;
2849
2850 if (m_nwkNeighborTable.LookUpForBestParent(params.m_extendedPanId, bestParentEntry))
2851 {
2852 MlmeAssociateRequestParams assocParams;
2853 m_nwkCapabilityInformation = params.m_capabilityInfo;
2854
2855 assocParams.m_chNum = bestParentEntry->GetLogicalCh();
2856 assocParams.m_chPage = 0; // Zigbee assumes Page is always 0
2857 assocParams.m_capabilityInfo = params.m_capabilityInfo;
2858 assocParams.m_coordPanId = panId;
2859
2860 if (bestParentEntry->GetNwkAddr() != Mac16Address("FF:FE"))
2861 {
2863 assocParams.m_coordShortAddr = bestParentEntry->GetNwkAddr();
2864 NS_LOG_DEBUG("\n "
2865 << "Send Association Request [" << bestParentEntry->GetNwkAddr()
2866 << "] | PAN ID: " << std::hex << "0x" << panId
2867 << " | Extended PAN ID: 0x" << params.m_extendedPanId << std::dec);
2868 }
2869 else
2870 {
2872 assocParams.m_coordExtAddr = bestParentEntry->GetExtAddr();
2873 NS_LOG_DEBUG("Send Assoc. Req. to [" << bestParentEntry->GetNwkAddr()
2874 << "] in \nPAN id and Ext PAN id: " << std::hex
2875 << "(0x" << panId << " | 0x"
2876 << params.m_extendedPanId << ")" << std::dec);
2877 }
2878
2880 m_nwkCapabilityInformation = params.m_capabilityInfo;
2881
2882 // Temporarily store MLME-ASSOCIATE.request parameters until the JOIN process concludes
2883 m_associateParams = assocParams;
2884
2886 }
2887 else
2888 {
2890 m_joinParams = {};
2891
2892 if (!m_nlmeJoinConfirmCallback.IsNull())
2893 {
2894 joinConfirmParams.m_extendedPanId = params.m_extendedPanId;
2895 joinConfirmParams.m_networkAddress = Mac16Address("FF:FF");
2896 joinConfirmParams.m_enhancedBeacon = false;
2897 joinConfirmParams.m_macInterfaceIndex = 0;
2898 joinConfirmParams.m_status = NwkStatus::NOT_PERMITED;
2899 m_nlmeJoinConfirmCallback(joinConfirmParams);
2900 }
2901 }
2902 }
2903 else
2904 {
2905 NS_FATAL_ERROR("Joining method not supported");
2906 }
2907}
2908
2909void
2911{
2912 NS_LOG_FUNCTION(this);
2913
2914 NS_ASSERT_MSG(params.m_beaconOrder == 15, "Beacon mode not supported for zigbee");
2915 NS_ASSERT_MSG(params.m_superframeOrder == 15, "Beacon mode not supported for zigbee");
2916
2917 CapabilityInformation capability;
2919
2920 if (capability.GetDeviceType() != MacDeviceType::ROUTER)
2921 {
2925 {
2926 NlmeStartRouterConfirmParams confirmParams;
2927 confirmParams.m_status = NwkStatus::INVALID_REQUEST;
2928 m_nlmeStartRouterConfirmCallback(confirmParams);
2929 }
2930 NS_LOG_ERROR("This device is not a Zigbee Router or is not joined to this network");
2931 }
2932 else
2933 {
2935 // store the NLME-START-ROUTER.request params while request the current channel
2936 m_startRouterParams = params;
2937 // request an update of the current channel in use in the PHY
2939 m_mac,
2941 }
2942}
2943
2944void
2949
2950void
2955
2956void
2961
2962void
2967
2968void
2973
2974void
2979
2980void
2985
2986void
2991
2992void
2997
2998void
3000{
3001 // TODO : PurgeTxQueue();
3003 {
3004 ZigbeeNwkHeader peekedNwkHeader;
3005 p->PeekHeader(peekedNwkHeader);
3006
3007 Ptr<PendingTxPkt> pendingTxPkt = Create<PendingTxPkt>();
3008 pendingTxPkt->dstAddr = peekedNwkHeader.GetDstAddr();
3009 pendingTxPkt->nsduHandle = nsduHandle;
3010 pendingTxPkt->txPkt = p;
3011 // TODO: expiration time here
3012 m_pendingTxQueue.emplace_back(pendingTxPkt);
3013 // TODO: pending trace here
3014 }
3015 else
3016 {
3017 // TODO: Drop trace here
3018 }
3019}
3020
3021bool
3023{
3024 // TODO : PurgeTxQueue();
3025
3026 /* std::erase_if(m_pendingTxQueue, [&dst](Ptr<PendingTxPkt> pkt) {
3027 return pkt->dstAddr == dst;
3028 });*/
3029
3030 for (auto iter = m_pendingTxQueue.begin(); iter != m_pendingTxQueue.end(); iter++)
3031 {
3032 if ((*iter)->dstAddr == dst)
3033 {
3034 *entry = **iter;
3035 // TODO: Dequeue trace if needed here.
3036 m_pendingTxQueue.erase(iter);
3037 return true;
3038 }
3039 }
3040 return false;
3041}
3042
3043void
3045{
3046 for (auto element : m_pendingTxQueue)
3047 {
3048 element = nullptr;
3049 }
3050 m_pendingTxQueue.clear();
3051}
3052
3053void
3054ZigbeeNwk::BufferTxPkt(Ptr<Packet> p, uint8_t macHandle, uint8_t nwkHandle)
3055{
3056 if (m_txBuffer.size() < m_txBufferMaxSize)
3057 {
3058 Ptr<TxPkt> txPkt = Create<TxPkt>();
3059 txPkt->macHandle = macHandle;
3060 txPkt->nwkHandle = nwkHandle;
3061 txPkt->txPkt = p;
3062 m_txBuffer.emplace_back(txPkt);
3063 }
3064 else
3065 {
3066 NS_LOG_DEBUG("Zigbee Tx Buffer is full, packet dropped.");
3067 // TODO : Drop trace for TX buffer
3068 }
3069}
3070
3071bool
3072ZigbeeNwk::RetrieveTxPkt(uint8_t macHandle, Ptr<TxPkt>& txPkt)
3073{
3074 for (auto bufferedPkt : m_txBuffer)
3075 {
3076 if (bufferedPkt->macHandle == macHandle)
3077 {
3078 txPkt = bufferedPkt;
3079
3080 std::erase_if(m_txBuffer,
3081 [&macHandle](Ptr<TxPkt> pkt) { return pkt->macHandle == macHandle; });
3082
3083 return true;
3084 }
3085 }
3086 return false;
3087}
3088
3089void
3091{
3092 for (auto element : m_txBuffer)
3093 {
3094 element = nullptr;
3095 }
3096 m_txBuffer.clear();
3097}
3098
3101{
3102 return static_cast<NwkStatus>(macStatus);
3103}
3104
3107{
3108 NS_LOG_FUNCTION(this);
3109
3111 {
3112 NS_FATAL_ERROR("Distributed allocation not supported");
3113 return Mac16Address("FF:FF");
3114 }
3115 else if (m_nwkAddrAlloc == STOCHASTIC_ALLOC)
3116 {
3117 // See nwkNetworkAddress valid range Zigbee specification r22.1.0, 3.5.2
3118 // Valid values in the Zigbee specification goes from 1 to 0xFFF7,
3119 // However, the range 0x8000 to 0x9FFF is used for multicast in other networks
3120 // (i.e. IPV6 over IEEE 802.15.4) for this reason, we avoid this range as well.
3121 // See RFC 4944, Section 9
3122 uint16_t rndValue = m_uniformRandomVariable->GetInteger(1, 0x7FFF);
3123 uint16_t rndValue2 = m_uniformRandomVariable->GetInteger(0xA000, 0xFFF7);
3124 uint16_t rndValue3 = m_uniformRandomVariable->GetInteger(1, 2);
3125
3126 Mac16Address allocAddr;
3127 if (rndValue3 == 1)
3128 {
3129 allocAddr = Mac16Address(rndValue);
3130 }
3131 else
3132 {
3133 allocAddr = Mac16Address(rndValue2);
3134 }
3135 return allocAddr;
3136 }
3137 else
3138 {
3139 NS_FATAL_ERROR("Address allocation method not supported");
3140 return Mac16Address("FF:FF");
3141 }
3142}
3143
3144uint8_t
3146{
3147 uint8_t mappedValue;
3148
3149 if (lqi > 50)
3150 {
3151 mappedValue = 1;
3152 }
3153 else if ((lqi <= 50) && (lqi > 45))
3154 {
3155 mappedValue = 2;
3156 }
3157 else if ((lqi <= 45) && (lqi > 40))
3158 {
3159 mappedValue = 3;
3160 }
3161 else if ((lqi <= 40) && (lqi > 38))
3162 {
3163 mappedValue = 4;
3164 }
3165 else if ((lqi <= 38) && (lqi > 35))
3166 {
3167 mappedValue = 5;
3168 }
3169 else if ((lqi <= 35) && (lqi > 24))
3170 {
3171 mappedValue = 6;
3172 }
3173 else
3174 {
3175 mappedValue = 7;
3176 }
3177
3178 return mappedValue;
3179}
3180
3181uint8_t
3182ZigbeeNwk::GetLinkCost(uint8_t lqi) const
3183{
3184 NS_LOG_FUNCTION(this);
3185
3187 {
3188 // Hop count based. Report constant value
3189 return 7;
3190 }
3191 else
3192 {
3193 // Based on non-linear mapping of LQI
3194 return GetLQINonLinearValue(lqi);
3195 }
3196}
3197
3198void
3201 uint8_t rreqRetries)
3202{
3203 NS_LOG_FUNCTION(this);
3204
3205 ZigbeePayloadType payloadType(ROUTE_REQ_CMD);
3206
3207 Ptr<Packet> nsdu = Create<Packet>();
3208 nsdu->AddHeader(payload);
3209 nsdu->AddHeader(payloadType);
3210 nsdu->AddHeader(nwkHeader);
3211
3213 nwkHeader.GetRadius() != 0)
3214 {
3215 // Set RREQ RETRIES
3216 Time rreqRetryTime = m_nwkcRREQRetryInterval + MilliSeconds(m_rreqJitter->GetValue());
3217
3218 Ptr<RreqRetryTableEntry> rreqRetryTableEntry;
3219 if (m_rreqRetryTable.LookUpEntry(payload.GetRouteReqId(), rreqRetryTableEntry))
3220 {
3221 if (rreqRetryTableEntry->GetRreqRetryCount() >= rreqRetries)
3222 {
3223 NS_LOG_DEBUG("Maximum RREQ retries reached for dst [" << payload.GetDstAddr()
3224 << "] and rreq ID "
3225 << payload.GetRouteReqId());
3226 // Note: The value of the maximum number of retries (rreqRetries) is either
3227 // nwkcInitialRREQRetries or nwkcRREQRetries depending on where the RREQ is
3228 // transmitted. See Zigbee specification r22.1.0, Section 3.6.3.5.1 This trace here
3229 // is used to keep track when the maximum RREQ retries is reached.
3231 payload.GetDstAddr(),
3232 rreqRetries);
3233 }
3234 else
3235 {
3236 // Schedule the next RREQ RETRY event and update entry.
3237 EventId rreqRetryEvent = Simulator::Schedule(rreqRetryTime,
3239 this,
3240 nwkHeader,
3241 payload,
3242 rreqRetries);
3243
3244 rreqRetryTableEntry->SetRreqRetryCount(rreqRetryTableEntry->GetRreqRetryCount() +
3245 1);
3246 rreqRetryTableEntry->SetRreqEventId(rreqRetryEvent);
3247 }
3248 }
3249 else
3250 {
3251 // Schedule the next RREQ RETRY and add a new record of the event.
3252 EventId rreqRetryEvent = Simulator::Schedule(rreqRetryTime,
3254 this,
3255 nwkHeader,
3256 payload,
3257 rreqRetries);
3258
3259 Ptr<RreqRetryTableEntry> newEntry =
3260 Create<RreqRetryTableEntry>(payload.GetRouteReqId(), rreqRetryEvent, 0);
3261
3262 m_rreqRetryTable.AddEntry(newEntry);
3263 }
3264 }
3265
3266 // Send the RREQ
3267 // See Section 3.4.1.1 Mac Data Service Requirements for RREQ
3268 if (nwkHeader.GetRadius() != 0)
3269 {
3270 McpsDataRequestParams params;
3271 params.m_dstPanId = m_nwkPanId;
3272 params.m_srcAddrMode = SHORT_ADDR;
3273 params.m_dstAddrMode = SHORT_ADDR;
3274 params.m_dstAddr = Mac16Address::GetBroadcast();
3275 params.m_msduHandle = m_macHandle.GetValue();
3276 m_macHandle++;
3278 }
3279 else
3280 {
3281 NS_LOG_DEBUG("Maximum radius reached, dropping RREQ");
3282 }
3283}
3284
3285void
3287 Mac16Address originator,
3288 Mac16Address responder,
3289 uint8_t rreqId,
3290 uint8_t pathcost)
3291{
3292 NS_LOG_FUNCTION(this);
3293
3294 ZigbeeNwkHeader nwkHeader;
3295 nwkHeader.SetFrameType(NWK_COMMAND);
3298
3299 nwkHeader.SetDstAddr(nextHop);
3302 nwkHeader.SetSeqNum(m_nwkSequenceNumber.GetValue());
3303 // see Zigbee specification 3.4.2.2
3304 // Use the maximum possible radius
3305 nwkHeader.SetRadius(m_nwkMaxDepth * 2);
3306
3307 ZigbeePayloadType payloadType(ROUTE_REP_CMD);
3308
3310 payload.SetRouteReqId(rreqId);
3311 payload.SetOrigAddr(originator);
3312 payload.SetRespAddr(responder);
3313 payload.SetPathCost(pathcost);
3314
3315 // See Section 3.4.2 Mac Data Service Requirements for RREP
3316 McpsDataRequestParams params;
3317 params.m_dstPanId = m_nwkPanId;
3318 params.m_srcAddrMode = SHORT_ADDR;
3319 params.m_dstAddrMode = SHORT_ADDR;
3320 params.m_dstAddr = nextHop;
3321 params.m_msduHandle = m_macHandle.GetValue();
3322 m_macHandle++;
3323
3324 Ptr<Packet> nsdu = Create<Packet>();
3325 nsdu->AddHeader(payload);
3326 nsdu->AddHeader(payloadType);
3327 nsdu->AddHeader(nwkHeader);
3328
3330}
3331
3332int64_t
3334{
3335 NS_LOG_FUNCTION(this << stream);
3336 m_uniformRandomVariable->SetStream(stream);
3337 return 1;
3338}
3339
3340void
3342{
3343 NS_LOG_FUNCTION(this);
3344
3345 ZigbeeBeaconPayload beaconPayloadHeader;
3346 beaconPayloadHeader.SetStackProfile(static_cast<uint8_t>(m_nwkStackProfile));
3347 beaconPayloadHeader.SetRouterCapacity(m_nwkcCoordinatorCapable);
3348 beaconPayloadHeader.SetDeviceDepth(0); // Not used by stack profile (0x02 =ZIGBEE pro)
3349 beaconPayloadHeader.SetEndDevCapacity(true);
3350 beaconPayloadHeader.SetExtPanId(m_nwkExtendedPanId);
3351 beaconPayloadHeader.SetTxOffset(0xFFFFFF);
3352 // TODO: beaconPayload.SetNwkUpdateId(m_nwkUpdateId);
3353
3354 // Set the beacon payload length in the MAC PIBs and then proceed to
3355 // update the beacon payload
3357 m_beaconPayload->AddHeader(beaconPayloadHeader);
3359 pibAttr->macBeaconPayloadLength = m_beaconPayload->GetSize();
3361 m_mac,
3363 pibAttr);
3364}
3365
3366void
3368{
3369 NS_LOG_FUNCTION(this);
3370
3371 // Extract octets from m_beaconPayload and copy them into the
3372 // macBeaconPayload attribute
3374 pibAttr->macBeaconPayload.resize(m_beaconPayload->GetSize());
3375 m_beaconPayload->CopyData(pibAttr->macBeaconPayload.data(), m_beaconPayload->GetSize());
3376 m_beaconPayload = nullptr;
3378 m_mac,
3380 pibAttr);
3381}
3382
3383std::ostream&
3384operator<<(std::ostream& os, const NwkStatus& state)
3385{
3386 switch (state)
3387 {
3388 case NwkStatus::SUCCESS:
3389 os << "SUCCESS";
3390 break;
3392 os << "FULL CAPACITY";
3393 break;
3395 os << "ACCESS DENIED";
3396 break;
3398 os << "COUNTER ERROR";
3399 break;
3401 os << "IMPROPER KEY TYPE";
3402 break;
3404 os << "IMPROPER SECURITY LEVEL";
3405 break;
3407 os << "UNSUPPORTED LEGACY";
3408 break;
3410 os << "UNSUPPORTED SECURITY";
3411 break;
3413 os << "BEACON LOSS";
3414 break;
3416 os << "CHANNEL ACCESS FAILURE";
3417 break;
3418 case NwkStatus::DENIED:
3419 os << "DENIED";
3420 break;
3422 os << "DISABLE TRX FAILURE";
3423 break;
3425 os << "SECURITY ERROR";
3426 break;
3428 os << "FRAME TOO LONG";
3429 break;
3431 os << "INVALID GTS";
3432 break;
3434 os << "INVALID HANDLE";
3435 break;
3437 os << "INVALID PARAMETER MAC";
3438 break;
3439 case NwkStatus::NO_ACK:
3440 os << "NO ACKNOLEDGMENT";
3441 break;
3443 os << "NO BEACON";
3444 break;
3445 case NwkStatus::NO_DATA:
3446 os << "NO DATA";
3447 break;
3449 os << "NO SHORT ADDRESS";
3450 break;
3452 os << "OUT OF CAP";
3453 break;
3455 os << "PAN ID CONFLICT";
3456 break;
3458 os << "REALIGMENT";
3459 break;
3461 os << "TRANSACTION EXPIRED";
3462 break;
3464 os << "TRANSACTION OVERFLOW";
3465 break;
3467 os << "TX ACTIVE";
3468 break;
3470 os << "UNAVAILABLE KEY";
3471 break;
3473 os << "INVALID ADDRESS";
3474 break;
3476 os << "ON TIME TOO LONG";
3477 break;
3479 os << "PAST TIME";
3480 break;
3482 os << "TRACKING OFF";
3483 break;
3485 os << "INVALID INDEX";
3486 break;
3488 os << "READ ONLY";
3489 break;
3491 os << "SUPERFRAME OVERLAP";
3492 break;
3494 os << "INVALID PARAMETER";
3495 break;
3497 os << "INVALID REQUEST";
3498 break;
3500 os << "NO PERMITED";
3501 break;
3503 os << "STARTUP FAILURE";
3504 break;
3506 os << "ALREADY PRESENT";
3507 break;
3509 os << "SYNC FAILURE";
3510 break;
3512 os << "NEIGHBOR TABLE FULL";
3513 break;
3515 os << "UNKNOWN DEVICE";
3516 break;
3518 os << "UNSUPPORTED ATTRIBUTE";
3519 break;
3521 os << "NO NETWORKS";
3522 break;
3524 os << "MAX FRAME COUNTER";
3525 break;
3526 case NwkStatus::NO_KEY:
3527 os << "NO KEY";
3528 break;
3530 os << "BAD CCM OUTPUT";
3531 break;
3533 os << "ROUTE DISCOVERY FAILED";
3534 break;
3536 os << "ROUTE ERROR";
3537 break;
3539 os << "BT TABLE FULL";
3540 break;
3542 os << "FRAME NOT BUFFERED";
3543 break;
3545 os << "INVALID INTERFACE";
3546 break;
3548 os << "LIMIT REACHED";
3549 break;
3551 os << "SCAN IN PROGRESS";
3552 break;
3553 }
3554 return os;
3555}
3556
3557std::ostream&
3558operator<<(std::ostream& os, const std::vector<uint8_t>& vec)
3559{
3560 std::copy(vec.begin(), vec.end(), std::ostream_iterator<uint16_t>(os, " "));
3561 return os;
3562}
3563
3564std::ostream&
3565operator<<(std::ostream& os, const uint8_t& num)
3566{
3567 os << static_cast<uint16_t>(num);
3568 return os;
3569}
3570
3571} // namespace zigbee
3572} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
An identifier for simulation events.
Definition event-id.h:45
This class can contain 16 bit addresses.
uint16_t ConvertToInt() const
static Mac16Address GetBroadcast()
bool IsBroadcast() const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
an EUI-64 address
virtual void DoInitialize()
Initialize() implementation.
Definition object.cc:440
Object()
Constructor.
Definition object.cc:96
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:409
@ S
second
Definition nstime.h:107
AttributeValue implementation for Time.
Definition nstime.h:1456
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
virtual void McpsDataRequest(McpsDataRequestParams params, Ptr< Packet > p)=0
IEEE 802.15.4-2006, section 7.1.1.1 MCPS-DATA.request Request to transfer a MSDU.
virtual void MlmeOrphanResponse(MlmeOrphanResponseParams params)=0
IEEE 802.15.4-2011, section 6.2.7.2 MLME-ORPHAN.response Primitive used to initiatte a response to an...
virtual void MlmeGetRequest(MacPibAttributeIdentifier id)=0
IEEE 802.15.4-2006, section 7.1.6.1 MLME-GET.request Request information about a given PIB attribute.
virtual void MlmeScanRequest(MlmeScanRequestParams params)=0
IEEE 802.15.4-2011, section 6.2.10.1 MLME-SCAN.request Request primitive used to initiate a channel s...
virtual void MlmeAssociateResponse(MlmeAssociateResponseParams params)=0
IEEE 802.15.4-2011, section 6.2.2.3 MLME-ASSOCIATE.response Primitive used to initiate a response to ...
virtual void MlmeStartRequest(MlmeStartRequestParams params)=0
IEEE 802.15.4-2006, section 7.1.14.1 MLME-START.request Request to allow a PAN coordinator to initiat...
virtual void MlmeAssociateRequest(MlmeAssociateRequestParams params)=0
IEEE 802.15.4-2011, section 6.2.2.1 MLME-ASSOCIATE.request Request primitive used by a device to requ...
virtual void MlmeSetRequest(MacPibAttributeIdentifier id, Ptr< MacPibAttributes > attribute)=0
IEEE 802.15.4-2011, section 6.2.11.1 MLME-SET.request Attempts to write the given value to the indica...
Represent the the Capability Information Bit fields See zigbe Specification r22.1....
uint8_t GetCapability() const
Used to obtain the complete capability information bit map.
void SetCapability(uint8_t capability)
Set the Capability Information bit map.
MacDeviceType GetDeviceType() const
This field will have a value of ROUTER if the joining device is a Zigbee router.
bool IsReceiverOnWhenIdle() const
This field will be set to the value of the lowest-order bit of the RxOnWhenIdle parameter passed to t...
void SetDeviceType(MacDeviceType devType)
Set the device type bit for the capability information field.
void SetReceiverOnWhenIdle(bool value)
Set the Receiver On When Idle bit for the capability information field.
bool IsAllocateAddrOn() const
This field will have a value of true in implementations of this specification, indicating that the jo...
Represent the Superframe Specification information field.
bool IsAssocPermit() const
Check if the Association Permit bit is enabled.
uint8_t GetFrameOrder() const
Get the Superframe Specification Frame Order field.
uint8_t GetBeaconOrder() const
Get the Superframe Specification Beacon Order field.
Represents the payload portion of a beacon frame.
bool GetRouterCapacity() const
Get the router capacity capability.
void SetDeviceDepth(uint8_t deviceDepth)
Set the cevice depth object.
uint8_t GetProtocolId() const
Get the Protocol Id used.
uint8_t GetStackProfile() const
Get the Stack Profile used.
void SetRouterCapacity(bool routerCapacity)
Set the Router Capacity capability True = The device is able to accept join.request from router-capab...
uint64_t GetExtPanId() const
Get the extended PAN identifier.
void SetStackProfile(uint8_t stackProfile)
Set the network profile identifier.
void SetEndDevCapacity(bool endDevCapacity)
Set the end device Capacity.
bool GetEndDevCapacity() const
Get the end dev capacity.
void SetTxOffset(uint32_t txOffset)
Set the Tx Offset time in symbols.
void SetExtPanId(uint64_t extPanId)
Set the extended PAN id.
Represent the NWK Header with the Frame Control and Routing fields Zigbee Specification r22....
void SetMulticast()
Set to true the value of the multicast flag in the frame control field.
bool GetEndDeviceInitiator() const
Get whether or not the source of this message was an end device.
void SetDiscoverRoute(enum DiscoverRouteType discoverRoute)
Suppress or enable route discovery for this frame.
void SetSrcAddr(Mac16Address addr)
Set Source address.
void SetEndDeviceInitiator()
This flag is used by the NWK to indicate if the the initiator device of the message is an end device ...
void SetProtocolVer(uint8_t ver)
Set the Protocol version.
MulticastMode GetMulticastMode() const
Get the multicast mode.
bool IsMulticast() const
Inform whether or not the current frame is used in multicast.
void SetSeqNum(uint8_t seqNum)
Set the Sequence number.
void SetNonMemberRadius(uint8_t radius)
Set the non-member radius.
uint8_t GetNonMemberRadius() const
Get the non-member radius.
uint8_t GetRadius() const
Get the Radius.
uint8_t GetSeqNum() const
Get the frame Sequence number.
NwkType GetFrameType() const
Set the Frame Control field "Frame Type" bits.
void SetRadius(uint8_t radius)
Set the Radius.
void SetMulticastMode(MulticastMode mode)
Set the multicast mode.
void SetFrameType(enum NwkType nwkType)
Set the Frame type used (Data or Command)
uint8_t GetMaxNonMemberRadius() const
Get the maximum non-member radius.
void SetMaxNonMemberRadius(uint8_t radius)
Set the maximum non-member radius.
Mac16Address GetDstAddr() const
Get the Destination address.
void SetDstAddr(Mac16Address addr)
Set Destination address.
DiscoverRouteType GetDiscoverRoute() const
Get the status of frame discovery route (suppress or enabled)
Mac16Address GetSrcAddr() const
Get the Source address.
void SendDataUcst(Ptr< Packet > packet, uint8_t nwkHandle)
Send a data unicast packet, and if necessary look for the next hop route and store the pending data t...
NeighborTable m_nwkNeighborTable
The network layer neighbor table See Zigbee specification r22.1.0, 3.6.1.5.
RouteDiscoveryStatus ProcessManyToOneRoute(Mac16Address macSrcAddr, uint8_t pathCost, ZigbeeNwkHeader nwkHeader, ZigbeePayloadRouteRequestCommand payload)
Process Many-To-One routes.
ZigbeeNwk()
Default constructor.
Mac64Address GetIeeeAddress() const
Obtain this device 64 bit IEEE address (A.K.A.
NlmeStartRouterRequestParams m_startRouterParams
Temporarily store the NLME-START-ROUTER.request parameters during the router initialization process.
Ptr< ZigbeeGroupTable > m_nwkGroupIdTable
The Group Table used by this Zigbee NWK.
uint8_t m_nwkConcentratorDiscoveryTime
The time in seconds between concentrator route discoveries.
void DisposePendingTx()
Dispose of all PendingTxPkt accumulated in the pending transmission queue.
uint8_t m_nwkCapabilityInformation
This NIB attribute contains the device capability information established at network joining time.
void MlmeOrphanIndication(lrwpan::MlmeOrphanIndicationParams params)
IEEE 802.15.4-2011 sections 6.2.7.1, Zigbee Specification r22.1.0 Section 3.6.1.4....
void UpdateBeaconPayload()
Updates the content of the beacon payload with the most recent information in the NWK.
TracedCallback< uint8_t, Mac16Address, uint8_t > m_rreqRetriesExhaustedTrace
A trace source that fires when a node has reached the maximum number of RREQ retries allowed.
Mac16Address AllocateNetworkAddress()
Used by a Zigbee coordinator or router to allocate a 16 bit address (A.K.A short address or network a...
void NlmeDirectJoinRequest(NlmeDirectJoinRequestParams params)
Zigbee Specification r22.1.0, section 3.2.2.16 and 3.6.1.4.3 NLME-DIRECT-JOIN.request Allows the next...
RoutingTable m_nwkRoutingTable
The network layer routing table See Zigbee specification r22.1.0, 3.6.3.2.
double m_nwkcMinRREQJitter
Minimum Route request broadcast jitter time (msec).
SequenceNumber8 m_nwkSequenceNumber
The sequence number used to identify outgoing frames See Zigbee specification r22....
NlmeNetworkFormationRequestParams m_netFormParams
The parameters used during a NLME-NETWORK-FORMATION.request.
void McpsDataConfirm(lrwpan::McpsDataConfirmParams params)
IEEE 802.15.4-2011 section 6.3.2 MCPS-DATA.confirm Reports the results of a request to a transfer dat...
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random values.
NlmeJoinIndicationParams m_joinIndParams
Temporarily store the NLME-JOIN.indication parameters while the join operations (asocciation) conclud...
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream) const
Print the entries in the routing table.
Mac16Address FindRoute(Mac16Address dst, bool &neighbor)
Search for a specific destination in this device neighbor and routing tables.
void SetNlmeJoinConfirmCallback(NlmeJoinConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
void NlmeStartRouterRequest(NlmeStartRouterRequestParams params)
Zigbee Specification r22.1.0, section 3.2.2.9 NLME-START-ROUTER.request This primitive allows the nex...
void SetNlmeRouteDiscoveryConfirmCallback(NlmeRouteDiscoveryConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
uint8_t m_currentChannel
Used to store the value of the PHY current channel.
Time m_routeExpiryTime
The expiration time of routing table entry.
static TypeId GetTypeId()
Get the type ID.
Definition zigbee-nwk.cc:35
void NldeDataRequest(NldeDataRequestParams params, Ptr< Packet > packet)
Zigbee Specification r22.1.0, Section 3.2.1.1 NLDE-DATA.request Request to transfer a NSDU.
void SendRREP(Mac16Address nextHop, Mac16Address originator, Mac16Address responder, uint8_t rreqId, uint8_t pathcost)
Construct and send a route reply command.
void PrintNeighborTable(Ptr< OutputStreamWrapper > stream) const
Print the entries in the neighbor table.
void MlmeSetConfirm(lrwpan::MlmeSetConfirmParams params)
IEEE 802.15.4-2011 section 6.2.11.2 MLME-SET.confirm Reports the result of an attempt to change a MAC...
void UpdateBeaconPayloadLength()
Create and store a MAC beacon payload, then updates its registered size in the MAC.
StackProfile m_nwkStackProfile
Describes the current stack profile used in this NWK layer.
NlmeDirectJoinConfirmCallback m_nlmeDirectJoinConfirmCallback
This callback is used by the next layer of a zigbee coordinator or router to be notified of the resul...
bool m_nwkReportConstantCost
If false, the NWK layer shall calculate the link cost from all neighbor nodes using the LQI values re...
Time m_nwkcRREQRetryInterval
Duration between retries of a broadcast route request command frame.
Ptr< UniformRandomVariable > m_bcstJitter
Provides uniform random values for the broadcast jitter.
void DoInitialize() override
Initialize() implementation.
NlmeNetworkFormationConfirmCallback m_nlmeNetworkFormationConfirmCallback
This callback is used to to notify the results of a network formation to the APS sublayer making the ...
void MlmeCommStatusIndication(lrwpan::MlmeCommStatusIndicationParams params)
IEEE 802.15.4-2011 section 6.2.4.2 MLME-COMM-STATUS.indication Allows the MAC MLME to indicate a comm...
PanIdTable m_panIdTable
Use to keep track of neighboring 16 bit PAN id.
Mac16Address m_nwkNetworkAddress
The 16-bit address that the device uses to communicate with the PAN.
RouteDiscoveryStatus FindNextHop(Mac16Address macSrcAddr, uint8_t pathCost, ZigbeeNwkHeader nwkHeader, ZigbeePayloadRouteRequestCommand payload, Mac16Address &nextHop)
Find the next hop in route to a destination.
void SetMac(Ptr< lrwpan::LrWpanMacBase > mac)
Set the underlying MAC to use in this Zigbee NWK.
uint8_t m_nwkParentInformation
The behavior depends upon whether the device is a FFD or RFD.
void ReceiveMulticastNonMemberFrame(ZigbeeNwkHeader nwkHeader, Ptr< Packet > msdu, lrwpan::McpsDataIndicationParams params)
Process a Multicast Frame received as a non member of a multicast group.
SequenceNumber8 m_macHandle
The handle assigned when doing a transmission request to the MAC layer.
NlmeJoinRequestParams m_joinParams
The parameters used during a NLME-JOIN.request.
void MlmeBeaconNotifyIndication(lrwpan::MlmeBeaconNotifyIndicationParams params)
IEEE 802.15.4-2011, Section 6.2.4.1 MLME-BEACON-NOTIFY.indication Allows the MAC MLME to indicate the...
void SetNlmeJoinIndicationCallback(NlmeJoinIndicationCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
uint8_t m_nwkcInitialRREQRetries
The number of times the first broadcast transmission of a route request command frame is retried.
void SetNlmeNetworkDiscoveryConfirmCallback(NlmeNetworkDiscoveryConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
void MlmeAssociateConfirm(lrwpan::MlmeAssociateConfirmParams params)
IEEE 802.15.4-2011 section MlME-ASSOCIATE.confirm Report the results of an associate request attempt.
void EnqueuePendingTx(Ptr< Packet > p, uint8_t nsduHandle)
Enqueue a packet in the pending transmission queue until a route is discovered for its destination.
void NlmeNetworkDiscoveryRequest(NlmeNetworkDiscoveryRequestParams params)
Zigbee Specification r22.1.0, section 3.2.2.3 NLME-NETWORK-DISCOVERY.request Allows the next higher l...
Ptr< NetFormPendingParamsGen > m_netFormParamsGen
The values temporarily stored as a result of the initial steps of a NLME-NETWORK-FORMATION....
NlmeStartRouterConfirmCallback m_nlmeStartRouterConfirmCallback
This callback is used by the next layer of a zigbee router or device to be notified of the result of ...
NlmeJoinConfirmCallback m_nlmeJoinConfirmCallback
This callback is used by the next layer of a zigbee router or device to be notified of the result of ...
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void ReceiveMulticastMemberFrame(ZigbeeNwkHeader nwkHeader, Ptr< Packet > msdu, lrwpan::McpsDataIndicationParams params)
Process a Multicast Frame received as a member of a multicast group.
void NlmeJoinRequest(NlmeJoinRequestParams params)
Zigbee Specification r22.1.0, section 3.2.2.13 NLME-JOIN.request This primitive allows the next highe...
uint8_t m_nwkConcentratorRadius
This NIB attribute indicates the hop count radius for concentrator route discoveries (Used by Many-To...
double m_nwkcMaxRREQJitter
Maximum Route request broadcast jitter time (msec).
Mac64Address m_nwkIeeeAddress
The EUI 64 bit IEEE address of the local device.
void SetGroupTable(Ptr< ZigbeeGroupTable > groupTable)
Get the group table used by this Zigbee NWK.
void SetNlmeStartRouterConfirmCallback(NlmeStartRouterConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
Time m_nwkPassiveAckTimeout
The maximum time duration in milliseconds allowed for the parent all the child devices to retransmit ...
void ReceiveRREP(Mac16Address macSrcAddr, uint8_t linkCost, ZigbeeNwkHeader nwkHeader, ZigbeePayloadRouteReplyCommand payload)
Handles the reception of a route reply command.
uint16_t m_nwkPanId
This NIB attribute should, at all times, have the same value as macPANId .
void SetNldeDataConfirmCallback(NldeDataConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
Ptr< Packet > m_beaconPayload
Points to the beacon payload used during the network formation process.
uint8_t m_countRREQRetries
Count the number of retries this device has transmitted an RREQ.
PendingPrimitiveNwk m_pendPrimitiveNwk
Indicates the current primitive in use in the NWK layer.
bool IsBroadcastAddress(Mac16Address address)
Returns true if the address is a broadcast address according to Zigbee specification r22....
double m_nwkcMaxBroadcastJitter
Minimum Broadcast jitter time (msec).
BroadcastTransactionTable m_btt
The broadcast transaction table.
void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
uint8_t m_nwkMaxBroadcastRetries
The maximum number of retries allowed after a broadcast transmission failure See Zigbe Specification ...
uint32_t m_maxPendingTxQueueSize
The maximum size of the pending transaction queue.
uint8_t m_nwkMaxDepth
The depth a device can have.
AddrAllocMethod m_nwkAddrAlloc
A value that determines the method used to assign addresses.
std::vector< NetworkDescriptor > m_networkDescriptorList
Temporarily store beacons information from POS routers and PAN coordinators during a network-discover...
NldeDataConfirmCallback m_nldeDataConfirmCallback
This callback is used to respond to data PDU (NSDU) transfer request issued by APS sublayer to the NW...
Ptr< lrwpan::LrWpanMacBase > m_mac
Pointer to the underlying MAC connected to this Zigbee NWK.
void MlmeStartConfirm(lrwpan::MlmeStartConfirmParams params)
IEEE 802.15.4-2011 section 7.1.14.2 MLME-START.confirm Reports the results of a network start request...
uint8_t GetLinkCost(uint8_t lqi) const
Obtain the link cost based on the value of the nwkReportConstantCost.
void MlmeAssociateIndication(lrwpan::MlmeAssociateIndicationParams params)
IEEE 802.15.4-2011, Section 6.2.2.2.
void ReceiveRREQ(Mac16Address macSrcAddr, uint8_t linkCost, ZigbeeNwkHeader nwkHeader, ZigbeePayloadRouteRequestCommand payload)
Handles the reception of a route request command.
void PrintRREQRetryTable(Ptr< OutputStreamWrapper > stream) const
Print the entries in the RREQ retry table.
void PrintRouteDiscoveryTable(Ptr< OutputStreamWrapper > stream)
Print the entries in the route discovery table.
Ptr< UniformRandomVariable > m_rreqJitter
Provides uniform random values for the route request jitter.
NwkStatus GetNwkStatus(lrwpan::MacStatus macStatus) const
Cast a Mac layer status to a NWK layer status.
uint16_t m_nwkMaxChildren
The number of children a device is allowed to have on its current network.
uint8_t m_scanEnergyThreshold
The maximum acceptable energy level used in an energy scan taking place during a NLME-NETWORK-FORMATI...
void MlmeScanConfirm(lrwpan::MlmeScanConfirmParams params)
IEEE 802.15.4-2011 section 6.2.10.2 MLME-SCAN.confirm Reports the results of a scan request.
void NlmeNetworkFormationRequest(NlmeNetworkFormationRequestParams params)
Zigbee Specification r22.1.0, Section 3.2.2.5 and 3.6.1.1 NLME-NETWORK-FORMATION.request Request the ...
SequenceNumber8 m_routeRequestId
The counter used to identify route request commands.
NlmeNetworkDiscoveryConfirmCallback m_nlmeNetworkDiscoveryConfirmCallback
This callback is used to to notify the results of a network formation to the APS sublayer making the ...
uint16_t m_nwkEndDeviceTimeoutDefault
Indicates the index of the requested timeout field that contains the timeout in minutes for any end d...
void DisposeTxPktBuffer()
Dispose of all the entries in the TxPkt Buffer.
bool m_nwkIsConcentrator
This NIB attribute is a flag determining if this device is a concentrator (Use in Many-To-One routing...
Time m_nwkcRouteDiscoveryTime
Indicates the duration until a route discovery expires.
uint8_t m_txBufferMaxSize
The maximum size of the transmission buffer.
lrwpan::MlmeAssociateRequestParams m_associateParams
Temporarily store MLME-ASSOCIATE.request parameters during a NLME-JOIN.request.
void SendRREQ(ZigbeeNwkHeader nwkHeader, ZigbeePayloadRouteRequestCommand payload, uint8_t rreqRetries)
Send a route request command.
RreqRetryTable m_rreqRetryTable
Keep track of all the route request retries.
bool m_nwkUseTreeRouting
This NIB attribute indicates whether the NWK layer should assume the ability to use hierarchical rout...
void SetNlmeNetworkFormationConfirmCallback(NlmeNetworkFormationConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
Time m_nwkNetworkBroadcastDeliveryTime
Time duration that a broadcast message needs to encompass the entire network.
NlmeRouteDiscoveryConfirmCallback m_nlmeRouteDiscoveryConfirmCallback
This callback is used to to notify the results of a network formation to the APS sublayer making the ...
void SetNlmeDirectJoinConfirmCallback(NlmeDirectJoinConfirmCallback c)
Set the callback as part of the interconnections between the NWK and the APS sublayer (or any other h...
bool m_nwkSymLink
Describes the current route symmetry: True: Routes are considered to be symmetric links.
uint32_t m_filteredChannelMask
Contains the list of channels with acceptable energy levels in a bitmap form.
std::deque< Ptr< PendingTxPkt > > m_pendingTxQueue
The pending transaction queue of data packets awaiting to be transmitted until a route to the destina...
uint16_t m_nwkMaxRouters
The number of routers any one device is allowed to have as children.
bool m_nwkcCoordinatorCapable
Indicates whether the device is capable of becoming the ZigBee coordinator Zigbee Specification r22....
void McpsDataIndication(lrwpan::McpsDataIndicationParams params, Ptr< Packet > msdu)
IEEE 802.15.4-2011 section 6.3.3 MCPS-DATA.indication Indicates the reception of an MSDU from MAC to ...
void BufferTxPkt(Ptr< Packet > p, uint8_t macHandle, uint8_t nwkHandle)
Buffer a copy of a DATA frame for post transmission handling (Transmission failure counts,...
bool RetrieveTxPkt(uint8_t macHandle, Ptr< TxPkt > &txPkt)
Retrieves a previously DATA frame buffered in the TxPkt buffer.
void NlmeRouteDiscoveryRequest(NlmeRouteDiscoveryRequestParams params)
Zigbee Specification r22.1.0, section 3.2.2.33.3 and 3.6.3.5 NLME-ROUTE-DISCOVERY....
std::deque< Ptr< TxPkt > > m_txBuffer
The transmission buffer.
Ptr< lrwpan::LrWpanMacBase > GetMac() const
Get the underlying MAC used by the current Zigbee NWK.
uint8_t GetLQINonLinearValue(uint8_t lqi) const
Get a non linear representation of a Link Quality Indicator (LQI).
void SetNldeDataIndicationCallback(NldeDataIndicationCallback c)
Set the callback for the end of a RX, as part of the interconnections between the NWK and the APS sub...
void DoDispose() override
Destructor implementation.
uint8_t m_nwkcRREQRetries
The number of times the broadcast transmission of a route request command frame is retried on relay b...
bool DequeuePendingTx(Mac16Address dst, Ptr< PendingTxPkt > entry)
Dequeue a packet previously enqueued in the pending transmission queue.
uint8_t m_nwkcProtocolVersion
Indicates the version of the ZigBee NWK protocol in the device.
void SendDataBcst(Ptr< Packet > packet, uint8_t nwkHandle)
Send a data broadcast packet, and add a record to the broadcast transaction table (BTT).
Mac16Address GetNetworkAddress() const
Obtain this device 16 bit network address (A.K.A.
void MlmeGetConfirm(lrwpan::MacStatus status, lrwpan::MacPibAttributeIdentifier id, Ptr< lrwpan::MacPibAttributes > attribute)
IEEE 802.15.4-2011 section 6.2.5.1 MLME-GET.confirm Reports the result of an attempt to obtain a MAC ...
NldeDataIndicationCallback m_nldeDataIndicationCallback
This callback is used to notify incoming packets to the APS sublayer.
RouteDiscoveryTable m_nwkRouteDiscoveryTable
The network route discovery table See Zigbee specification r22.1.0, 3.6.3.2.
uint64_t m_nwkExtendedPanId
The extended PAN identifier for the PAN of which the device is a member.
NlmeJoinIndicationCallback m_nlmeJoinIndicationCallback
This callback is used by the next layer of a zigbee coordinator or router to be notified when a new d...
Represent a variable portion of the zigbee payload header that includes the route reply command.
void SetRouteReqId(uint8_t rid)
Set the Route request identifier.
Mac16Address GetRespAddr() const
Get the Responder address.
Mac16Address GetOrigAddr() const
Get the Originator address.
void SetRespAddr(Mac16Address addr)
Set Responder address.
uint8_t GetRouteReqId() const
Get the Route request identifier.
void SetOrigAddr(Mac16Address addr)
Set Originator address.
void SetPathCost(uint8_t cost)
Set the path cost.
Represent a variable portion of the zigbee payload header that includes the route request command.
uint8_t GetRouteReqId() const
Get the Route request identifier.
void SetCmdOptManyToOneField(enum ManyToOne manyToOne)
Set the command option field Many To One.
uint8_t GetCmdOptManyToOneField() const
Get the command option field Many To One.
void SetRouteReqId(uint8_t id)
Set the Route request identifier.
void SetMulticastField(bool mcst)
Set the command option multicast field.
void SetDstAddr(Mac16Address addr)
Set Destination address.
Mac16Address GetDstAddr() const
Get the Destination address.
bool GetMulticastField() const
Get the command option multicast field.
Represent the static portion of the zigbee payload header that describes the payload command type.
NwkCommandType GetCmdType() const
Get the command frame type.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1457
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1477
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
MacPibAttributeIdentifier
IEEE 802.15.4-2006 PHY and MAC PIB Attribute Identifiers Table 23 and Table 86.
MacStatus
The status of a confirm or an indication primitive as a result of a previous request.
@ 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.
@ macExtendedAddress
The extended address of the device (64 bit address).
@ macBeaconPayload
The contents of the beacon payload.
@ NO_BEACON
A scan operation failed to find any network beacons.
@ FULL_CAPACITY
PAN at capacity.
@ SUCCESS
The operation was completed successfully.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
SequenceNumber< uint8_t, int8_t > SequenceNumber8
8 bit Sequence number.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time Minutes(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
NwkDeviceType
The network layer device type.
static const double RequestedTimeoutField[15]
Requested Timeout Field See Zigbee Specification r22.1.0, 3.4.11.3.1.
@ ZIGBEE_COORDINATOR
Zigbee coordinator.
@ ZIGBEE_ENDDEVICE
Zigbee end device.
@ ZIGBEE_ROUTER
Zigbee router.
@ ROUTE_VALIDATION_UNDERWAY
Route discovery validation underway.
@ ROUTE_ACTIVE
Route active.
@ ROUTE_DISCOVERY_UNDERWAY
Route discovery underway.
@ ENDDEVICE
End device or router treated as an end device.
@ ROUTER
Router device.
@ NBR_CHILD
Neighbor is the child.
@ NBR_PARENT
Neighbor is the parent.
@ NBR_NONE
No relationship.
@ STOCHASTIC_ALLOC
Stochastic address allocation (Zigbee Specification r22.1.0 Section 3.6.1.7)
Definition zigbee-nwk.h:90
@ DISTRIBUTED_ALLOC
Distributed address allocation (Zigbee Specification r22.1.0 Section 3.6.1.6)
Definition zigbee-nwk.h:88
DiscoverRouteType
Zigbee Specification r22.1.0, Values of the discover route sub-field (Table 3-47)
@ ENABLE_ROUTE_DISCOVERY
Enable route discovery.
Callback< void, NlmeRouteDiscoveryConfirmParams > NlmeRouteDiscoveryConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:652
@ ASSOCIATION
The device is requesting to join a network through association.
Definition zigbee-nwk.h:109
@ DIRECT_OR_REJOIN
The device is joining directly or rejoining using the orphaning procedure.
Definition zigbee-nwk.h:110
Callback< void, NlmeNetworkFormationConfirmParams > NlmeNetworkFormationConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:636
@ NO_ROUTING_CAPACITY
No routing capacity.
Definition zigbee-nwk.h:250
@ NO_ROUTE_AVAILABLE
No route available.
Definition zigbee-nwk.h:246
Callback< void, NlmeStartRouterConfirmParams > NlmeStartRouterConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:684
Callback< void, NlmeJoinIndicationParams > NlmeJoinIndicationCallback
This callback is used to notify the next higher layer with an indication that a new device has succes...
Definition zigbee-nwk.h:676
@ MCST
Multicast Address mode.
Definition zigbee-nwk.h:78
@ NO_ADDRESS
No destination address.
Definition zigbee-nwk.h:77
@ UCST_BCST
Unicast or Broadcast address mode.
Definition zigbee-nwk.h:79
@ NWK_COMMAND
Network command frame type.
@ DATA
Data frame type.
@ INTER_PAN
Inter-Pan frame type.
@ ROUTE_REP_CMD
Route response command.
@ ROUTE_REQ_CMD
Route request command.
Callback< void, NldeDataIndicationParams, Ptr< Packet > > NldeDataIndicationCallback
This callback is called after a NSDU has successfully received and NWK push it to deliver it to the n...
Definition zigbee-nwk.h:619
StackProfile
Use to describe the identifier of the zigbee stack profile.
Definition zigbee-nwk.h:98
@ ZIGBEE_PRO
Zigbee stack profile 0x02 (Zigbee Pro, also known as r22.1.0, 3.0)
Definition zigbee-nwk.h:100
std::ostream & operator<<(std::ostream &os, const NwkStatus &state)
Overloaded operator to print the value of a NwkStatus.
RouteDiscoveryStatus
The status returned while attempting to find the next hop in route towards a specific destination or ...
Definition zigbee-nwk.h:122
@ NO_DISCOVER_ROUTE
We are currently not allowed to perform a route discovery for this route (RouteDiscover flag in netwo...
Definition zigbee-nwk.h:130
@ ROUTE_NOT_FOUND
The next hop was not found.
Definition zigbee-nwk.h:125
@ MANY_TO_ONE_ROUTE
A new Many-To-One route was created.
Definition zigbee-nwk.h:135
@ ROUTE_FOUND
The next hop toward the destination was found in our routing table or neighbor table (Mesh route).
Definition zigbee-nwk.h:123
@ NO_ROUTE_CHANGE
No route entry was created or updated during a Many-To-One process.
Definition zigbee-nwk.h:136
@ DISCOVER_UNDERWAY
The route was found in the tables but currently has no next hop.
Definition zigbee-nwk.h:132
@ ROUTE_UPDATED
A route was found and updated with a better route (Mesh route or Many-To-One route)
Definition zigbee-nwk.h:128
@ TABLE_FULL
Either the routing or neighbor table are full.
Definition zigbee-nwk.h:127
Callback< void, NlmeNetworkDiscoveryConfirmParams > NlmeNetworkDiscoveryConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:644
Callback< void, NldeDataConfirmParams > NldeDataConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:628
Callback< void, NlmeDirectJoinConfirmParams > NlmeDirectJoinConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:660
@ MEMBER
Member multicast mode.
@ NONMEMBER
Non member multicast mode.
@ NLME_NET_DISCV
Pending NLME-NETWORK-DISCOVERY.request primitive.
Definition zigbee-nwk.h:64
@ NLME_NETWORK_FORMATION
Pending NLME-NETWORK-FORMATION.request primitive.
Definition zigbee-nwk.h:60
@ NLME_JOIN
Pending NLME-JOIN.request primitive.
Definition zigbee-nwk.h:62
@ NLDE_NLME_NONE
No pending primitive.
Definition zigbee-nwk.h:59
@ NLME_START_ROUTER
Pending NLME-START-ROUTER.request primitive.
Definition zigbee-nwk.h:63
@ NLME_JOIN_INDICATION
Pending NLME-JOIN.indication primitive.
Definition zigbee-nwk.h:65
@ NLME_ROUTE_DISCOVERY
Pending NLME-ROUTE-DISCOVERY.request primitive.
Definition zigbee-nwk.h:66
Callback< void, NlmeJoinConfirmParams > NlmeJoinConfirmCallback
This callback is used to notify the next higher layer with a confirmation in response to a previously...
Definition zigbee-nwk.h:668
NwkStatus
Network layer status values Combines Zigbee Specification r22.1.0 Table 3-73 and and IEEE 802....
Definition zigbee-nwk.h:152
@ BEACON_LOSS
The beacon was lost following a synchronization request.
Definition zigbee-nwk.h:162
@ UNSUPPORTED_LEGACY
Deprecated security used in IEEE 802.15.4-2003.
Definition zigbee-nwk.h:160
@ ALREADY_PRESENT
Already present (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:194
@ READ_ONLY
SET/GET request issued for a read only attribute.
Definition zigbee-nwk.h:187
@ MAX_FRM_COUNTER
Max Frame counter (IEEE 802.15.4, Zigbee specification r22.1.0)
Definition zigbee-nwk.h:200
@ UNSUPPORTED_SECURITY
The security applied is not supported.
Definition zigbee-nwk.h:161
@ DISABLE_TRX_FAILURE
The attempt to disable the transceier has failed.
Definition zigbee-nwk.h:165
@ FULL_CAPACITY
PAN at capacity.
Definition zigbee-nwk.h:155
@ NO_DATA
No response data were available following a request.
Definition zigbee-nwk.h:173
@ IMPROPER_KEY_TYPE
The key is not allowed to be used with that frame type.
Definition zigbee-nwk.h:158
@ INVALID_PARAMETER_MAC
Invalid parameter in response to a request passed to the MAC.
Definition zigbee-nwk.h:170
@ TRANSACTION_OVERFLOW
There is no capacity to store the transaction.
Definition zigbee-nwk.h:179
@ SUPERFRAME_OVERLAP
Coordinator sperframe and this device superframe tx overlap.
Definition zigbee-nwk.h:188
@ NOT_PERMITED
Not permitted (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:192
@ INVALID_REQUEST
Invalid request (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:191
@ OUT_OF_CAP
(Deprecated) See IEEE 802.15.4-2003
Definition zigbee-nwk.h:175
@ NO_NETWORKS
No network (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:199
@ SECURITY_ERROR
Cryptographic process of the frame failed(FAILED_SECURITY_CHECK).
Definition zigbee-nwk.h:166
@ UNSUPPORTED_ATTRIBUTE
Unsupported attribute (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:198
@ TRANSACTION_EXPIRED
The transaction expired and its information discarded.
Definition zigbee-nwk.h:178
@ REALIGMENT
A coordinator realigment command has been received.
Definition zigbee-nwk.h:177
@ SUCCESS
The operation was completed successfully.
Definition zigbee-nwk.h:154
@ LIMIT_REACHED
Limit reached during network scan (IEEE 802.15.4-2011)
Definition zigbee-nwk.h:208
@ NO_SHORT_ADDRESS
Failure due to unallocated 16-bit short address.
Definition zigbee-nwk.h:174
@ INVALID_INTERFACE
Invalid interface (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:207
@ INVALID_INDEX
A MAC PIB write failed because specified index is out of range.
Definition zigbee-nwk.h:186
@ UNAVAILABLE_KEY
Unavailable key, unknown or blacklisted.
Definition zigbee-nwk.h:181
@ INVALID_PARAMETER
Invalid Parameter (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:190
@ INVALID_ADDRESS
Invalid source or destination address.
Definition zigbee-nwk.h:182
@ FRAME_NOT_BUFFERED
Frame not buffered (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:206
@ IMPROPER_SECURITY_LEVEL
Insufficient security level expected by the recipient.
Definition zigbee-nwk.h:159
@ INVALID_HANDLE
When purging from TX queue handle was not found.
Definition zigbee-nwk.h:169
@ CHANNEL_ACCESS_FAILURE
A Tx could not take place due to activity in the CH.
Definition zigbee-nwk.h:163
@ TX_ACTIVE
The transceiver was already enabled.
Definition zigbee-nwk.h:180
@ BAD_CCM_OUTPUT
Bad ccm output (IEEE 802.15.4, Zigbee specification r22.1.0)
Definition zigbee-nwk.h:202
@ UNKNOWN_DEVICE
Unknown device (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:197
@ ACCESS_DENIED
PAN access denied.
Definition zigbee-nwk.h:156
@ NEIGHBOR_TABLE_FULL
Neighbor table full (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:196
@ FRAME_TOO_LONG
Frame more than aMaxPHYPacketSize or too large for CAP or GTS.
Definition zigbee-nwk.h:167
@ BT_TABLE_FULL
Bt table full (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:205
@ DENIED
The GTS request has been denied by the PAN coordinator.
Definition zigbee-nwk.h:164
@ ROUTE_DISCOVERY_FAILED
Route discovery failed (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:203
@ SYNC_FAILURE
Sync Failure (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:195
@ TRACKING_OFF
This device is currently not tracking beacons.
Definition zigbee-nwk.h:185
@ COUNTER_ERROR
The frame counter of the received frame is invalid.
Definition zigbee-nwk.h:157
@ NO_ACK
No acknowledgment was received after macMaxFrameRetries.
Definition zigbee-nwk.h:171
@ STARTUP_FAILURE
Startup failure (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:193
@ ON_TIME_TOO_LONG
RX enable request fail due to syms.
Definition zigbee-nwk.h:183
@ NO_BEACON
A scan operation failed to find any network beacons.
Definition zigbee-nwk.h:172
@ SCAN_IN_PROGRESS
The dev was scanning during this call (IEEE 802.5.4)
Definition zigbee-nwk.h:209
@ PAST_TIME
Rx enable request fail due to lack of time in superframe.
Definition zigbee-nwk.h:184
@ PAN_ID_CONFLICT
PAN id conflict detected and informed to the coordinator.
Definition zigbee-nwk.h:176
@ ROUTE_ERROR
Route error (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:204
@ NO_KEY
No Key (Zigbee specification r22.1.0)
Definition zigbee-nwk.h:201
@ INVALID_GTS
Missing GTS transmit or undefined direction.
Definition zigbee-nwk.h:168
Every class exported by the ns3 library is enclosed in the ns3 namespace.
AddressMode m_dstAddrMode
Destination address mode.
Mac16Address m_dstAddr
Destination address.
uint16_t m_dstPanId
Destination PAN identifier.
AddressMode m_srcAddrMode
Source address mode.
uint8_t m_txOptions
Tx Options (bitfield)
MLME-ASSOCIATE.confirm params.
MLME-ASSOCIATE.indication params.
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.
uint32_t m_chPage
The channel page on which to attempt association.
uint16_t m_coordPanId
The identifier of the PAN with which to associate.
MLME-ASSOCIATE.response params.
Mac16Address m_assocShortAddr
The short address allocated by the coordinator on successful assoc.
MacStatus m_status
The status of the association attempt (As defined on Table 83 IEEE 802.15.4-2006)
Mac64Address m_extDevAddr
The extended address of the device requesting association.
MLME-BEACON-NOTIFY.indication params.
MLME-COMM-STATUS.indication params.
MLME-ORPHAN.indication params.
bool m_assocMember
T = allocated with this coord | F = otherwise.
Mac64Address m_orphanAddr
The address of the orphaned device.
Mac16Address m_shortAddr
The short address allocated.
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.
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.
Network Descriptor, Zigbee Specification r22.1.0, 3.2.2.4, Table 3-12.
Definition zigbee-nwk.h:475
uint16_t m_panId
The 16-bit PAN identifier of the network.
Definition zigbee-nwk.h:477
uint8_t m_updateId
The value of the UpdateID from the NIB.
Definition zigbee-nwk.h:478
uint8_t m_superframeOrder
The superframe order value of the underlying MAC (Determinates the value of the active period)
Definition zigbee-nwk.h:486
bool m_routerCapacity
TRUE = The device is able to accept join requests from router-capable devices.
Definition zigbee-nwk.h:490
bool m_endDeviceCapacity
TRUE= The device is able to accept join request from end devices.
Definition zigbee-nwk.h:492
StackProfile m_stackProfile
The Zigbee stack profile identifier in use in the discovered network.
Definition zigbee-nwk.h:480
uint8_t m_logCh
The current channel number occupied by the network.
Definition zigbee-nwk.h:479
uint8_t m_beaconOrder
The beacon order value of the underlying MAC.
Definition zigbee-nwk.h:484
uint8_t m_zigbeeVersion
The version of the zigbee protocol in use in the discovered network.
Definition zigbee-nwk.h:482
uint64_t m_extPanId
The 64-bit PAN identifier of the network.
Definition zigbee-nwk.h:476
bool m_permitJoining
TRUE = Indicates that at least one zigbee router on the network currently permits joining.
Definition zigbee-nwk.h:488
NLDE-DATA.confirm params.
Definition zigbee-nwk.h:292
uint8_t m_nsduHandle
The handle associated with the NSDU being confirmed.
Definition zigbee-nwk.h:295
NwkStatus m_status
The status of the corresponding request.
Definition zigbee-nwk.h:293
Time m_txTime
The time indication for the transmitted packet based on the local clock.
Definition zigbee-nwk.h:296
NLDE-DATA.indication params.
Definition zigbee-nwk.h:306
AddressMode m_dstAddrMode
Destination address mode.
Definition zigbee-nwk.h:307
Time m_rxTime
A time indication for the received packet based on the local clock.
Definition zigbee-nwk.h:313
uint32_t m_nsduLength
The number of octets comprising the NSDU being indicated.
Definition zigbee-nwk.h:311
uint8_t m_linkQuality
LQI value delivered by the MAC on receipt of this frame.
Definition zigbee-nwk.h:312
bool m_securityUse
An indication of whether the received data is using security.
Definition zigbee-nwk.h:315
Mac16Address m_srcAddr
The individual device address from which the NSDU originated.
Definition zigbee-nwk.h:310
Mac16Address m_dstAddr
The destination address to which the NSDU was sent.
Definition zigbee-nwk.h:309
NLDE-DATA.request params.
Definition zigbee-nwk.h:324
NLME-DIRECT-JOIN.confirm params.
Definition zigbee-nwk.h:449
NwkStatus m_status
The status the corresponding request.
Definition zigbee-nwk.h:450
Mac64Address m_deviceAddr
The IEEE EUI-64 address in the request to which this is a confirmation.
Definition zigbee-nwk.h:452
NLME-DIRECT-JOIN.request params.
Definition zigbee-nwk.h:436
NLME-JOIN.confirm params.
Definition zigbee-nwk.h:539
Mac16Address m_networkAddress
The 16 bit network address that was allocated to this device.
Definition zigbee-nwk.h:542
NwkStatus m_status
The status of the corresponding request.
Definition zigbee-nwk.h:540
uint8_t m_macInterfaceIndex
The value of the MAC index from nwkMacInterfaceTable.
Definition zigbee-nwk.h:550
uint64_t m_extendedPanId
The extended 64 bit PAN ID for the network of which the device is now a member.
Definition zigbee-nwk.h:545
ChannelList m_channelList
The structure indicating the current channel of the network that has been joined.
Definition zigbee-nwk.h:547
bool m_enhancedBeacon
True if using enhanced beacons (placeholder, not supported)
Definition zigbee-nwk.h:549
NLME-JOIN.indication params.
Definition zigbee-nwk.h:571
NLME-JOIN.request params.
Definition zigbee-nwk.h:517
NLME-NETWORK-DISCOVERY.confirm params.
Definition zigbee-nwk.h:502
uint8_t m_networkCount
Gives the number of networks discovered by the search.
Definition zigbee-nwk.h:505
std::vector< NetworkDescriptor > m_netDescList
A list of descriptors, one for each of the networks discovered.
Definition zigbee-nwk.h:506
NwkStatus m_status
The status of the corresponding request.
Definition zigbee-nwk.h:503
NLME-NETWORK-DISCOVERY.request params.
Definition zigbee-nwk.h:463
NLME-NETWORK-FORMATION.confirm params.
Definition zigbee-nwk.h:394
NwkStatus m_status
The status as a result of this request.
Definition zigbee-nwk.h:395
NLME-NETWORK-FORMATION.request params.
Definition zigbee-nwk.h:349
NLME-ROUTE-DISCOVERY.confirm params.
Definition zigbee-nwk.h:421
NwkStatus m_status
The status as a result of this request.
Definition zigbee-nwk.h:422
NetworkStatusCode m_networkStatusCode
In case where.
Definition zigbee-nwk.h:424
NLME-ROUTE-DISCOVERY.request params.
Definition zigbee-nwk.h:405
NLME-START-ROUTER.confirm params.
Definition zigbee-nwk.h:603
NwkStatus m_status
The status of the corresponding request.
Definition zigbee-nwk.h:604
NLME-START-ROUTER.request params.
Definition zigbee-nwk.h:590