BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
neighbor_cache.c
00001 /* 00002 * Copyright (c) 2014-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #include "ns_types.h" 00019 #include "common_functions.h" 00020 #include "ns_trace.h" 00021 #include "string.h" 00022 #include "nsdynmemLIB.h" 00023 #include "Service_Libs/Neighbor_cache/neighbor_table_definition.h" 00024 00025 #ifdef HAVE_NEIGHBOR_CACHE 00026 00027 static void entry_delete(neigh_cache_s *neigh_cache, neigh_cache_entry_s *entry); 00028 00029 /** 00030 * \brief A function to initialize a neighbor cache before use 00031 * 00032 * \param neigh_cache pointer to neighbor cache. 00033 */ 00034 void neighbor_cache_init(neigh_cache_s *neigh_cache) 00035 { 00036 ns_list_init(&neigh_cache->head); 00037 } 00038 00039 /** 00040 * \brief A function to flush an entire neighbour cache 00041 * 00042 * \param neigh_cache pointer to neighbor cache. 00043 * 00044 * \return <n> The number of entries removed 00045 */ 00046 int neighbor_cache_flush(neigh_cache_s *neigh_cache) 00047 { 00048 int count = 0; 00049 00050 ns_list_foreach_safe(neigh_cache_entry_s, entry, &neigh_cache->head) { 00051 entry_delete(neigh_cache, entry); 00052 count++; 00053 } 00054 00055 return count; 00056 } 00057 00058 /** 00059 * \brief Extended internal implementation of neighbor_cache_entry_get 00060 * 00061 * \param neigh_cache pointer to neighbor cache. 00062 * \param address_type type for 16-bit or 64-bit address 00063 * \param address_ptr pointer to address of specified type 00064 * \param reorder true if permitted to reorder the list 00065 * 00066 * \return pointer to found entry 00067 * \return NULL if not found 00068 */ 00069 static neigh_cache_entry_s *entry_get(neigh_cache_s *neigh_cache, neighbor_address_type_e address_type, const void *address_ptr, bool reorder) 00070 { 00071 uint16_t mac16 = 0; 00072 neigh_cache_entry_s *entry = NULL; 00073 00074 if (address_type == NEIGH_16_BIT_ADDRESS) { 00075 mac16 = common_read_16_bit(address_ptr); 00076 } 00077 00078 ns_list_foreach(neigh_cache_entry_s, e, &neigh_cache->head) { 00079 bool match = false; 00080 switch (address_type) { 00081 case NEIGH_64_BIT_ADDRESS: 00082 match = memcmp(address_ptr, e->mac64, sizeof(entry->mac64)) == 0; 00083 break; 00084 case NEIGH_16_BIT_ADDRESS: 00085 match = e->mac16 == mac16; 00086 break; 00087 case NEIGH__TIMED_OUT: 00088 match = e->ttl == 0; 00089 break; 00090 } 00091 if (match) { 00092 entry = e; 00093 break; 00094 } 00095 } 00096 00097 if (!entry) { 00098 return NULL; 00099 } 00100 00101 /* 00102 * If permitted, move this entry to head of list, so frequently-used entries 00103 * stay near the top. 00104 */ 00105 if (entry != ns_list_get_first(&neigh_cache->head) && reorder) { 00106 ns_list_remove(&neigh_cache->head, entry); 00107 ns_list_add_to_start(&neigh_cache->head, entry); 00108 } 00109 00110 return entry; 00111 } 00112 00113 /** 00114 * \brief A function to locate a specific entry by address 00115 * 00116 * Note that this can re-order the cache, so could upset iteration using macros. 00117 * 00118 * \param neigh_cache pointer to neighbor cache. 00119 * \param address_type type for 16-bit or 64-bit address 00120 * \param address_ptr pointer to address of specified type 00121 * 00122 * \return pointer to cache entry 00123 * \return NULL if not found 00124 */ 00125 neigh_cache_entry_s *neighbor_cache_entry_get(neigh_cache_s *neigh_cache, neighbor_address_type_e address_type, const void *address_ptr) 00126 { 00127 return entry_get(neigh_cache, address_type, address_ptr, true); 00128 } 00129 00130 /** 00131 * \brief A function to create or return an existing neighbor cache entry. 00132 * 00133 * \param neigh_cache pointer to neighbor cache. 00134 * \param address_ptr pointer to EUI-64 address (64-bit) 00135 * 00136 * \return pointer to cache entry, possibly newly created. 00137 * \return NULL if entry not found an unable to allocate memory for new entry 00138 */ 00139 neigh_cache_entry_s *neighbor_cache_entry_create(neigh_cache_s *neigh_cache, const uint8_t address_ptr[8]) 00140 { 00141 neigh_cache_entry_s *entry; 00142 00143 entry = neighbor_cache_entry_get(neigh_cache, NEIGH_64_BIT_ADDRESS, address_ptr); 00144 if (entry) { 00145 return entry; 00146 } 00147 00148 entry = ns_dyn_mem_alloc(sizeof * entry); 00149 if (!entry) { 00150 return NULL; 00151 } 00152 00153 memset(entry, 0, sizeof * entry); 00154 memcpy(entry->mac64, address_ptr, sizeof entry->mac64); 00155 entry->mac16 = 0xFFFF; 00156 entry->neighbor_keypair_info = NULL; 00157 ns_list_add_to_start(&neigh_cache->head, entry); 00158 00159 return entry; 00160 } 00161 00162 /** 00163 * \brief Delete an entry from the list, including housekeeping 00164 * 00165 * \param neigh_cache pointer to neighbor cache. 00166 * \param entry pointer to entry 00167 */ 00168 static void entry_delete(neigh_cache_s *neigh_cache, neigh_cache_entry_s *entry) 00169 { 00170 ns_list_remove(&neigh_cache->head, entry); 00171 if (entry->neighbor_keypair_info) { 00172 ns_dyn_mem_free(entry->neighbor_keypair_info); 00173 } 00174 ns_dyn_mem_free(entry); 00175 } 00176 00177 /** 00178 * \brief A function to delete an entry by address. 00179 * 00180 * \param neigh_cache pointer to neighbor cache. 00181 * \param address_type type for 16-bit or 64-bit address 00182 * \param address_ptr pointer to address of specified type 00183 * 00184 * \return 0 Removed OK 00185 * \return -1 Entry not found 00186 */ 00187 int8_t neighbor_cache_entry_delete(neigh_cache_s *neigh_cache, neighbor_address_type_e address_type, const void *address_ptr) 00188 { 00189 neigh_cache_entry_s *entry; 00190 00191 entry = entry_get(neigh_cache, address_type, address_ptr, false); 00192 if (!entry) { 00193 return -1; 00194 } 00195 00196 entry_delete(neigh_cache, entry); 00197 00198 return 0; 00199 } 00200 00201 /** 00202 * \brief A function to delete an entry by entry pointer. 00203 * 00204 * \param neigh_cache pointer to neighbor cache. 00205 * \param entry pointer to entry 00206 * 00207 * \return pointer to the next entry, to allow deletion during iteration 00208 * \return NULL if no more entries 00209 * \return NEIGH_ENTRY_PTR_ERR if entry pointer not found (no longer checked) 00210 */ 00211 neigh_cache_entry_s *neighbor_cache_entry_delete_by_entry_pointer(neigh_cache_s *neigh_cache, neigh_cache_entry_s *entry) 00212 { 00213 neigh_cache_entry_s *next = ns_list_get_next(&neigh_cache->head, entry); 00214 00215 entry_delete(neigh_cache, entry); 00216 00217 return next; 00218 } 00219 00220 /** 00221 * \brief A function to update Neighbor cache Time-To-Live values. 00222 * 00223 * This decrements the TTL for all entries in the cache. TTL values are 00224 * are clamped to not wrap past zero. When an entry's TTL value becomes zero, 00225 * link_req_counter is set to NEIGH_LINK_REQUEST_COUNTER. (Note that 00226 * newly-created entries have ttl and link_req_counter both zero - they will 00227 * need initialising before use). 00228 * 00229 * \param neigh_cache pointer to neighbor cache. 00230 * \param tick amount to decrement TTL 00231 * 00232 * \return total number of entries in the cache whose TTL is 0 after the update 00233 */ 00234 int neighbor_cache_ttl_update(neigh_cache_s *neigh_cache, uint16_t ticks) 00235 { 00236 int count = 0; 00237 00238 ns_list_foreach(neigh_cache_entry_s, entry, &neigh_cache->head) { 00239 if (entry->ttl > ticks) { 00240 entry->ttl -= ticks; 00241 } else { 00242 if (entry->ttl > 0) { 00243 entry->link_req_counter = NEIGH_LINK_REQUEST_COUNTER; 00244 entry->ttl = 0; 00245 } 00246 count++; 00247 } 00248 } 00249 00250 return count; 00251 } 00252 00253 /** 00254 * \brief A function to get a timed-out neighbor entry. 00255 * 00256 * Returns an entry whose TTL field is set to zero. 00257 * 00258 * \param neigh_cache pointer to neighbor cache. 00259 * 00260 * \return pointer to a timed-out entry 00261 * \return NULL if no timed-out entries 00262 */ 00263 neigh_cache_entry_s *neighbor_cache_entry_get_timed_out(neigh_cache_s *neigh_cache) 00264 { 00265 return neighbor_cache_entry_get(neigh_cache, NEIGH__TIMED_OUT, NULL); 00266 } 00267 00268 #else // HAVE_NEIGHBOR_CACHE 00269 00270 void neighbor_cache_init(neigh_cache_s *neigh_cache) { 00271 (void)neigh_cache; 00272 } 00273 int neighbor_cache_flush(neigh_cache_s *neigh_cache){ 00274 (void)neigh_cache; 00275 return 0; 00276 } 00277 00278 #endif // HAVE_NEIGHBOR_CACHE
Generated on Tue Jul 12 2022 12:22:14 by
