From 765c45c2ed627ed0def931d73e5913dd4f8b599e Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 9 Nov 2018 08:59:20 -0800 Subject: [PATCH] [ncp] allow pcap without link-raw (#3274) This commit adds a new spinel property `SPINEL_PROP_PHY_PCAP_ENABLED` to allow packet capture (pcap) to be enabled independently of link-raw mode. This allows pcap to be used on NCPs while running full Thread protocol. --- src/ncp/ncp_base.cpp | 54 ++---------------------- src/ncp/ncp_base.hpp | 7 ++-- src/ncp/ncp_base_dispatcher.cpp | 6 +++ src/ncp/ncp_base_mtd.cpp | 73 +++++++++++++++++++++++++++++++++ src/ncp/spinel.c | 8 ++++ src/ncp/spinel.h | 4 +- 6 files changed, 97 insertions(+), 55 deletions(-) diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 60a997270..e9a9261d2 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -224,6 +224,7 @@ NcpBase::NcpBase(Instance *aInstance) , mAllowLocalNetworkDataChange(false) , mRequireJoinExistingNetwork(false) , mIsRawStreamEnabled(false) + , mPcapEnabled(false) , mDisableStreamWrite(false) , mShouldEmitChildTableUpdate(false) #if OPENTHREAD_FTD @@ -271,7 +272,6 @@ NcpBase::NcpBase(Instance *aInstance) #if OPENTHREAD_ENABLE_UDP_FORWARD otUdpForwardSetForwarder(mInstance, &NcpBase::HandleUdpForwardStream, this); #endif - otLinkSetPcapCallback(mInstance, &NcpBase::HandleRawFrame, static_cast(this)); otIcmp6SetEchoMode(mInstance, OT_ICMP6_ECHO_HANDLER_DISABLED); #if OPENTHREAD_FTD otThreadSetChildTableCallback(mInstance, &NcpBase::HandleChildTableChanged); @@ -639,56 +639,6 @@ void NcpBase::RegisterPeekPokeDelagates(otNcpDelegateAllowPeekPoke aAllowPeekDel #endif // OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE -// ---------------------------------------------------------------------------- -// MARK: Raw frame handling -// ---------------------------------------------------------------------------- - -void NcpBase::HandleRawFrame(const otRadioFrame *aFrame, void *aContext) -{ - static_cast(aContext)->HandleRawFrame(aFrame); -} - -void NcpBase::HandleRawFrame(const otRadioFrame *aFrame) -{ - uint16_t flags = 0; - uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0; - - if (!mIsRawStreamEnabled) - { - goto exit; - } - - if (aFrame->mDidTx) - { - flags |= SPINEL_MD_FLAG_TX; - } - - // Append frame header and frame length - SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW)); - SuccessOrExit(mEncoder.WriteUint16(aFrame->mLength)); - - // Append the frame contents - SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength)); - - // Append metadata (rssi, etc) - SuccessOrExit(mEncoder.WriteInt8(aFrame->mInfo.mRxInfo.mRssi)); // RSSI - SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise floor (Currently unused) - SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags - - SuccessOrExit(mEncoder.OpenStruct()); // PHY-data - // Empty for now - SuccessOrExit(mEncoder.CloseStruct()); - - SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data - // Empty for now - SuccessOrExit(mEncoder.CloseStruct()); - - SuccessOrExit(mEncoder.EndFrame()); - -exit: - return; -} - // ---------------------------------------------------------------------------- // MARK: Spinel Response Handling // ---------------------------------------------------------------------------- @@ -1789,6 +1739,8 @@ template <> otError NcpBase::HandlePropertyGet(void) #if OPENTHREAD_MTD || OPENTHREAD_FTD SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_1)); + SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_PCAP)); + #if OPENTHREAD_ENABLE_MAC_FILTER SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_WHITELIST)); #endif diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 318a7bc83..3e7c3284f 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -237,9 +237,6 @@ protected: NcpFrameBuffer * aNcpBuffer); void HandleFrameRemovedFromNcpBuffer(NcpFrameBuffer::FrameTag aFrameTag); - static void HandleRawFrame(const otRadioFrame *aFrame, void *aContext); - void HandleRawFrame(const otRadioFrame *aFrame); - otError EncodeChannelMask(uint32_t aChannelMask); otError DecodeChannelMask(uint32_t &aChannelMask); @@ -263,6 +260,9 @@ protected: static void HandleStateChanged(otChangedFlags aFlags, void *aContext); void ProcessThreadChangedFlags(void); + static void HandlePcapFrame(const otRadioFrame *aFrame, void *aContext); + void HandlePcapFrame(const otRadioFrame *aFrame); + static void HandleTimeSyncUpdate(void *aContext); void HandleTimeSyncUpdate(void); @@ -530,6 +530,7 @@ protected: bool mAllowLocalNetworkDataChange; bool mRequireJoinExistingNetwork; bool mIsRawStreamEnabled; + bool mPcapEnabled; bool mDisableStreamWrite; bool mShouldEmitChildTableUpdate; diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index d1a28ebc5..32a202416 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -139,6 +139,9 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) // MTD (or FTD) Properties (Get Handler) #if OPENTHREAD_MTD || OPENTHREAD_FTD + case SPINEL_PROP_PHY_PCAP_ENABLED: + handler = &NcpBase::HandlePropertyGet; + break; case SPINEL_PROP_MAC_DATA_POLL_PERIOD: handler = &NcpBase::HandlePropertyGet; break; @@ -687,6 +690,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) // MTD (or FTD) Properties (Set Handler) #if OPENTHREAD_MTD || OPENTHREAD_FTD + case SPINEL_PROP_PHY_PCAP_ENABLED: + handler = &NcpBase::HandlePropertySet; + break; case SPINEL_PROP_PHY_CHAN_SUPPORTED: handler = &NcpBase::HandlePropertySet; break; diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 68da34163..4c351619d 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2929,6 +2929,79 @@ exit: } #endif // OPENTHREAD_ENABLE_UDP_FORWARD +// ---------------------------------------------------------------------------- +// MARK: Pcap frame handling +// ---------------------------------------------------------------------------- + +void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame, void *aContext) +{ + static_cast(aContext)->HandlePcapFrame(aFrame); +} + +void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame) +{ + uint16_t flags = 0; + uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0; + + VerifyOrExit(mPcapEnabled); + + if (aFrame->mDidTx) + { + flags |= SPINEL_MD_FLAG_TX; + } + + SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW)); + SuccessOrExit(mEncoder.WriteUint16(aFrame->mLength)); + + SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength)); + + // Append metadata (rssi, etc) + SuccessOrExit(mEncoder.WriteInt8(aFrame->mInfo.mRxInfo.mRssi)); // RSSI + SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise floor (Currently unused) + SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags + + SuccessOrExit(mEncoder.OpenStruct()); // PHY-data + // Empty for now + SuccessOrExit(mEncoder.CloseStruct()); + + SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data + // Empty for now + SuccessOrExit(mEncoder.CloseStruct()); + + SuccessOrExit(mEncoder.EndFrame()); + +exit: + return; +} + +template <> otError NcpBase::HandlePropertyGet(void) +{ + return mEncoder.WriteBool(mPcapEnabled); +} + +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + bool enabled; + + SuccessOrExit(error = mDecoder.ReadBool(enabled)); + VerifyOrExit(enabled != mPcapEnabled); + + mPcapEnabled = enabled; + + if (mPcapEnabled) + { + otLinkSetPcapCallback(mInstance, &NcpBase::HandlePcapFrame, static_cast(this)); + } + else + { + otLinkSetPcapCallback(mInstance, NULL, NULL); + } + +exit: + return error; +} + // ---------------------------------------------------------------------------- // MARK: Property/Status Changed // ---------------------------------------------------------------------------- diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index 534dc18d7..e89c4a77e 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1290,6 +1290,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PHY_RX_SENSITIVITY"; break; + case SPINEL_PROP_PHY_PCAP_ENABLED: + ret = "PHY_PCAP_ENABLED"; + break; + case SPINEL_PROP_JAM_DETECT_ENABLE: ret = "JAM_DETECT_ENABLE"; break; @@ -2359,6 +2363,10 @@ const char *spinel_capability_to_cstr(unsigned int capability) ret = "MCU_POWER_STATE"; break; + case SPINEL_CAP_PCAP: + ret = "PCAP"; + break; + case SPINEL_CAP_802_15_4_2003: ret = "802_15_4_2003"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 710159384..ac73aa49f 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -724,6 +724,7 @@ enum SPINEL_CAP_CMD_MULTI = 11, SPINEL_CAP_UNSOL_UPDATE_FILTER = 12, SPINEL_CAP_MCU_POWER_STATE = 13, + SPINEL_CAP_PCAP = 14, SPINEL_CAP_802_15_4__BEGIN = 16, SPINEL_CAP_802_15_4_2003 = (SPINEL_CAP_802_15_4__BEGIN + 0), @@ -987,6 +988,7 @@ typedef enum SPINEL_PROP_PHY_TX_POWER = SPINEL_PROP_PHY__BEGIN + 5, ///< [c] SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c] SPINEL_PROP_PHY_RX_SENSITIVITY = SPINEL_PROP_PHY__BEGIN + 7, ///< dBm [c] + SPINEL_PROP_PHY_PCAP_ENABLED = SPINEL_PROP_PHY__BEGIN + 8, ///< [b] SPINEL_PROP_PHY__END = 0x30, SPINEL_PROP_PHY_EXT__BEGIN = 0x1200, @@ -1150,7 +1152,7 @@ typedef enum SPINEL_PROP_MAC_15_4_LADDR = SPINEL_PROP_MAC__BEGIN + 4, ///< [E] SPINEL_PROP_MAC_15_4_SADDR = SPINEL_PROP_MAC__BEGIN + 5, ///< [S] SPINEL_PROP_MAC_15_4_PANID = SPINEL_PROP_MAC__BEGIN + 6, ///< [S] - SPINEL_PROP_MAC_RAW_STREAM_ENABLED = SPINEL_PROP_MAC__BEGIN + 7, ///< [C] + SPINEL_PROP_MAC_RAW_STREAM_ENABLED = SPINEL_PROP_MAC__BEGIN + 7, ///< [b] SPINEL_PROP_MAC_PROMISCUOUS_MODE = SPINEL_PROP_MAC__BEGIN + 8, ///< [C] SPINEL_PROP_MAC_ENERGY_SCAN_RESULT = SPINEL_PROP_MAC__BEGIN + 9, ///< chan,maxRssi [Cc] SPINEL_PROP_MAC_DATA_POLL_PERIOD = SPINEL_PROP_MAC__BEGIN + 10, ///< pollPeriod (in ms) [L]