xref: /aosp_15_r20/external/openthread/src/ncp/changed_props_set.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *    Copyright (c) 2016-2017, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *    All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *    Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *    modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *       documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *    3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *       names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *       derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*cfb92d14SAndroid Build Coastguard Worker  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*cfb92d14SAndroid Build Coastguard Worker  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*cfb92d14SAndroid Build Coastguard Worker  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20*cfb92d14SAndroid Build Coastguard Worker  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*cfb92d14SAndroid Build Coastguard Worker  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*cfb92d14SAndroid Build Coastguard Worker  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*cfb92d14SAndroid Build Coastguard Worker  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*cfb92d14SAndroid Build Coastguard Worker  */
27*cfb92d14SAndroid Build Coastguard Worker 
28*cfb92d14SAndroid Build Coastguard Worker #include "changed_props_set.hpp"
29*cfb92d14SAndroid Build Coastguard Worker 
30*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
31*cfb92d14SAndroid Build Coastguard Worker 
32*cfb92d14SAndroid Build Coastguard Worker namespace ot {
33*cfb92d14SAndroid Build Coastguard Worker namespace Ncp {
34*cfb92d14SAndroid Build Coastguard Worker 
35*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte.
36*cfb92d14SAndroid Build Coastguard Worker 
37*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
38*cfb92d14SAndroid Build Coastguard Worker // MARK: ChangedPropsSet class
39*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
40*cfb92d14SAndroid Build Coastguard Worker 
41*cfb92d14SAndroid Build Coastguard Worker // Defines the list of properties that can support unsolicited update.
42*cfb92d14SAndroid Build Coastguard Worker //
43*cfb92d14SAndroid Build Coastguard Worker // Note that {`SPINEL_PROP_LAST_STATUS`, `SPINEL_STATUS_RESET_UNKNOWN`} should be first entry to ensure that RESET is
44*cfb92d14SAndroid Build Coastguard Worker // reported before any other property update.
45*cfb92d14SAndroid Build Coastguard Worker //
46*cfb92d14SAndroid Build Coastguard Worker // Since a `uint64_t` is used as bit-mask to track which entries are in the changed set, we should ensure that the
47*cfb92d14SAndroid Build Coastguard Worker // number of entries in the list is always less than or equal to 64.
48*cfb92d14SAndroid Build Coastguard Worker //
49*cfb92d14SAndroid Build Coastguard Worker const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = {
50*cfb92d14SAndroid Build Coastguard Worker     // Spinel property , Status (if prop is `LAST_STATUS`),  IsFilterable?
51*cfb92d14SAndroid Build Coastguard Worker 
52*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_RESET_UNKNOWN, false},
53*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_STREAM_DEBUG, SPINEL_STATUS_OK, true},
54*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_IPV6_LL_ADDR, SPINEL_STATUS_OK, true},
55*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_IPV6_ML_ADDR, SPINEL_STATUS_OK, true},
56*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_IPV6_ADDRESS_TABLE, SPINEL_STATUS_OK, true},
57*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_ROLE, SPINEL_STATUS_OK, true},
58*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_PARTITION_ID, SPINEL_STATUS_OK, true},
59*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, SPINEL_STATUS_OK, true},
60*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_LEADER_NETWORK_DATA, SPINEL_STATUS_OK, true},
61*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_CHILD_TABLE, SPINEL_STATUS_OK, true},
62*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_ON_MESH_NETS, SPINEL_STATUS_OK, true},
63*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_OFF_MESH_ROUTES, SPINEL_STATUS_OK, true},
64*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_STACK_UP, SPINEL_STATUS_OK, true},
65*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING, SPINEL_STATUS_OK, true},
66*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_NOMEM, true},
67*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_DROPPED, true},
68*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
69*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_JAM_DETECTED, SPINEL_STATUS_OK, true},
70*cfb92d14SAndroid Build Coastguard Worker #endif
71*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_FAILURE, false},
72*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_MAC_SCAN_STATE, SPINEL_STATUS_OK, false},
73*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE, SPINEL_STATUS_OK, true},
74*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_PHY_CHAN, SPINEL_STATUS_OK, true},
75*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_MAC_15_4_PANID, SPINEL_STATUS_OK, true},
76*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_NETWORK_NAME, SPINEL_STATUS_OK, true},
77*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_XPANID, SPINEL_STATUS_OK, true},
78*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_NETWORK_KEY, SPINEL_STATUS_OK, true},
79*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_PSKC, SPINEL_STATUS_OK, true},
80*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_NET_LEAVE_GRACEFULLY, SPINEL_STATUS_OK, false},
81*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_PHY_CHAN_SUPPORTED, SPINEL_STATUS_OK, true},
82*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
83*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_STATUS_OK, true},
84*cfb92d14SAndroid Build Coastguard Worker #endif
85*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_JOINER_ENABLE
86*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_NO_PEERS, false},
87*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_SECURITY, false},
88*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_RSP_TIMEOUT, false},
89*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_SUCCESS, false},
90*cfb92d14SAndroid Build Coastguard Worker #endif
91*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
92*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_NETWORK_TIME, SPINEL_STATUS_OK, false},
93*cfb92d14SAndroid Build Coastguard Worker #endif
94*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_PARENT_RESPONSE_INFO, SPINEL_STATUS_OK, true},
95*cfb92d14SAndroid Build Coastguard Worker     {SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET_TLVS, SPINEL_STATUS_OK, false},
96*cfb92d14SAndroid Build Coastguard Worker };
97*cfb92d14SAndroid Build Coastguard Worker 
GetNumEntries(void) const98*cfb92d14SAndroid Build Coastguard Worker uint8_t ChangedPropsSet::GetNumEntries(void) const
99*cfb92d14SAndroid Build Coastguard Worker {
100*cfb92d14SAndroid Build Coastguard Worker     static_assert(OT_ARRAY_LENGTH(mSupportedProps) <= sizeof(mChangedSet) * kBitsPerByte,
101*cfb92d14SAndroid Build Coastguard Worker                   "Changed set size is smaller than number of entries in `mSupportedProps[]` array");
102*cfb92d14SAndroid Build Coastguard Worker 
103*cfb92d14SAndroid Build Coastguard Worker     return OT_ARRAY_LENGTH(mSupportedProps);
104*cfb92d14SAndroid Build Coastguard Worker }
105*cfb92d14SAndroid Build Coastguard Worker 
Add(spinel_prop_key_t aPropKey,spinel_status_t aStatus)106*cfb92d14SAndroid Build Coastguard Worker void ChangedPropsSet::Add(spinel_prop_key_t aPropKey, spinel_status_t aStatus)
107*cfb92d14SAndroid Build Coastguard Worker {
108*cfb92d14SAndroid Build Coastguard Worker     uint8_t      numEntries;
109*cfb92d14SAndroid Build Coastguard Worker     const Entry *entry;
110*cfb92d14SAndroid Build Coastguard Worker 
111*cfb92d14SAndroid Build Coastguard Worker     entry = GetSupportedEntries(numEntries);
112*cfb92d14SAndroid Build Coastguard Worker 
113*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
114*cfb92d14SAndroid Build Coastguard Worker     {
115*cfb92d14SAndroid Build Coastguard Worker         if ((entry->mPropKey == aPropKey) && (entry->mStatus == aStatus))
116*cfb92d14SAndroid Build Coastguard Worker         {
117*cfb92d14SAndroid Build Coastguard Worker             if (!IsEntryFiltered(index))
118*cfb92d14SAndroid Build Coastguard Worker             {
119*cfb92d14SAndroid Build Coastguard Worker                 SetBit(mChangedSet, index);
120*cfb92d14SAndroid Build Coastguard Worker             }
121*cfb92d14SAndroid Build Coastguard Worker 
122*cfb92d14SAndroid Build Coastguard Worker             break;
123*cfb92d14SAndroid Build Coastguard Worker         }
124*cfb92d14SAndroid Build Coastguard Worker     }
125*cfb92d14SAndroid Build Coastguard Worker }
126*cfb92d14SAndroid Build Coastguard Worker 
EnablePropertyFilter(spinel_prop_key_t aPropKey,bool aEnable)127*cfb92d14SAndroid Build Coastguard Worker otError ChangedPropsSet::EnablePropertyFilter(spinel_prop_key_t aPropKey, bool aEnable)
128*cfb92d14SAndroid Build Coastguard Worker {
129*cfb92d14SAndroid Build Coastguard Worker     uint8_t      numEntries;
130*cfb92d14SAndroid Build Coastguard Worker     const Entry *entry;
131*cfb92d14SAndroid Build Coastguard Worker     bool         didFind = false;
132*cfb92d14SAndroid Build Coastguard Worker 
133*cfb92d14SAndroid Build Coastguard Worker     entry = GetSupportedEntries(numEntries);
134*cfb92d14SAndroid Build Coastguard Worker 
135*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
136*cfb92d14SAndroid Build Coastguard Worker     {
137*cfb92d14SAndroid Build Coastguard Worker         if (entry->mFilterable && (entry->mPropKey == aPropKey))
138*cfb92d14SAndroid Build Coastguard Worker         {
139*cfb92d14SAndroid Build Coastguard Worker             if (aEnable)
140*cfb92d14SAndroid Build Coastguard Worker             {
141*cfb92d14SAndroid Build Coastguard Worker                 SetBit(mFilterSet, index);
142*cfb92d14SAndroid Build Coastguard Worker 
143*cfb92d14SAndroid Build Coastguard Worker                 // If filter is enabled for a property, the `mChangedSet` is cleared
144*cfb92d14SAndroid Build Coastguard Worker                 // for the same property so to ensure a pending update is also filtered.
145*cfb92d14SAndroid Build Coastguard Worker 
146*cfb92d14SAndroid Build Coastguard Worker                 ClearBit(mChangedSet, index);
147*cfb92d14SAndroid Build Coastguard Worker             }
148*cfb92d14SAndroid Build Coastguard Worker             else
149*cfb92d14SAndroid Build Coastguard Worker             {
150*cfb92d14SAndroid Build Coastguard Worker                 ClearBit(mFilterSet, index);
151*cfb92d14SAndroid Build Coastguard Worker             }
152*cfb92d14SAndroid Build Coastguard Worker 
153*cfb92d14SAndroid Build Coastguard Worker             didFind = true;
154*cfb92d14SAndroid Build Coastguard Worker 
155*cfb92d14SAndroid Build Coastguard Worker             // Continue the search only if the prop key is `LAST_STATUS`, as
156*cfb92d14SAndroid Build Coastguard Worker             // we have multiple filterable `LAST_STATUS` entries in the table
157*cfb92d14SAndroid Build Coastguard Worker             // with different error status (DROPPED and NOMEM).
158*cfb92d14SAndroid Build Coastguard Worker 
159*cfb92d14SAndroid Build Coastguard Worker             if (aPropKey != SPINEL_PROP_LAST_STATUS)
160*cfb92d14SAndroid Build Coastguard Worker             {
161*cfb92d14SAndroid Build Coastguard Worker                 break;
162*cfb92d14SAndroid Build Coastguard Worker             }
163*cfb92d14SAndroid Build Coastguard Worker         }
164*cfb92d14SAndroid Build Coastguard Worker     }
165*cfb92d14SAndroid Build Coastguard Worker 
166*cfb92d14SAndroid Build Coastguard Worker     return didFind ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
167*cfb92d14SAndroid Build Coastguard Worker }
168*cfb92d14SAndroid Build Coastguard Worker 
IsPropertyFiltered(spinel_prop_key_t aPropKey) const169*cfb92d14SAndroid Build Coastguard Worker bool ChangedPropsSet::IsPropertyFiltered(spinel_prop_key_t aPropKey) const
170*cfb92d14SAndroid Build Coastguard Worker {
171*cfb92d14SAndroid Build Coastguard Worker     bool         isFiltered = false;
172*cfb92d14SAndroid Build Coastguard Worker     uint8_t      numEntries;
173*cfb92d14SAndroid Build Coastguard Worker     const Entry *entry;
174*cfb92d14SAndroid Build Coastguard Worker 
175*cfb92d14SAndroid Build Coastguard Worker     entry = GetSupportedEntries(numEntries);
176*cfb92d14SAndroid Build Coastguard Worker 
177*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < numEntries; index++, entry++)
178*cfb92d14SAndroid Build Coastguard Worker     {
179*cfb92d14SAndroid Build Coastguard Worker         if (entry->mFilterable && (entry->mPropKey == aPropKey))
180*cfb92d14SAndroid Build Coastguard Worker         {
181*cfb92d14SAndroid Build Coastguard Worker             isFiltered = IsEntryFiltered(index);
182*cfb92d14SAndroid Build Coastguard Worker 
183*cfb92d14SAndroid Build Coastguard Worker             break;
184*cfb92d14SAndroid Build Coastguard Worker         }
185*cfb92d14SAndroid Build Coastguard Worker     }
186*cfb92d14SAndroid Build Coastguard Worker 
187*cfb92d14SAndroid Build Coastguard Worker     return isFiltered;
188*cfb92d14SAndroid Build Coastguard Worker }
189*cfb92d14SAndroid Build Coastguard Worker 
190*cfb92d14SAndroid Build Coastguard Worker } // namespace Ncp
191*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
192