mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 09:57:47 +00:00
Require radio driver to provide transmit and receive buffers. (#87)
Some radio chips have memory-mapped regions for transmit and receive buffers. This change allows the radio driver to pass those buffers, when available, directly to upper layers and avoid unnecessary copies.
This commit is contained in:
@@ -65,19 +65,22 @@ enum PhyState
|
||||
struct RadioMessage
|
||||
{
|
||||
uint8_t mChannel;
|
||||
uint8_t mPsdu[Mac::Frame::kMTU];
|
||||
uint8_t mPsdu[kMaxPHYPacketSize];
|
||||
} __attribute__((packed));
|
||||
|
||||
static void radioSendAck(void);
|
||||
static void radioProcessFrame(void);
|
||||
|
||||
static PhyState s_state = kStateDisabled;
|
||||
static RadioPacket *s_receive_frame = NULL;
|
||||
static RadioPacket *s_transmit_frame = NULL;
|
||||
static RadioPacket m_ack_packet;
|
||||
static RadioMessage s_receive_message;
|
||||
static RadioMessage s_transmit_message;
|
||||
static 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[8];
|
||||
static uint8_t s_extended_address[OT_EXT_ADDRESS_SIZE];
|
||||
static uint16_t s_short_address;
|
||||
static uint16_t s_panid;
|
||||
|
||||
@@ -93,7 +96,7 @@ ThreadError otPlatRadioSetExtendedAddress(uint8_t *address)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(s_extended_address); i++)
|
||||
{
|
||||
s_extended_address[i] = address[7 - i];
|
||||
s_extended_address[i] = address[sizeof(s_extended_address) - 1 - i];
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
@@ -115,6 +118,10 @@ void PlatformRadioInit(void)
|
||||
|
||||
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
s_receive_frame.mPsdu = s_receive_message.mPsdu;
|
||||
s_transmit_frame.mPsdu = s_transmit_message.mPsdu;
|
||||
s_ack_frame.mPsdu = s_ack_message.mPsdu;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable(void)
|
||||
@@ -173,25 +180,29 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioReceive(RadioPacket *packet)
|
||||
ThreadError otPlatRadioReceive(uint8_t aChannel)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateListen;
|
||||
s_receive_frame = packet;
|
||||
s_receive_frame.mChannel = aChannel;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
RadioPacket *otPlatRadioGetTransmitBuffer(void)
|
||||
{
|
||||
return &s_transmit_frame;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateTransmit;
|
||||
s_transmit_frame = packet;
|
||||
s_data_pending = false;
|
||||
|
||||
exit:
|
||||
@@ -227,8 +238,6 @@ exit:
|
||||
|
||||
void radioReceive(void)
|
||||
{
|
||||
RadioPacket receive_frame;
|
||||
RadioMessage message;
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
uint8_t command_id;
|
||||
int rval;
|
||||
@@ -236,7 +245,7 @@ void radioReceive(void)
|
||||
VerifyOrExit(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen ||
|
||||
s_state == kStateAckWait, ;);
|
||||
|
||||
rval = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
|
||||
rval = recvfrom(s_sockfd, &s_receive_message, sizeof(s_receive_message), 0, NULL, NULL);
|
||||
assert(rval >= 0);
|
||||
|
||||
switch (s_state)
|
||||
@@ -248,25 +257,24 @@ void radioReceive(void)
|
||||
break;
|
||||
|
||||
case kStateAckWait:
|
||||
receive_frame.mLength = rval - 1;
|
||||
memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
|
||||
s_receive_frame.mLength = rval - 1;
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
if (reinterpret_cast<Mac::Frame *>(&s_receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(&s_transmit_frame)->GetSequence();
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&s_receive_frame)->GetSequence();
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
if (reinterpret_cast<Mac::Frame *>(&s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
|
||||
reinterpret_cast<Mac::Frame *>(&s_transmit_frame)->GetCommandId(command_id);
|
||||
|
||||
if (command_id == Mac::Frame::kMacCmdDataRequest)
|
||||
{
|
||||
@@ -279,14 +287,13 @@ void radioReceive(void)
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
if (s_receive_frame->mChannel != message.mChannel)
|
||||
if (s_receive_frame.mChannel != s_receive_message.mChannel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s_state = kStateReceive;
|
||||
s_receive_frame->mLength = rval - 1;
|
||||
memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
|
||||
s_receive_frame.mLength = rval - 1;
|
||||
|
||||
radioProcessFrame();
|
||||
break;
|
||||
@@ -303,15 +310,13 @@ exit:
|
||||
int radioTransmit(void)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
RadioMessage message;
|
||||
int rval = 0;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
message.mChannel = s_transmit_frame->mChannel;
|
||||
memcpy(message.mPsdu, s_transmit_frame->mPsdu, s_transmit_frame->mLength);
|
||||
s_transmit_message.mChannel = s_transmit_frame.mChannel;
|
||||
|
||||
for (unsigned i = 1; i < 34; i++)
|
||||
{
|
||||
@@ -321,12 +326,12 @@ int radioTransmit(void)
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
rval = sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr,
|
||||
rval = sendto(s_sockfd, &s_transmit_message, 1 + s_transmit_frame.mLength, 0, (struct sockaddr *)&sockaddr,
|
||||
sizeof(sockaddr));
|
||||
assert(rval >= 0);
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
|
||||
if (reinterpret_cast<Mac::Frame *>(&s_transmit_frame)->GetAckRequest())
|
||||
{
|
||||
s_state = kStateAckWait;
|
||||
}
|
||||
@@ -382,13 +387,12 @@ void PlatformRadioProcess(void)
|
||||
void radioSendAck(void)
|
||||
{
|
||||
Mac::Frame *ack_frame;
|
||||
RadioMessage message;
|
||||
uint8_t sequence;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
sequence = reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetSequence();
|
||||
sequence = reinterpret_cast<Mac::Frame *>(&s_receive_frame)->GetSequence();
|
||||
|
||||
ack_frame = reinterpret_cast<Mac::Frame *>(&m_ack_packet);
|
||||
ack_frame = reinterpret_cast<Mac::Frame *>(&s_ack_frame);
|
||||
ack_frame->InitMacHeader(Mac::Frame::kFcfFrameAck, Mac::Frame::kSecNone);
|
||||
ack_frame->SetSequence(sequence);
|
||||
|
||||
@@ -396,8 +400,7 @@ void radioSendAck(void)
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
message.mChannel = s_receive_frame->mChannel;
|
||||
memcpy(message.mPsdu, m_ack_packet.mPsdu, m_ack_packet.mLength);
|
||||
s_ack_message.mChannel = s_receive_frame.mChannel;
|
||||
|
||||
for (unsigned i = 1; i < 34; i++)
|
||||
{
|
||||
@@ -407,7 +410,7 @@ void radioSendAck(void)
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, &message, 1 + m_ack_packet.mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
sendto(s_sockfd, &s_ack_message, 1 + s_ack_frame.mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +421,7 @@ void radioProcessFrame(void)
|
||||
uint16_t dstpan;
|
||||
Mac::Address dstaddr;
|
||||
|
||||
receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
|
||||
receive_frame = reinterpret_cast<Mac::Frame *>(&s_receive_frame);
|
||||
receive_frame->GetDstAddr(dstaddr);
|
||||
|
||||
switch (dstaddr.mLength)
|
||||
@@ -444,11 +447,11 @@ void radioProcessFrame(void)
|
||||
ExitNow(error = kThreadError_Abort);
|
||||
}
|
||||
|
||||
s_receive_frame->mPower = -20;
|
||||
s_receive_frame->mLqi = kPhyNoLqi;
|
||||
s_receive_frame.mPower = -20;
|
||||
s_receive_frame.mLqi = kPhyNoLqi;
|
||||
|
||||
// generate acknowledgment
|
||||
if (reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetAckRequest())
|
||||
if (reinterpret_cast<Mac::Frame *>(&s_receive_frame)->GetAckRequest())
|
||||
{
|
||||
radioSendAck();
|
||||
}
|
||||
@@ -460,7 +463,12 @@ exit:
|
||||
s_state = kStateIdle;
|
||||
}
|
||||
|
||||
otPlatRadioReceiveDone(error);
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
receive_frame = NULL;
|
||||
}
|
||||
|
||||
otPlatRadioReceiveDone(receive_frame, error);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+24
-18
@@ -95,12 +95,12 @@ typedef enum otRadioCaps
|
||||
*/
|
||||
typedef struct RadioPacket
|
||||
{
|
||||
uint8_t mLength; ///< Length of the PSDU.
|
||||
uint8_t mPsdu[kMaxPHYPacketSize]; ///< The PSDU.
|
||||
uint8_t mChannel; ///< Channel used to transmit/receive the frame.
|
||||
int8_t mPower; ///< Transmit/receive power in dBm.
|
||||
uint8_t mLqi; ///< Link Quality Indicator for received frames.
|
||||
bool mSecurityValid; ///< Security Enabled flag is set and frame passes security checks.
|
||||
uint8_t *mPsdu; ///< The PSDU.
|
||||
uint8_t mLength; ///< Length of the PSDU.
|
||||
uint8_t mChannel; ///< Channel used to transmit/receive the frame.
|
||||
int8_t mPower; ///< Transmit/receive power in dBm.
|
||||
uint8_t mLqi; ///< Link Quality Indicator for received frames.
|
||||
bool mSecurityValid; ///< Security Enabled flag is set and frame passes security checks.
|
||||
} RadioPacket;
|
||||
|
||||
/**
|
||||
@@ -208,14 +208,12 @@ ThreadError otPlatRadioIdle(void);
|
||||
* 2. Remain in Receive until a packet is received or reception is aborted.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
* @param[in] aChannel The channel to use for receiving.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Receive.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Receive.
|
||||
*/
|
||||
ThreadError otPlatRadioReceive(RadioPacket *aPacket);
|
||||
ThreadError otPlatRadioReceive(uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* The radio driver calls this method to notify OpenThread of a received packet.
|
||||
@@ -224,26 +222,34 @@ ThreadError otPlatRadioReceive(RadioPacket *aPacket);
|
||||
* was aborted and a frame was not received.
|
||||
*
|
||||
*/
|
||||
extern void otPlatRadioReceiveDone(ThreadError error);
|
||||
extern void otPlatRadioReceiveDone(RadioPacket *aPacket, ThreadError error);
|
||||
|
||||
/**
|
||||
* Begins the transmit sequence on the radio.
|
||||
* This method returns a pointer to the transmit buffer.
|
||||
*
|
||||
* The caller forms the IEEE 802.15.4 frame in this buffer then calls otPlatRadioTransmit() to request transmission.
|
||||
*
|
||||
* @returns A pointer to the transmit buffer.
|
||||
*
|
||||
*/
|
||||
RadioPacket *otPlatRadioGetTransmitBuffer(void);
|
||||
|
||||
/**
|
||||
* This method begins the transmit sequence on the radio.
|
||||
*
|
||||
* The caller must form the IEEE 802.15.4 frame in the buffer provided by otPlatRadioGetTransmitBuffer() before requesting
|
||||
* transmission. The channel and transmit power are also included in the RadioPacket structure.
|
||||
*
|
||||
* The transmit sequence consists of:
|
||||
* 1. Transitioning the radio to Transmit from Idle.
|
||||
* 2. Transmits the psdu on the given channel and at the given transmit power.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
* @note The transmit power is specified in @p aPacket.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Transmit.
|
||||
* @retval ::kThreadError_InvalidArgs One or more parameters in @p aPacket are invalid.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Transmit.
|
||||
*/
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *aPacket);
|
||||
ThreadError otPlatRadioTransmit(void);
|
||||
|
||||
/**
|
||||
* The radio driver calls this method to notify OpenThread that the transmission has completed.
|
||||
|
||||
@@ -135,7 +135,7 @@ ThreadError Serial::ProcessCommand(void)
|
||||
int Serial::Output(const char *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
uint16_t remaining = kTxBufferSize - mTxLength;
|
||||
uint16_t tail = (mTxHead + mTxLength) % kTxBufferSize;
|
||||
uint16_t tail;
|
||||
|
||||
if (aBufLength > remaining)
|
||||
{
|
||||
@@ -170,7 +170,7 @@ void Serial::Send(void)
|
||||
{
|
||||
VerifyOrExit(mSendLength == 0, ;);
|
||||
|
||||
if (mTxHead + mTxLength > kTxBufferSize)
|
||||
if (mTxLength > kTxBufferSize - mTxHead)
|
||||
{
|
||||
mSendLength = kTxBufferSize - mTxHead;
|
||||
}
|
||||
|
||||
+61
-63
@@ -289,15 +289,13 @@ void Mac::NextOperation(void)
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
mReceiveFrame.SetChannel(mScanChannel);
|
||||
otPlatRadioReceive(&mReceiveFrame);
|
||||
otPlatRadioReceive(mScanChannel);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (mRxOnWhenIdle || mReceiveTimer.IsRunning())
|
||||
{
|
||||
mReceiveFrame.SetChannel(mChannel);
|
||||
otPlatRadioReceive(&mReceiveFrame);
|
||||
otPlatRadioReceive(mChannel);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -389,34 +387,33 @@ void Mac::HandleBeginTransmit(void *aContext)
|
||||
obj->HandleBeginTransmit();
|
||||
}
|
||||
|
||||
void Mac::ProcessTransmitSecurity(void)
|
||||
void Mac::ProcessTransmitSecurity(Frame &aFrame)
|
||||
{
|
||||
uint8_t securityLevel;
|
||||
uint8_t nonce[kNonceSize];
|
||||
uint8_t tagLength;
|
||||
Crypto::AesCcm aesCcm;
|
||||
|
||||
if (mSendFrame.GetSecurityEnabled() == false)
|
||||
if (aFrame.GetSecurityEnabled() == false)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mSendFrame.GetSecurityLevel(securityLevel);
|
||||
mSendFrame.SetFrameCounter(mKeyManager.GetMacFrameCounter());
|
||||
aFrame.GetSecurityLevel(securityLevel);
|
||||
aFrame.SetFrameCounter(mKeyManager.GetMacFrameCounter());
|
||||
|
||||
mSendFrame.SetKeyId((mKeyManager.GetCurrentKeySequence() & 0x7f) + 1);
|
||||
aFrame.SetKeyId((mKeyManager.GetCurrentKeySequence() & 0x7f) + 1);
|
||||
|
||||
GenerateNonce(mExtAddress, mKeyManager.GetMacFrameCounter(), securityLevel, nonce);
|
||||
|
||||
aesCcm.SetKey(mKeyManager.GetCurrentMacKey(), 16);
|
||||
tagLength = mSendFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
tagLength = aFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
|
||||
aesCcm.Init(mSendFrame.GetHeaderLength(), mSendFrame.GetPayloadLength(), tagLength,
|
||||
nonce, sizeof(nonce));
|
||||
aesCcm.Init(aFrame.GetHeaderLength(), aFrame.GetPayloadLength(), tagLength, nonce, sizeof(nonce));
|
||||
|
||||
aesCcm.Header(mSendFrame.GetHeader(), mSendFrame.GetHeaderLength());
|
||||
aesCcm.Payload(mSendFrame.GetPayload(), mSendFrame.GetPayload(), mSendFrame.GetPayloadLength(), true);
|
||||
aesCcm.Finalize(mSendFrame.GetFooter(), &tagLength);
|
||||
aesCcm.Header(aFrame.GetHeader(), aFrame.GetHeaderLength());
|
||||
aesCcm.Payload(aFrame.GetPayload(), aFrame.GetPayload(), aFrame.GetPayloadLength(), true);
|
||||
aesCcm.Finalize(aFrame.GetFooter(), &tagLength);
|
||||
|
||||
mKeyManager.IncrementMacFrameCounter();
|
||||
|
||||
@@ -426,6 +423,7 @@ exit:
|
||||
|
||||
void Mac::HandleBeginTransmit(void)
|
||||
{
|
||||
Frame &sendFrame(*static_cast<Frame *>(otPlatRadioGetTransmitBuffer()));
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (otPlatRadioIdle() != kThreadError_None)
|
||||
@@ -437,21 +435,21 @@ void Mac::HandleBeginTransmit(void)
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
mSendFrame.SetChannel(mScanChannel);
|
||||
SendBeaconRequest(mSendFrame);
|
||||
mSendFrame.SetSequence(0);
|
||||
sendFrame.SetChannel(mScanChannel);
|
||||
SendBeaconRequest(sendFrame);
|
||||
sendFrame.SetSequence(0);
|
||||
break;
|
||||
|
||||
case kStateTransmitBeacon:
|
||||
mSendFrame.SetChannel(mChannel);
|
||||
SendBeacon(mSendFrame);
|
||||
mSendFrame.SetSequence(mBeaconSequence++);
|
||||
sendFrame.SetChannel(mChannel);
|
||||
SendBeacon(sendFrame);
|
||||
sendFrame.SetSequence(mBeaconSequence++);
|
||||
break;
|
||||
|
||||
case kStateTransmitData:
|
||||
mSendFrame.SetChannel(mChannel);
|
||||
SuccessOrExit(error = mSendHead->HandleFrameRequest(mSendFrame));
|
||||
mSendFrame.SetSequence(mDataSequence);
|
||||
sendFrame.SetChannel(mChannel);
|
||||
SuccessOrExit(error = mSendHead->HandleFrameRequest(sendFrame));
|
||||
sendFrame.SetSequence(mDataSequence);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -460,11 +458,11 @@ void Mac::HandleBeginTransmit(void)
|
||||
}
|
||||
|
||||
// Security Processing
|
||||
ProcessTransmitSecurity();
|
||||
ProcessTransmitSecurity(sendFrame);
|
||||
|
||||
SuccessOrExit(error = otPlatRadioTransmit(&mSendFrame));
|
||||
SuccessOrExit(error = otPlatRadioTransmit());
|
||||
|
||||
if (mSendFrame.GetAckRequest() && !(otPlatRadioGetCaps() & kRadioCapsAckTimeout))
|
||||
if (sendFrame.GetAckRequest() && !(otPlatRadioGetCaps() & kRadioCapsAckTimeout))
|
||||
{
|
||||
mAckTimer.Start(kAckTimeout);
|
||||
otLogDebgMac("ack timer start\n");
|
||||
@@ -587,6 +585,7 @@ void Mac::HandleReceiveTimer(void)
|
||||
|
||||
void Mac::SentFrame(bool aAcked)
|
||||
{
|
||||
Frame &sendFrame(*static_cast<Frame *>(otPlatRadioGetTransmitBuffer()));
|
||||
Address destination;
|
||||
Neighbor *neighbor;
|
||||
Sender *sender;
|
||||
@@ -602,9 +601,9 @@ void Mac::SentFrame(bool aAcked)
|
||||
break;
|
||||
|
||||
case kStateTransmitData:
|
||||
if (mSendFrame.GetAckRequest() && !aAcked)
|
||||
if (sendFrame.GetAckRequest() && !aAcked)
|
||||
{
|
||||
otDumpDebgMac("NO ACK", mSendFrame.GetHeader(), 16);
|
||||
otDumpDebgMac("NO ACK", sendFrame.GetHeader(), 16);
|
||||
|
||||
if (mTransmitAttempts < kMaxFrameAttempts)
|
||||
{
|
||||
@@ -613,7 +612,7 @@ void Mac::SentFrame(bool aAcked)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mSendFrame.GetDstAddr(destination);
|
||||
sendFrame.GetDstAddr(destination);
|
||||
|
||||
if ((neighbor = mMle.GetNeighbor(destination)) != NULL)
|
||||
{
|
||||
@@ -632,7 +631,7 @@ void Mac::SentFrame(bool aAcked)
|
||||
}
|
||||
|
||||
mDataSequence++;
|
||||
sender->HandleSentFrame(mSendFrame);
|
||||
sender->HandleSentFrame(sendFrame);
|
||||
|
||||
ScheduleNextTransmission();
|
||||
break;
|
||||
@@ -646,7 +645,7 @@ exit:
|
||||
{}
|
||||
}
|
||||
|
||||
ThreadError Mac::ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeighbor)
|
||||
ThreadError Mac::ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t securityLevel;
|
||||
@@ -659,23 +658,23 @@ ThreadError Mac::ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeig
|
||||
const uint8_t *macKey;
|
||||
Crypto::AesCcm aesCcm;
|
||||
|
||||
mReceiveFrame.SetSecurityValid(false);
|
||||
aFrame.SetSecurityValid(false);
|
||||
|
||||
if (mReceiveFrame.GetSecurityEnabled() == false)
|
||||
if (aFrame.GetSecurityEnabled() == false)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(aNeighbor != NULL, error = kThreadError_Security);
|
||||
|
||||
mReceiveFrame.GetSecurityLevel(securityLevel);
|
||||
mReceiveFrame.GetFrameCounter(frameCounter);
|
||||
aFrame.GetSecurityLevel(securityLevel);
|
||||
aFrame.GetFrameCounter(frameCounter);
|
||||
|
||||
GenerateNonce(aSrcAddr.mExtAddress, frameCounter, securityLevel, nonce);
|
||||
|
||||
tagLength = mReceiveFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
tagLength = aFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
|
||||
mReceiveFrame.GetKeyId(keyid);
|
||||
aFrame.GetKeyId(keyid);
|
||||
keyid--;
|
||||
|
||||
if (keyid == (mKeyManager.GetCurrentKeySequence() & 0x7f))
|
||||
@@ -705,21 +704,19 @@ ThreadError Mac::ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeig
|
||||
{
|
||||
for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
|
||||
{
|
||||
receiver->HandleReceivedFrame(mReceiveFrame, kThreadError_Security);
|
||||
receiver->HandleReceivedFrame(aFrame, kThreadError_Security);
|
||||
}
|
||||
|
||||
ExitNow(error = kThreadError_Security);
|
||||
}
|
||||
|
||||
aesCcm.SetKey(macKey, 16);
|
||||
aesCcm.Init(mReceiveFrame.GetHeaderLength(), mReceiveFrame.GetPayloadLength(),
|
||||
tagLength, nonce, sizeof(nonce));
|
||||
aesCcm.Header(mReceiveFrame.GetHeader(), mReceiveFrame.GetHeaderLength());
|
||||
aesCcm.Payload(mReceiveFrame.GetPayload(), mReceiveFrame.GetPayload(), mReceiveFrame.GetPayloadLength(),
|
||||
false);
|
||||
aesCcm.Init(aFrame.GetHeaderLength(), aFrame.GetPayloadLength(), tagLength, nonce, sizeof(nonce));
|
||||
aesCcm.Header(aFrame.GetHeader(), aFrame.GetHeaderLength());
|
||||
aesCcm.Payload(aFrame.GetPayload(), aFrame.GetPayload(), aFrame.GetPayloadLength(), false);
|
||||
aesCcm.Finalize(tag, &tagLength);
|
||||
|
||||
VerifyOrExit(memcmp(tag, mReceiveFrame.GetFooter(), tagLength) == 0, error = kThreadError_Security);
|
||||
VerifyOrExit(memcmp(tag, aFrame.GetFooter(), tagLength) == 0, error = kThreadError_Security);
|
||||
|
||||
if (keySequence > mKeyManager.GetCurrentKeySequence())
|
||||
{
|
||||
@@ -733,18 +730,18 @@ ThreadError Mac::ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeig
|
||||
|
||||
aNeighbor->mValid.mLinkFrameCounter = frameCounter + 1;
|
||||
|
||||
mReceiveFrame.SetSecurityValid(true);
|
||||
aFrame.SetSecurityValid(true);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
extern "C" void otPlatRadioReceiveDone(ThreadError aError)
|
||||
extern "C" void otPlatRadioReceiveDone(RadioPacket *aFrame, ThreadError aError)
|
||||
{
|
||||
sMac->ReceiveDoneTask(aError);
|
||||
sMac->ReceiveDoneTask(static_cast<Frame *>(aFrame), aError);
|
||||
}
|
||||
|
||||
void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
{
|
||||
Address srcaddr;
|
||||
Address dstaddr;
|
||||
@@ -753,9 +750,9 @@ void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
Whitelist::Entry *entry;
|
||||
int8_t rssi;
|
||||
|
||||
VerifyOrExit(aError == kThreadError_None, ;);
|
||||
VerifyOrExit(aError == kThreadError_None && aFrame != NULL, ;);
|
||||
|
||||
mReceiveFrame.GetSrcAddr(srcaddr);
|
||||
aFrame->GetSrcAddr(srcaddr);
|
||||
neighbor = mMle.GetNeighbor(srcaddr);
|
||||
|
||||
switch (srcaddr.mLength)
|
||||
@@ -783,12 +780,12 @@ void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
|
||||
if (mWhitelist.GetConstantRssi(*entry, rssi) == kThreadError_None)
|
||||
{
|
||||
mReceiveFrame.mPower = rssi;
|
||||
aFrame->mPower = rssi;
|
||||
}
|
||||
}
|
||||
|
||||
// Destination Address Filtering
|
||||
mReceiveFrame.GetDstAddr(dstaddr);
|
||||
aFrame->GetDstAddr(dstaddr);
|
||||
|
||||
switch (dstaddr.mLength)
|
||||
{
|
||||
@@ -796,28 +793,28 @@ void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
break;
|
||||
|
||||
case sizeof(ShortAddress):
|
||||
mReceiveFrame.GetDstPanId(panid);
|
||||
aFrame->GetDstPanId(panid);
|
||||
VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) &&
|
||||
((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) ||
|
||||
dstaddr.mShortAddress == mShortAddress), ;);
|
||||
break;
|
||||
|
||||
case sizeof(ExtAddress):
|
||||
mReceiveFrame.GetDstPanId(panid);
|
||||
aFrame->GetDstPanId(panid);
|
||||
VerifyOrExit(panid == mPanId &&
|
||||
memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0, ;);
|
||||
break;
|
||||
}
|
||||
|
||||
// Security Processing
|
||||
SuccessOrExit(ProcessReceiveSecurity(srcaddr, neighbor));
|
||||
SuccessOrExit(ProcessReceiveSecurity(*aFrame, srcaddr, neighbor));
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
if (mReceiveFrame.GetType() == Frame::kFcfFrameBeacon)
|
||||
if (aFrame->GetType() == Frame::kFcfFrameBeacon)
|
||||
{
|
||||
mActiveScanHandler(mActiveScanContext, &mReceiveFrame);
|
||||
mActiveScanHandler(mActiveScanContext, aFrame);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -828,14 +825,14 @@ void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
mReceiveTimer.Stop();
|
||||
}
|
||||
|
||||
if (mReceiveFrame.GetType() == Frame::kFcfFrameMacCmd)
|
||||
if (aFrame->GetType() == Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
SuccessOrExit(HandleMacCommand());
|
||||
SuccessOrExit(HandleMacCommand(*aFrame));
|
||||
}
|
||||
|
||||
for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
|
||||
{
|
||||
receiver->HandleReceivedFrame(mReceiveFrame, kThreadError_None);
|
||||
receiver->HandleReceivedFrame(*aFrame, kThreadError_None);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -845,11 +842,12 @@ exit:
|
||||
NextOperation();
|
||||
}
|
||||
|
||||
ThreadError Mac::HandleMacCommand(void)
|
||||
ThreadError Mac::HandleMacCommand(Frame &aFrame)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t commandId;
|
||||
mReceiveFrame.GetCommandId(commandId);
|
||||
|
||||
aFrame.GetCommandId(commandId);
|
||||
|
||||
if (commandId == Frame::kMacCmdBeaconRequest)
|
||||
{
|
||||
|
||||
@@ -366,11 +366,12 @@ public:
|
||||
/**
|
||||
* This method is called to handle receive events.
|
||||
*
|
||||
* @param[in] aError ::kThreadError_None when successfully received a frame, ::kThreadError_Abort when reception
|
||||
* was aborted and a frame was not received.
|
||||
* @param[in] aFrame A pointer to the received frame, or NULL if the receive operation aborted.
|
||||
* @param[in] aError ::kThreadError_None when successfully received a frame, ::kThreadError_Abort when reception
|
||||
* was aborted and a frame was not received.
|
||||
*
|
||||
*/
|
||||
void ReceiveDoneTask(ThreadError aError);
|
||||
void ReceiveDoneTask(Frame *aFrame, ThreadError aError);
|
||||
|
||||
/**
|
||||
* This method is called to handle transmit events.
|
||||
@@ -393,14 +394,14 @@ public:
|
||||
private:
|
||||
void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce);
|
||||
void NextOperation(void);
|
||||
void ProcessTransmitSecurity(void);
|
||||
ThreadError ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeighbor);
|
||||
void ProcessTransmitSecurity(Frame &aFrame);
|
||||
ThreadError ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor);
|
||||
void ScheduleNextTransmission(void);
|
||||
void SentFrame(bool aAcked);
|
||||
void SendBeaconRequest(Frame &aFrame);
|
||||
void SendBeacon(Frame &aFrame);
|
||||
void StartBackoff(void);
|
||||
ThreadError HandleMacCommand(void);
|
||||
ThreadError HandleMacCommand(Frame &aFrame);
|
||||
|
||||
static void HandleAckTimer(void *aContext);
|
||||
void HandleAckTimer(void);
|
||||
@@ -426,8 +427,6 @@ private:
|
||||
|
||||
Beacon mBeacon;
|
||||
|
||||
Frame mSendFrame;
|
||||
Frame mReceiveFrame;
|
||||
Sender *mSendHead, *mSendTail;
|
||||
Receiver *mReceiveHead, *mReceiveTail;
|
||||
|
||||
|
||||
@@ -74,7 +74,11 @@ void TestMacHeader(void)
|
||||
|
||||
for (unsigned i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
|
||||
{
|
||||
uint8_t psdu[Mac::Frame::kMTU];
|
||||
Mac::Frame frame;
|
||||
|
||||
frame.mPsdu = psdu;
|
||||
|
||||
frame.InitMacHeader(tests[i].fcf, tests[i].secCtl);
|
||||
printf("%d\n", frame.GetHeaderLength());
|
||||
VerifyOrQuit(frame.GetHeaderLength() == tests[i].headerLength,
|
||||
|
||||
Reference in New Issue
Block a user