From a4614ac7958b6a00aa829985f7592385c74512e4 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 1 Apr 2019 14:46:27 -0700 Subject: [PATCH] [ncp] decode meta-data (CSMA/retry counts) in STREAM_RAW property set (#3727) This commit adds logic to decode and use the optional meta-data fields in a `VALUE_SET` command (frame tx request) for `PROP_STREAM_RAW` in raw-link or radio only (RCP) mode. The optional meta-data fields map to definitions in `otRadioFrame` to specify number of CSMA backoffs attempts, frame retry attempts, whether to enable CSMA-CA for this frame or not. If any optional field is not included, default value is used instead. This aligns the implementation with specification of `PROP_STREAM_RAW` in `spinel.h`. --- src/ncp/ncp_base.hpp | 1 + src/ncp/ncp_base_radio.cpp | 57 +++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 6c495a79d..df2c6a903 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -409,6 +409,7 @@ protected: #endif // OPENTHREAD_FTD #if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API + otError DecodeStreamRawTxRequest(otRadioFrame &aFrame); otError HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader); #endif diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp index 6e35cf0bf..aa4a84853 100644 --- a/src/ncp/ncp_base_radio.cpp +++ b/src/ncp/ncp_base_radio.cpp @@ -336,33 +336,58 @@ exit: return error; } +otError NcpBase::DecodeStreamRawTxRequest(otRadioFrame &aFrame) +{ + otError error; + const uint8_t *payloadPtr; + uint16_t payloadLen; + bool csmaEnable; + + SuccessOrExit(error = mDecoder.ReadDataWithLen(payloadPtr, payloadLen)); + VerifyOrExit(payloadLen <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_PARSE); + + aFrame.mLength = static_cast(payloadLen); + memcpy(aFrame.mPsdu, payloadPtr, aFrame.mLength); + + // Parse the meta data + + // Channel is a required parameter in meta data. + SuccessOrExit(error = mDecoder.ReadUint8(aFrame.mChannel)); + + // Set the default value for all optional parameters. + aFrame.mInfo.mTxInfo.mMaxCsmaBackoffs = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT; + aFrame.mInfo.mTxInfo.mMaxFrameRetries = OPENTHREAD_CONFIG_MAC_MAX_FRAME_RETRIES_DIRECT; + aFrame.mInfo.mTxInfo.mCsmaCaEnabled = true; + + // All the next parameters are optional. Note that even if the + // decoder fails to parse any of optional parameters we still want to + // return `OT_ERROR_NONE` (so `error` is not updated after this + // point). + + SuccessOrExit(mDecoder.ReadUint8(aFrame.mInfo.mTxInfo.mMaxCsmaBackoffs)); + SuccessOrExit(mDecoder.ReadUint8(aFrame.mInfo.mTxInfo.mMaxFrameRetries)); + SuccessOrExit(mDecoder.ReadBool(csmaEnable)); + aFrame.mInfo.mTxInfo.mCsmaCaEnabled = csmaEnable; + +exit: + return error; +} + otError NcpBase::HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader) { - const uint8_t *frameBuffer = NULL; - otRadioFrame * frame; - uint16_t frameLen = 0; - otError error = OT_ERROR_NONE; + otError error = OT_ERROR_NONE; + otRadioFrame *frame; VerifyOrExit(otLinkRawIsEnabled(mInstance), error = OT_ERROR_INVALID_STATE); frame = otLinkRawGetTransmitBuffer(mInstance); + VerifyOrExit(frame != NULL, error = OT_ERROR_NO_BUFS); - SuccessOrExit(error = mDecoder.ReadDataWithLen(frameBuffer, frameLen)); - SuccessOrExit(error = mDecoder.ReadUint8(frame->mChannel)); - - VerifyOrExit(frameLen <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_PARSE); + SuccessOrExit(error = DecodeStreamRawTxRequest(*frame)); // Cache the transaction ID for async response mCurTransmitTID = SPINEL_HEADER_GET_TID(aHeader); - // Update frame buffer and length - frame->mLength = static_cast(frameLen); - memcpy(frame->mPsdu, frameBuffer, frame->mLength); - - // TODO: This should be later added in the STREAM_RAW argument to allow user to directly specify it. - frame->mInfo.mTxInfo.mMaxCsmaBackoffs = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT; - frame->mInfo.mTxInfo.mMaxFrameRetries = OPENTHREAD_CONFIG_MAC_MAX_FRAME_RETRIES_DIRECT; - // Pass frame to the radio layer. Note, this fails if we // haven't enabled raw stream or are already transmitting. error = otLinkRawTransmit(mInstance, &NcpBase::LinkRawTransmitDone);