mirror of
https://github.com/espressif/openthread.git
synced 2026-08-24 19:29:52 +00:00
[ncp] enhance unsolicited property/status updates (#1993)
This commit implements a new model for keeping track of unsolicited property updates and how asynchronous `VALUE_IS` spinel frames are emitted from NCP. It also implements a mechanism for host to block updates from certain filterable properties. The behavior can be controlled through spinel properties `UNSOL_UPDATE_FILTER` and `UNSOL_UPDATE_LIST` (tied to capability `CAP_UNSOL_UPDATE_FILTER`). The new model is then used to track dropped IPv6 messages, end of scan, change in jamming state, and a newly added STATUS_NOMEM report in case of no NCP buffer space for log messages.
This commit is contained in:
committed by
Jonathan Hui
parent
cb463add61
commit
9839e9702b
+536
-312
File diff suppressed because it is too large
Load Diff
+175
-6
@@ -214,6 +214,7 @@ private:
|
||||
|
||||
static void UpdateChangedProps(Tasklet &aTasklet);
|
||||
void UpdateChangedProps(void);
|
||||
void ProcessThreadChangedFlags(void);
|
||||
|
||||
static void SendDoneTask(void *aContext);
|
||||
void SendDoneTask(void);
|
||||
@@ -344,6 +345,8 @@ private:
|
||||
NCP_GET_PROP_HANDLER(HWADDR);
|
||||
NCP_GET_PROP_HANDLER(LOCK);
|
||||
NCP_GET_PROP_HANDLER(HOST_POWER_STATE);
|
||||
NCP_GET_PROP_HANDLER(UNSOL_UPDATE_FILTER);
|
||||
NCP_GET_PROP_HANDLER(UNSOL_UPDATE_LIST);
|
||||
NCP_GET_PROP_HANDLER(PHY_ENABLED);
|
||||
NCP_GET_PROP_HANDLER(PHY_FREQ);
|
||||
NCP_GET_PROP_HANDLER(PHY_CHAN_SUPPORTED);
|
||||
@@ -444,6 +447,7 @@ private:
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_LEGACY
|
||||
NCP_GET_PROP_HANDLER(NEST_LEGACY_ULA_PREFIX);
|
||||
NCP_GET_PROP_HANDLER(NEST_LEGACY_LAST_NODE_JOINED);
|
||||
#endif
|
||||
|
||||
// Property Set Handlers
|
||||
@@ -452,6 +456,7 @@ private:
|
||||
NCP_SET_PROP_HANDLER(HOST_POWER_STATE);
|
||||
NCP_SET_PROP_HANDLER(PHY_TX_POWER);
|
||||
NCP_SET_PROP_HANDLER(PHY_CHAN);
|
||||
NCP_SET_PROP_HANDLER(UNSOL_UPDATE_FILTER);
|
||||
NCP_SET_PROP_HANDLER(MAC_SCAN_MASK);
|
||||
NCP_SET_PROP_HANDLER(MAC_SCAN_STATE);
|
||||
NCP_SET_PROP_HANDLER(MAC_15_4_PANID);
|
||||
@@ -539,6 +544,7 @@ private:
|
||||
|
||||
// Property Insert Handlers
|
||||
|
||||
NCP_INSERT_PROP_HANDLER(UNSOL_UPDATE_FILTER);
|
||||
#if OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
|
||||
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
|
||||
@@ -561,6 +567,7 @@ private:
|
||||
|
||||
// Property Remove Handlers
|
||||
|
||||
NCP_REMOVE_PROP_HANDLER(UNSOL_UPDATE_FILTER);
|
||||
#if OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
|
||||
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
|
||||
@@ -602,6 +609,169 @@ protected:
|
||||
NcpFrameBuffer mTxFrameBuffer;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Defines a class to track a set of property/status changes that require update to host. The properties that can
|
||||
* be added to this set must support sending unsolicited updates. This class also provides mechanism for user
|
||||
* to block certain filterable properties disallowing the unsolicited update from them.
|
||||
*
|
||||
*/
|
||||
class ChangedPropsSet
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Defines an entry in the set/list.
|
||||
*
|
||||
*/
|
||||
struct Entry
|
||||
{
|
||||
spinel_prop_key_t mPropKey; ///< The spinel property key.
|
||||
spinel_status_t mStatus; ///< The spinel status (used only if prop key is `LAST_STATUS`).
|
||||
bool mFilterable; ///< Indicates whether the entry can be filtered
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the set.
|
||||
*
|
||||
*/
|
||||
ChangedPropsSet(void):
|
||||
mChangedSet(0),
|
||||
mFilterSet(0)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* This method clears the set.
|
||||
*
|
||||
*/
|
||||
void Clear(void) { mChangedSet = 0; }
|
||||
|
||||
/**
|
||||
* This method indicates if the set is empty or not.
|
||||
*
|
||||
* @returns TRUE if the set if empty, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsEmpty(void) const { return (mChangedSet == 0); }
|
||||
|
||||
/**
|
||||
* This method adds a property to the set. The property added must be in the list of supported properties
|
||||
* capable of sending unsolicited update, otherwise the input is ignored.
|
||||
*
|
||||
* Note that if the property is already in the set, adding it again does not change the set.
|
||||
*
|
||||
* @param[in] aPropKey The spinel property key to be added to the set
|
||||
*
|
||||
*/
|
||||
void AddProperty(spinel_prop_key_t aPropKey) { Add(aPropKey, SPINEL_STATUS_OK); }
|
||||
|
||||
/**
|
||||
* This method adds a `LAST_STATUS` update to the set. The update must be in list of supported entries.
|
||||
*
|
||||
* @param[in] aStatus The spinel status update to be added to set.
|
||||
*
|
||||
*/
|
||||
void AddLastStatus(spinel_status_t aStatus) { Add(SPINEL_PROP_LAST_STATUS, aStatus); }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to array of entries of supported property/status updates. The list includes
|
||||
* all properties that can generate unsolicited update.
|
||||
*
|
||||
* @param[out] aNumEntries A reference to output the number of entries in the list.
|
||||
*
|
||||
* @returns A pointer to the supported entries array.
|
||||
*
|
||||
*/
|
||||
const Entry *GetSupportedEntries(uint8_t &aNumEntries) const {
|
||||
aNumEntries = GetNumEntries();
|
||||
return &mSupportedProps[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the entry associated with a given index.
|
||||
*
|
||||
* @param[in] aIndex The index to an entry.
|
||||
*
|
||||
* @returns A pointer to the entry associated with @p aIndex, or NULL if the index is beyond end of array.
|
||||
*
|
||||
*/
|
||||
const Entry *GetEntry(uint8_t aIndex) const {
|
||||
return (aIndex < GetNumEntries()) ? &mSupportedProps[aIndex] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if the entry associated with an index is in the set (i.e., it has been changed and
|
||||
* requires an unsolicited update).
|
||||
*
|
||||
* @param[in] aIndex The index to an entry.
|
||||
*
|
||||
* @returns TRUE if the entry is in the set, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsEntryChanged(uint8_t aIndex) const { return IsBitSet(mChangedSet, aIndex); }
|
||||
|
||||
/**
|
||||
* This method removes an entry associated with an index in the set.
|
||||
*
|
||||
* Note that if the property/entry is not in the set, removing it simply does nothing.
|
||||
*
|
||||
* @param[in] aIndex Index of entry to be removed.
|
||||
*
|
||||
*/
|
||||
void RemoveEntry(uint8_t aIndex) { ClearBit(mChangedSet, aIndex); }
|
||||
|
||||
/**
|
||||
* This method enables/disables filtering of a given property.
|
||||
*
|
||||
* @param[in] aPropKey The property key to filter.
|
||||
* @param[in] aEnable TRUE to enable filtering, FALSE to disable.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Filter state for given property updated successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The given property is not valid (i.e., not capable of unsolicited update).
|
||||
*
|
||||
*/
|
||||
otError EnablePropertyFilter(spinel_prop_key_t aPropKey, bool aEnable);
|
||||
|
||||
/**
|
||||
* This method determines whether filtering is enabled for an entry associated with an index.
|
||||
*
|
||||
* @param[in] aIndex Index of entry to be checked.
|
||||
*
|
||||
* @returns TRUE if the filter is enabled for the given entry, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsEntryFiltered(uint8_t aIndex) const { return IsBitSet(mFilterSet, aIndex); }
|
||||
|
||||
/**
|
||||
* This method determines whether filtering is enabled for a given property key.
|
||||
*
|
||||
* @param[in] aPropKey The property key to check.
|
||||
*
|
||||
* @returns TRUE if the filter is enabled for the given property, FALSE if the property is not filtered or if
|
||||
* it is not filterable.
|
||||
*
|
||||
*/
|
||||
bool IsPropertyFiltered(spinel_prop_key_t aPropKey) const;
|
||||
|
||||
/**
|
||||
* This method clears the filter.
|
||||
*
|
||||
*/
|
||||
void ClearFilter(void) { mFilterSet = 0; }
|
||||
|
||||
private:
|
||||
uint8_t GetNumEntries(void) const;
|
||||
void Add(spinel_prop_key_t aPropKey, spinel_status_t aStatus);
|
||||
|
||||
static void SetBit (uint32_t &aBitset, uint8_t aBitIndex) { aBitset |= (1U << aBitIndex); }
|
||||
static void ClearBit(uint32_t &aBitset, uint8_t aBitIndex) { aBitset &= ~(1U << aBitIndex); }
|
||||
static bool IsBitSet(uint32_t aBitset, uint8_t aBitIndex) { return (aBitset & (1U << aBitIndex)) != 0; }
|
||||
|
||||
static const Entry mSupportedProps[];
|
||||
|
||||
uint32_t mChangedSet;
|
||||
uint32_t mFilterSet;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kTxBufferSize = OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE, // Tx Buffer size (used by mTxFrameBuffer).
|
||||
@@ -614,18 +784,16 @@ private:
|
||||
bool mDiscoveryScanJoinerFlag;
|
||||
bool mDiscoveryScanEnableFiltering;
|
||||
uint16_t mDiscoveryScanPanId;
|
||||
|
||||
Tasklet mUpdateChangedPropsTask;
|
||||
uint32_t mChangedFlags;
|
||||
bool mShouldSignalEndOfScan;
|
||||
uint32_t mThreadChangedFlags;
|
||||
ChangedPropsSet mChangedPropsSet;
|
||||
|
||||
spinel_host_power_state_t mHostPowerState;
|
||||
bool mHostPowerStateInProgress;
|
||||
NcpFrameBuffer::FrameTag mHostPowerReplyFrameTag;
|
||||
uint8_t mHostPowerStateHeader;
|
||||
|
||||
#if OPENTHREAD_ENABLE_JAM_DETECTION
|
||||
bool mShouldSignalJamStateChange;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
|
||||
otNcpDelegateAllowPeekPoke mAllowPeekDelegate;
|
||||
otNcpDelegateAllowPeekPoke mAllowPokeDelegate;
|
||||
@@ -661,6 +829,7 @@ private:
|
||||
#if OPENTHREAD_ENABLE_LEGACY
|
||||
const otNcpLegacyHandlers *mLegacyHandlers;
|
||||
uint8_t mLegacyUlaPrefix[OT_NCP_LEGACY_ULA_PREFIX_LENGTH];
|
||||
otExtAddress mLegacyLastJoinedNode;
|
||||
bool mLegacyNodeDidJoin;
|
||||
#endif
|
||||
|
||||
|
||||
+14
-2
@@ -972,6 +972,14 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PROP_TRNG_RAW_32";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_UNSOL_UPDATE_FILTER:
|
||||
ret = "PROP_UNSOL_UPDATE_FILTER";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_UNSOL_UPDATE_LIST:
|
||||
ret = "PROP_UNSOL_UPDATE_LIST";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_PHY_ENABLED:
|
||||
ret = "PROP_PHY_ENABLED";
|
||||
break;
|
||||
@@ -1568,8 +1576,8 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PROP_NEST_LEGACY_ULA_PREFIX";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_NEST_LEGACY_JOINED_NODE:
|
||||
ret = "PROP_NEST_LEGACY_JOINED_NODE";
|
||||
case SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED:
|
||||
ret = "PROP_NEST_LEGACY_LAST_NODE_JOINED";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_DEBUG_TEST_ASSERT:
|
||||
@@ -1819,6 +1827,10 @@ const char *spinel_capability_to_cstr(unsigned int capability)
|
||||
ret = "CAP_CMD_MULTI";
|
||||
break;
|
||||
|
||||
case SPINEL_CAP_UNSOL_UPDATE_FILTER:
|
||||
ret = "CAP_UNSOL_UPDATE_FILTER";
|
||||
break;
|
||||
|
||||
case SPINEL_CAP_802_15_4_2003:
|
||||
ret = "CAP_802_15_4_2003";
|
||||
break;
|
||||
|
||||
+35
-2
@@ -365,6 +365,7 @@ enum
|
||||
SPINEL_CAP_GPIO = 9,
|
||||
SPINEL_CAP_TRNG = 10,
|
||||
SPINEL_CAP_CMD_MULTI = 11,
|
||||
SPINEL_CAP_UNSOL_UPDATE_FILTER = 12,
|
||||
|
||||
SPINEL_CAP_802_15_4__BEGIN = 16,
|
||||
SPINEL_CAP_802_15_4_2003 = (SPINEL_CAP_802_15_4__BEGIN + 0),
|
||||
@@ -550,6 +551,37 @@ typedef enum
|
||||
/// Raw samples from TRNG entropy source representing 32 bits of entropy.
|
||||
SPINEL_PROP_TRNG_RAW_32 = SPINEL_PROP_BASE_EXT__BEGIN + 7,
|
||||
|
||||
|
||||
/// NCP Unsolicited update filter
|
||||
/** Format: `A(I)`
|
||||
* Type: Read-Write (optional Insert-Remove)
|
||||
* Required capability: `CAP_UNSOL_UPDATE_FILTER`
|
||||
*
|
||||
* Contains a list of properties which are excluded from generating
|
||||
* unsolicited value updates. This property is empty after reset.
|
||||
* In other words, the host may opt-out of unsolicited property updates
|
||||
* for a specific property by adding that property id to this list.
|
||||
* Hosts SHOULD NOT add properties to this list which are not
|
||||
* present in `PROP_UNSOL_UPDATE_LIST`. If such properties are added,
|
||||
* the NCP ignores the unsupported properties.
|
||||
*/
|
||||
SPINEL_PROP_UNSOL_UPDATE_FILTER = SPINEL_PROP_BASE_EXT__BEGIN + 8,
|
||||
|
||||
/// List of properties capable of generating unsolicited value update.
|
||||
/** Format: `A(I)`
|
||||
* Type: Read-Only
|
||||
* Required capability: `CAP_UNSOL_UPDATE_FILTER`
|
||||
*
|
||||
* Contains a list of properties which are capable of generating
|
||||
* unsolicited value updates. This list can be used when populating
|
||||
* `PROP_UNSOL_UPDATE_FILTER` to disable all unsolicited property
|
||||
* updates.
|
||||
*
|
||||
* This property is intended to effectively behave as a constant
|
||||
* for a given NCP firmware.
|
||||
*/
|
||||
SPINEL_PROP_UNSOL_UPDATE_LIST = SPINEL_PROP_BASE_EXT__BEGIN + 9,
|
||||
|
||||
SPINEL_PROP_BASE_EXT__END = 0x1100,
|
||||
|
||||
SPINEL_PROP_PHY__BEGIN = 0x20,
|
||||
@@ -1275,9 +1307,10 @@ typedef enum
|
||||
/** Format: 'D' */
|
||||
SPINEL_PROP_NEST_LEGACY_ULA_PREFIX = SPINEL_PROP_NEST__BEGIN + 1,
|
||||
|
||||
/// A (newly) joined legacy node (this is signaled from NCP)
|
||||
/// The EUI64 of last node joined using legacy protocol (if none, all zero EUI64 is returned).
|
||||
/** Format: 'E' */
|
||||
SPINEL_PROP_NEST_LEGACY_JOINED_NODE = SPINEL_PROP_NEST__BEGIN + 2,
|
||||
SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED
|
||||
= SPINEL_PROP_NEST__BEGIN + 2,
|
||||
|
||||
SPINEL_PROP_NEST__END = 15360,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user