Fix IEEE 802.15.4 Frame Pending handling. (#139)

* Only set Frame Pending in ACK in response to a Data Request message.
* Data Request sender uses the Frame Pending value in the ACK.
This commit is contained in:
Jonathan Hui
2016-06-14 08:46:11 -07:00
committed by GitHub
parent 5084009670
commit a24bbf09c0
+127 -25
View File
@@ -56,17 +56,34 @@ enum
IEEE802154_FRAME_TYPE_MACCMD = 3 << 0,
IEEE802154_FRAME_TYPE_MASK = 7 << 0,
IEEE802154_SECURITY_ENABLED = 1 << 3,
IEEE802154_FRAME_PENDING = 1 << 4,
IEEE802154_ACK_REQUEST = 1 << 5,
IEEE802154_PANID_COMPRESSION = 1 << 6,
IEEE802154_DST_ADDR_NONE = 0 << 2,
IEEE802154_DST_ADDR_SHORT = 2 << 2,
IEEE802154_DST_ADDR_EXT = 3 << 2,
IEEE802154_DST_ADDR_MASK = 3 << 2,
IEEE802154_SRC_ADDR_NONE = 0 << 6,
IEEE802154_SRC_ADDR_SHORT = 2 << 6,
IEEE802154_SRC_ADDR_EXT = 3 << 6,
IEEE802154_SRC_ADDR_MASK = 3 << 6,
IEEE802154_DSN_OFFSET = 2,
IEEE802154_DSTPAN_OFFSET = 3,
IEEE802154_DSTADDR_OFFSET = 5,
IEEE802154_SEC_LEVEL_MASK = 7 << 0,
IEEE802154_KEY_ID_MODE_0 = 0 << 3,
IEEE802154_KEY_ID_MODE_1 = 1 << 3,
IEEE802154_KEY_ID_MODE_2 = 2 << 3,
IEEE802154_KEY_ID_MODE_3 = 3 << 3,
IEEE802154_KEY_ID_MODE_MASK = 3 << 3,
IEEE802154_MACCMD_DATA_REQ = 4,
};
typedef enum PhyState
@@ -96,7 +113,6 @@ static struct RadioMessage s_ack_message;
static RadioPacket s_receive_frame;
static RadioPacket s_transmit_frame;
static RadioPacket s_ack_frame;
static bool s_data_pending = false;
static uint8_t s_extended_address[OT_EXT_ADDRESS_SIZE];
static uint16_t s_short_address;
@@ -116,11 +132,114 @@ static inline bool isFrameTypeMacCmd(const uint8_t *frame)
return (frame[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MACCMD;
}
static inline bool isSecurityEnabled(const uint8_t *frame)
{
return (frame[0] & IEEE802154_SECURITY_ENABLED) != 0;
}
static inline bool isFramePending(const uint8_t *frame)
{
return (frame[0] & IEEE802154_FRAME_PENDING) != 0;
}
static inline bool isAckRequested(const uint8_t *frame)
{
return (frame[0] & IEEE802154_ACK_REQUEST) != 0;
}
static inline bool isPanIdCompressed(const uint8_t *frame)
{
return (frame[0] & IEEE802154_PANID_COMPRESSION) != 0;
}
static inline bool isDataRequest(const uint8_t *frame)
{
const uint8_t *cur = frame;
uint8_t securityControl;
bool rval;
// FCF + DSN
cur += 2 + 1;
VerifyOrExit(isFrameTypeMacCmd(frame), rval = false);
// Destination PAN + Address
switch (frame[1] & IEEE802154_DST_ADDR_MASK)
{
case IEEE802154_DST_ADDR_SHORT:
cur += sizeof(otPanId) + sizeof(otShortAddress);
break;
case IEEE802154_DST_ADDR_EXT:
cur += sizeof(otPanId) + sizeof(otExtAddress);
break;
default:
ExitNow(rval = false);
}
// Source PAN + Address
switch (frame[1] & IEEE802154_SRC_ADDR_MASK)
{
case IEEE802154_SRC_ADDR_SHORT:
if (!isPanIdCompressed(frame))
{
cur += sizeof(otPanId);
}
cur += sizeof(otShortAddress);
break;
case IEEE802154_SRC_ADDR_EXT:
if (!isPanIdCompressed(frame))
{
cur += sizeof(otPanId);
}
cur += sizeof(otExtAddress);
break;
default:
ExitNow(rval = false);
}
// Security Control + Frame Counter + Key Identifier
if (isSecurityEnabled(frame))
{
securityControl = *cur;
if (securityControl & IEEE802154_SEC_LEVEL_MASK)
{
cur += 1 + 4;
}
switch (securityControl & IEEE802154_KEY_ID_MODE_MASK)
{
case IEEE802154_KEY_ID_MODE_0:
cur += 0;
break;
case IEEE802154_KEY_ID_MODE_1:
cur += 1;
break;
case IEEE802154_KEY_ID_MODE_2:
cur += 5;
break;
case IEEE802154_KEY_ID_MODE_3:
cur += 9;
break;
}
}
// Command ID
rval = cur[0] == IEEE802154_MACCMD_DATA_REQ;
exit:
return rval;
}
static inline uint8_t getDsn(const uint8_t *frame)
{
return frame[IEEE802154_DSN_OFFSET];
@@ -274,7 +393,6 @@ ThreadError otPlatRadioTransmit(void)
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
s_state = kStateTransmit;
s_data_pending = false;
exit:
return error;
@@ -300,23 +418,6 @@ bool otPlatRadioGetPromiscuous(void)
return s_promiscuous;
}
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
{
ThreadError error = kThreadError_None;
VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
s_state = kStateIdle;
if (rxPending != NULL)
{
*rxPending = s_data_pending;
}
exit:
return error;
}
void radioReceive(void)
{
uint8_t tx_sequence, rx_sequence;
@@ -352,13 +453,8 @@ void radioReceive(void)
break;
}
if (isFrameTypeMacCmd(s_transmit_frame.mPsdu))
{
s_data_pending = true;
}
s_state = kStateIdle;
otPlatRadioTransmitDone(s_data_pending, kThreadError_None);
otPlatRadioTransmitDone(isFramePending(s_receive_frame.mPsdu), kThreadError_None);
break;
case kStateListen:
@@ -472,6 +568,12 @@ void radioSendAck(void)
s_ack_frame.mLength = IEEE802154_ACK_LENGTH;
s_ack_message.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
if (isDataRequest(s_receive_frame.mPsdu))
{
s_ack_message.mPsdu[0] |= IEEE802154_FRAME_PENDING;
}
s_ack_message.mPsdu[1] = 0;
s_ack_message.mPsdu[2] = getDsn(s_receive_frame.mPsdu);