diff --git a/AUTHORS b/AUTHORS index 19d403be2..2c68370b5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -230,7 +230,7 @@ Anna Poon (poon2@llnl.gov) Gauri Prasad Vikas Pushkar (vikaskupushkar@gmail.com) Philipp Raich (philipp.raich@tuwien.ac.at) -Alberto Gallegos Ramonet (ramonet@fc.ritsumei.ac.jp) +Alberto Gallegos Ramonet (alramonet@is.tokushima-u.ac.jp) Manoj Kumar Rana (manoj24.rana@gmail.com) Andrea Ranieri (andreran@uno.it) Bruno Ranieri (Yrrsinn@googlemail.com) diff --git a/CHANGES.md b/CHANGES.md index 931aea495..e6e186311 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,7 +22,8 @@ Changes from ns-3.36 to ns-3.37 ### Changes to existing API - * Adds support for channel paging to the **LrWpanPhy** (only placeholder, a single modulation/band is currently supported). +* Adds support for channel paging to the **LrWpanPhy** (only placeholder, a single modulation/band is currently supported). +* Adds supporting structures used by **LrWpanMac** (PAN descriptor, Command Payload Header, Capability Field). ### Changes to build system diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6ec66c216..0b1e1ea83 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -15,6 +15,7 @@ Release 3-dev ### New user-visible features - (lr-wpan) !959 - Add PHY channel page support +- (lr-wpan) Adds PAN descriptor, CommandPayload Header and Capability Field ### Bugs fixed diff --git a/src/lr-wpan/doc/lr-wpan.rst b/src/lr-wpan/doc/lr-wpan.rst index 58233e169..7312b197f 100644 --- a/src/lr-wpan/doc/lr-wpan.rst +++ b/src/lr-wpan/doc/lr-wpan.rst @@ -90,11 +90,38 @@ This maps to |ns3| classes and methods such as::: ... } +The primitives currently supported by the ns-3 model are: + +MAC Primitives +++++++++++++++ + +* MCPS-DATA.Request +* MCPS-DATA.Confirm +* MCPS-DATA.Indication +* MLME-START.Request +* MLME-START.Confirm + +PHY Primitives +++++++++++++++ + +* PLME-CCA.Request +* PLME-CCA.Confirm +* PD-DATA.Request +* PD-DATA.Confirm +* PD-DATA.Indication +* PLME-SET-TRX-STATE.Request +* PLME-SET-TRX-STATE.Confirm + MAC ### -The MAC at present implements the unslotted CSMA/CA variant, without beaconing. -Currently there is no support for coordinators and the relevant APIs. +The MAC at present implements both, the unslotted CSMA/CA (non-beacon mode) and +the slotted CSMA/CA (beacon-enabled mode). The beacon-enabled mode supports only +direct transmissions. Indirect transmissions and Guaranteed Time Slots (GTS) are +currently not supported. + +The present implementation supports a single PAN coordinator, support for additional +coordinators is under consideration for future releases. The implemented MAC is similar to Contiki's NullMAC, i.e., a MAC without sleep features. The radio is assumed to be always active (receiving or transmitting), @@ -219,10 +246,9 @@ Scope and Limitations ===================== Future versions of this document will contain a PICS proforma similar to -Appendix D of IEEE 802.15.4-2006. The current emphasis is on the -unslotted mode of 802.15.4 operation for use in Zigbee, and the scope -is limited to enabling a single mode (CSMA/CA) with basic data transfer -capabilities. Association with PAN coordinators is not yet supported, nor the +Appendix D of IEEE 802.15.4-2006. The current emphasis is on direct transmissions +running on both, slotted and unslotted mode (CSMA/CA) of 802.15.4 operation for use in Zigbee. +Association with PAN coordinators is not yet supported, nor the use of extended addressing. Interference is modeled as AWGN but this is currently not thoroughly tested. @@ -310,6 +336,7 @@ The following tests have been written, which can be found in ``src/lr-wpan/tests * ``lr-wpan-pd-plme-sap-test.cc``: Test the PLME and PD SAP per IEEE 802.15.4 * ``lr-wpan-spectrum-value-helper-test.cc``: Test that the conversion between power (expressed as a scalar quantity) and spectral power, and back again, falls within a 25% tolerance across the range of possible channels and input powers. * ``lr-wpan-ifs-test.cc``: Check that the Intraframe Spaces (IFS) are being used and issued in the correct order. +* ``lr-wpan-slotted-csmaca-test.cc``: Test the transmission and deferring of data packets in the Contention Access Period (CAP) for the slotted CSMA/CA (beacon-enabled mode). Validation ********** diff --git a/src/lr-wpan/model/lr-wpan-fields.cc b/src/lr-wpan/model/lr-wpan-fields.cc index 8de8fcbd9..ebbf81087 100644 --- a/src/lr-wpan/model/lr-wpan-fields.cc +++ b/src/lr-wpan/model/lr-wpan-fields.cc @@ -479,4 +479,134 @@ operator << (std::ostream &os, const PendingAddrFields &pendingAddrFields) return os; } +/*********************************************************** + * Capability Information Field + ***********************************************************/ + +CapabilityField::CapabilityField () +{ + m_deviceType = true; + m_powerSource = false; + m_receiverOnWhenIdle = true; + m_securityCap = false; + m_allocAddr = true; +} + +uint32_t +CapabilityField::GetSerializedSize (void) const +{ + return 1; +} + +Buffer::Iterator +CapabilityField::Serialize (Buffer::Iterator i) const +{ + uint8_t capability; + + capability = 0; //!< Bit 0 (reserved) + capability = (m_deviceType << 1) & (0x01 << 1); //!< Bit 1 + capability |= (m_powerSource << 2) & (0x01 << 2); //!< Bit 2 + capability |= (m_receiverOnWhenIdle << 3) & (0x01 << 3); //!< Bit 3 + //!< Bit 4-5 (reserved) + capability |= (m_securityCap << 6) & (0x01 << 6); //!< Bit 6 + capability |= (m_allocAddr << 7) & (0x01 << 7); //!< Bit 7 + i.WriteU8 (capability); + return i; +} + +Buffer::Iterator +CapabilityField::Deserialize (Buffer::Iterator i) +{ + uint8_t capability = i.ReadU8 (); + //!< Bit 0 (reserved) + m_deviceType = (capability >> 1) & (0x01); //!< Bit 1 + m_powerSource = (capability >> 2) & (0x01); //!< Bit 2 + m_receiverOnWhenIdle = (capability >> 3) & (0x01); //!< Bit 3 + //!< Bit 4-5 (reserved) + m_securityCap = (capability >> 6) & (0x01); //!< Bit 6 + m_allocAddr = (capability >> 7) & (0x01); //!< Bit 7 + + return i; +} + +bool +CapabilityField::IsDeviceTypeFfd (void) const +{ + return m_deviceType; +} + +bool +CapabilityField::IsPowSrcAvailable (void) const +{ + return m_powerSource; +} + +bool +CapabilityField::IsReceiverOnWhenIdle (void) const +{ + return m_receiverOnWhenIdle; +} + + +bool +CapabilityField::IsSecurityCapability (void) const +{ + return m_securityCap; +} + +bool +CapabilityField::IsShortAddrAllocOn (void) const +{ + return m_allocAddr; +} + +void +CapabilityField::SetFfdDevice (bool devType) +{ + m_deviceType = devType; +} + +void +CapabilityField::SetPowSrcAvailable (bool pow) +{ + m_powerSource = pow; +} + +void +CapabilityField::SetRxOnWhenIdle (bool rxIdle) +{ + m_receiverOnWhenIdle = rxIdle; +} + +void +CapabilityField::SetSecurityCap (bool sec) +{ + m_securityCap = sec; +} + +void +CapabilityField::SetShortAddrAllocOn (bool addrAlloc) +{ + m_allocAddr = addrAlloc; +} + +/** + * output stream output operator + * + * \param os output stream + * \param capabilityField the Capability Information Field + * + * \returns output stream + */ +std::ostream & +operator << (std::ostream &os, const CapabilityField &capabilityField) +{ + os << " FFD device capable = " << bool (capabilityField.IsDeviceTypeFfd ()) + << ", Alternate Power Current Available = " << bool (capabilityField.IsPowSrcAvailable ()) + << ", Receiver On When Idle = " << bool (capabilityField.IsReceiverOnWhenIdle ()) + << ", Security Capable = " << bool (capabilityField.IsSecurityCapability ()) + << ", Coordinator Allocate Short Address = " << bool (capabilityField.IsShortAddrAllocOn ()); + return os; +} + } // ns-3 namespace diff --git a/src/lr-wpan/model/lr-wpan-fields.h b/src/lr-wpan/model/lr-wpan-fields.h index 9aa812f5b..03ffba9c0 100644 --- a/src/lr-wpan/model/lr-wpan-fields.h +++ b/src/lr-wpan/model/lr-wpan-fields.h @@ -144,7 +144,6 @@ public: */ Buffer::Iterator Deserialize (Buffer::Iterator i); - private: // Superframe Specification field // See IEEE 802.14.15-2011 5.2.2.1.2 @@ -228,11 +227,11 @@ private: //GTS specification field uint8_t m_gtsSpecDescCount; //!< GTS specification field Descriptor Count (Bit 0-2) - // GTS specification field Reserved (Not necessary) (Bit 3-6) + // GTS specification field Reserved (Not necessary) (Bit 3-6) uint8_t m_gtsSpecPermit; //!< GTS specification field GTS Permit (Bit 7) //GTS Direction field uint8_t m_gtsDirMask; //!< GTS Direction field Directions Mask (Bit 0-6) - // GTS Direction field Reserved (Not Necessary) (Bit 7) + // GTS Direction field Reserved (Not Necessary) (Bit 7) //GTS List gtsDescriptor m_gtsList[7]; //!< GTS List field (maximum descriptors stored == 7) }; @@ -343,6 +342,98 @@ private: std::ostream &operator << (std::ostream &os, const PendingAddrFields &pendingAddrFields); +/** + * \ingroup lr-wpan + * + * Represent the Capability Information Field. + * See IEEE 802.15.4-2011 Section 5.3.1.2 Figure 50 + */ +class CapabilityField +{ + +public: + CapabilityField (); + /** + * Get the size of the serialized Capability Information Field. + * \return the size of the serialized field. + */ + uint32_t GetSerializedSize (void) const; + /** + * Serialize the entire Capability Information Field. + * \param i an iterator which points to where the Capability information field should be written. + * \return an iterator. + */ + Buffer::Iterator Serialize (Buffer::Iterator i) const; + /** + * Deserialize the entire Capability Information Field. + * \param i an iterator which points to where the Capability information field should be read. + * \return an iterator. + */ + Buffer::Iterator Deserialize (Buffer::Iterator i); + /** + * True if the device type is a Full Functional Device (FFD) false if is a Reduced Functional Device (RFD). + */ + bool IsDeviceTypeFfd (void) const; + /** + * True if the device is receiving power from alternating current mains. + * \return True if the device is receiving power from alternating current mains. + */ + bool IsPowSrcAvailable (void) const; + /** + * True if the device does not disable its receiver to conserve power during idle periods. + * \return True if the device does not disable its receiver to conserve power during idle periods. + */ + bool IsReceiverOnWhenIdle (void) const; + /** + * True if the device is capable of sending and receiving cryptographically protected MAC frames. + * \return True if the device is capable of sending and receiving cryptographically protected MAC frames. + */ + bool IsSecurityCapability (void) const; + /** + * True if the device wishes the coordinator to allocate a short address as result of the association procedure. + * \return True if the device wishes the coordinator to allocate a short address as result of the association procedure. + */ + bool IsShortAddrAllocOn (void) const; + /** + * Set the Device type in the Capability Information Field. + * True = full functional device (FFD) False = reduced functional device (RFD). + * \param devType The device type described in the Capability Information Field. + */ + void SetFfdDevice (bool devType); + /** + * Set the Power Source available flag in the Capability Information Field. + * \param pow Set true if a Power Source is available in the Capability Information Field. + */ + void SetPowSrcAvailable (bool pow); + /** + * Indicate if the receiver is On on Idle + * \param rxIdle Set true if the receiver is on when Idle + */ + void SetRxOnWhenIdle (bool rxIdle); + /** + * Set the Security Capability flag in the Capability Information Field. + * \param sec Set true if the device have Security Capabilities. + */ + void SetSecurityCap (bool sec); + /** + * Set the Short Address Flag in the Capability Information Field. + * \param addrAlloc Describes whether or not the coordinator should allocate a short + * address in the association process. + */ + void SetShortAddrAllocOn (bool addrAlloc); + +private: + + bool m_deviceType; //!< Capability Information Field, Device Type (bit 1) + bool m_powerSource; //!< Capability Information Field, Power Source (bit 2) + bool m_receiverOnWhenIdle; //!< Capability Information Field, Receiver On When Idle (bit 3) + bool m_securityCap; //!< Capability Information Field, Security Capability (bit 6) + bool m_allocAddr; //!< Capability Information Field, Allocate Address (bit 7) + +}; +std::ostream &operator << (std::ostream &os, const CapabilityField &capabilityField); + + } //end namespace ns3 #endif /* LR_WPAN_FIELDS_H */ diff --git a/src/lr-wpan/model/lr-wpan-mac-pl-headers.cc b/src/lr-wpan/model/lr-wpan-mac-pl-headers.cc index be0b4daa6..b68919a9f 100644 --- a/src/lr-wpan/model/lr-wpan-mac-pl-headers.cc +++ b/src/lr-wpan/model/lr-wpan-mac-pl-headers.cc @@ -20,6 +20,7 @@ #include "lr-wpan-mac-pl-headers.h" #include +#include namespace ns3 { @@ -28,8 +29,7 @@ namespace ns3 { ***********************************************************/ BeaconPayloadHeader::BeaconPayloadHeader () -{ -} +{} NS_OBJECT_ENSURE_REGISTERED (BeaconPayloadHeader); @@ -137,7 +137,6 @@ CommandPayloadHeader::CommandPayloadHeader () SetCommandFrameType (CMD_RESERVED); } - CommandPayloadHeader::CommandPayloadHeader (enum MacCommand macCmd) { SetCommandFrameType (macCmd); @@ -166,7 +165,32 @@ uint32_t CommandPayloadHeader::GetSerializedSize (void) const { uint32_t size = 1; - + // TODO: add missing serialize commands size when other commands are added. + switch (m_cmdFrameId) + { + case ASSOCIATION_REQ: + size += m_capabilityInfo.GetSerializedSize (); + break; + case ASSOCIATION_RESP: + size += 3; // (short address + Association Status) + break; + case DISASSOCIATION_NOTIF: + break; + case DATA_REQ: + break; + case PANID_CONFLICT: + break; + case ORPHAN_NOTIF: + break; + case BEACON_REQ: + break; + case COOR_REALIGN: + break; + case GTS_REQ: + break; + case CMD_RESERVED: + break; + } return size; } @@ -175,13 +199,67 @@ CommandPayloadHeader::Serialize (Buffer::Iterator start) const { Buffer::Iterator i = start; i.WriteU8 (m_cmdFrameId); + // TODO: add missing serialize commands when other commands are added. + switch (m_cmdFrameId) + { + case ASSOCIATION_REQ: + i = m_capabilityInfo.Serialize (i); + break; + case ASSOCIATION_RESP: + WriteTo (i,m_shortAddr); + i.WriteU8 (m_assocStatus); + break; + case DISASSOCIATION_NOTIF: + break; + case DATA_REQ: + break; + case PANID_CONFLICT: + break; + case ORPHAN_NOTIF: + break; + case BEACON_REQ: + break; + case COOR_REALIGN: + break; + case GTS_REQ: + break; + case CMD_RESERVED: + break; + } } uint32_t CommandPayloadHeader::Deserialize (Buffer::Iterator start) { Buffer::Iterator i = start; - m_cmdFrameId = i.ReadU8 (); + m_cmdFrameId = static_cast (i.ReadU8 ()); + // TODO: add missing deserialize commands when other commands are added. + switch (m_cmdFrameId) + { + case ASSOCIATION_REQ: + i = m_capabilityInfo.Deserialize (i); + break; + case ASSOCIATION_RESP: + ReadFrom (i, m_shortAddr); + m_assocStatus = static_cast (i.ReadU8 ()); + break; + case DISASSOCIATION_NOTIF: + break; + case DATA_REQ: + break; + case PANID_CONFLICT: + break; + case ORPHAN_NOTIF: + break; + case BEACON_REQ: + break; + case COOR_REALIGN: + break; + case GTS_REQ: + break; + case CMD_RESERVED: + break; + } return i.GetDistanceFrom (start); } @@ -190,6 +268,36 @@ void CommandPayloadHeader::Print (std::ostream &os) const { os << "| MAC Command Frame ID | = " << (uint32_t) m_cmdFrameId; + switch (m_cmdFrameId) + { + case ASSOCIATION_REQ: + os << "| Device Type FFD | = " << m_capabilityInfo.IsDeviceTypeFfd () + << "| Alternative Power Source available | = " << m_capabilityInfo.IsPowSrcAvailable () + << "| Receiver on when Idle | = " << m_capabilityInfo.IsReceiverOnWhenIdle () + << "| Security capable | = " << m_capabilityInfo.IsSecurityCapability () + << "| Allocate address on | = " << m_capabilityInfo.IsShortAddrAllocOn (); + break; + case ASSOCIATION_RESP: + os << "| Assigned Short Address | = " << m_shortAddr + << "| Status Response | = " << m_assocStatus; + break; + case DISASSOCIATION_NOTIF: + break; + case DATA_REQ: + break; + case PANID_CONFLICT: + break; + case ORPHAN_NOTIF: + break; + case BEACON_REQ: + break; + case COOR_REALIGN: + break; + case GTS_REQ: + break; + case CMD_RESERVED: + break; + } } void @@ -198,43 +306,84 @@ CommandPayloadHeader::SetCommandFrameType (MacCommand macCommand) m_cmdFrameId = macCommand; } +void +CommandPayloadHeader::SetCapabilityField (CapabilityField cap) +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_REQ); + m_capabilityInfo = cap; +} CommandPayloadHeader::MacCommand CommandPayloadHeader::GetCommandFrameType (void) const { switch (m_cmdFrameId) { - case 0x01: - return ASSOCIATION_REQ; - break; - case 0x02: - return ASSOCIATION_RESP; - break; - case 0x03: - return DISASSOCIATION_NOTIF; - break; - case 0x04: - return DATA_REQ; - break; - case 0x05: - return PANID_CONFLICT; - break; - case 0x06: - return ORPHAN_NOTIF; - break; - case 0x07: - return BEACON_REQ; - break; - case 0x08: - return COOR_REALIGN; - break; - case 0x09: - return GTS_REQ; - break; - default: - return CMD_RESERVED; + case 0x01: + return ASSOCIATION_REQ; + break; + case 0x02: + return ASSOCIATION_RESP; + break; + case 0x03: + return DISASSOCIATION_NOTIF; + break; + case 0x04: + return DATA_REQ; + break; + case 0x05: + return PANID_CONFLICT; + break; + case 0x06: + return ORPHAN_NOTIF; + break; + case 0x07: + return BEACON_REQ; + break; + case 0x08: + return COOR_REALIGN; + break; + case 0x09: + return GTS_REQ; + break; + default: + return CMD_RESERVED; } } +void +CommandPayloadHeader::SetShortAddr (Mac16Address shortAddr) +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_RESP); + m_shortAddr = shortAddr; +} + +void +CommandPayloadHeader::SetAssociationStatus (AssocStatus status) +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_RESP); + m_assocStatus = status; +} + +Mac16Address +CommandPayloadHeader::GetShortAddr (void) const +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_RESP); + return m_shortAddr; +} + +CommandPayloadHeader::AssocStatus +CommandPayloadHeader::GetAssociationStatus (void) const +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_RESP); + return m_assocStatus; +} + +CapabilityField +CommandPayloadHeader::GetCapabilityField (void) const +{ + NS_ASSERT (m_cmdFrameId == ASSOCIATION_REQ); + return m_capabilityInfo; +} + } // ns3 namespace diff --git a/src/lr-wpan/model/lr-wpan-mac-pl-headers.h b/src/lr-wpan/model/lr-wpan-mac-pl-headers.h index b311e407a..4eac14c35 100644 --- a/src/lr-wpan/model/lr-wpan-mac-pl-headers.h +++ b/src/lr-wpan/model/lr-wpan-mac-pl-headers.h @@ -125,7 +125,16 @@ public: GTS_REQ = 0x09, //!< GTS Request (RFD true: none) CMD_RESERVED = 0xff //!< Reserved }; - + /** + * Association Status Field values. + * See IEEE 802.15.4-2011, Table 6 + */ + enum AssocStatus + { + SUCCESSFUL = 0x00, //!< Association successful + FULL_CAPACITY = 0x01, //!< PAN at capacity + ACCESS_DENIED = 0x02 //!< PAN access denied + }; CommandPayloadHeader (void); /** @@ -150,15 +159,47 @@ public: */ void SetCommandFrameType (MacCommand macCmd); /** - * Get the command frame type - * \return the command frame type + * Set the Capability Information Field to the command payload header (Association Request Command). + * \param cap The capability Information field + */ + void SetCapabilityField (CapabilityField cap); + /** + * Set the Short Address Assigned by the coordinator (Association Response Command). + * \param shortAddr The short address assigned by the coordinator + */ + void SetShortAddr (Mac16Address shortAddr); + /** + * Set status resulting from the association attempt (Association Response Command). + * \param status The status resulting from the association attempt + */ + void SetAssociationStatus (AssocStatus status); + /** + * Get the Short address assigned by the coordinator (Association Response Command). + * \return The Mac16Address assigned by the coordinator + */ + Mac16Address GetShortAddr (void) const; + /** + * Get the status resulting from an association request (Association Response Command). + * \return The resulting status from an association request + */ + AssocStatus GetAssociationStatus (void) const; + /** + * Get the command frame type ID + * \return The command type ID from the command payload header */ MacCommand GetCommandFrameType (void) const; - + /** + * Get the Capability Information Field from the command payload header. (Association Request Command) + * \return The Capability Information Field + */ + CapabilityField GetCapabilityField (void) const; private: - /** The command Frame Identifier*/ - uint8_t m_cmdFrameId; + + MacCommand m_cmdFrameId; //!< The command Frame Identifier + CapabilityField m_capabilityInfo; //!< Capability Information Field (Association Request Command) + Mac16Address m_shortAddr; //!< Contains the short address assigned by the coordinator (Association Response Command) See IEEE 802.15.4-2011 5.3.2.2. + AssocStatus m_assocStatus; //!< Association Status (Association Response Command) }; diff --git a/src/lr-wpan/model/lr-wpan-mac.h b/src/lr-wpan/model/lr-wpan-mac.h index c009b7658..0c05cc0e2 100644 --- a/src/lr-wpan/model/lr-wpan-mac.h +++ b/src/lr-wpan/model/lr-wpan-mac.h @@ -228,6 +228,25 @@ typedef enum MLMEPOLL_INVALID_PARAMETER = 9 } LrWpanMlmePollConfirmStatus; +/** + * \ingroup lr-wpan + * + * PAN Descriptor, Table 17 IEEE 802.15.4-2011 + */ +struct PanDescriptor +{ + LrWpanAddressMode m_coorAddrMode; //!< The coordinator addressing mode corresponding to the received beacon frame. + uint16_t m_coorPanId; //!< The PAN ID of the coordinator as specified in the received beacon frame. + Mac16Address m_coorShortAddr; //!< The coordinator short address as specified in the coordinator address mode. + Mac64Address m_coorExtAddr; //!< The coordinator extended address as specified in the coordinator address mode. + uint8_t m_logCh; //!< The current channel number occupied by the network. + uint8_t m_logChPage; //!< The current channel page occupied by the network. + SuperframeField m_superframeSpec; //!< The superframe specification as specified in the received beacon frame. + bool m_gtsPermit; //!< TRUE if the beacon is from the PAN coordinator that is accepting GTS requests. + uint8_t m_linkQuality; //!< The LQI at which the network beacon was received. Lower values represent lower LQI. + Time m_timeStamp; //!< Beacon frame reception time. Used as Time data type in ns-3 to avoid precision problems. +}; + /** * \ingroup lr-wpan *