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