Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mle.c
00001 /* 00002 * Copyright (c) 2013-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 00018 #include "nsconfig.h" 00019 #include "MLE/mle.h" 00020 00021 #ifndef NO_MLE 00022 #include "ns_types.h" 00023 #include "eventOS_event.h" 00024 #include "eventOS_event_timer.h" 00025 #include "socket_api.h" 00026 #include "Core/include/socket.h" 00027 #include "nsdynmemLIB.h" 00028 #include "ns_trace.h" 00029 #include "string.h" 00030 #include "NWK_INTERFACE/Include/protocol.h" 00031 #include "Common_Protocols/udp.h" 00032 #include "6LoWPAN/Thread/thread_common.h" 00033 #include "6LoWPAN/Thread/thread_bootstrap.h" 00034 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00035 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h" 00036 #include "platform/arm_hal_interrupt.h" 00037 #include "platform/topo_trace.h" 00038 #include "common_functions.h" 00039 #include "MLE/mle_tlv.h" 00040 #include "NWK_INTERFACE/Include/protocol_timer.h" 00041 #include "Common_Protocols/ipv6_constants.h" 00042 #include "Service_Libs/mle_service/mle_service_api.h" 00043 #include "Service_Libs/etx/etx.h" 00044 #include "6LoWPAN/MAC/mac_helper.h" 00045 #include "mac_api.h" 00046 #include "6LoWPAN/MAC/mac_data_poll.h" 00047 #include "6LoWPAN/lowpan_adaptation_interface.h" 00048 00049 #define MLE_UNICAST_CHALLENGE_TIMEOUT 20 00050 00051 #define TRACE_GROUP "mle" 00052 00053 typedef enum { 00054 ARM_MLE_INIT = 0, 00055 ARM_MLE_TTL_TIMER 00056 } arm_mle_event_id_e; 00057 00058 //MLE class structure 00059 typedef struct mle_table_class { 00060 int8_t interfaceId; 00061 mle_class_user_mode mode; 00062 mle_neigh_table_list_t mle_table; //Active Entry 00063 mle_neigh_table_list_t free_enty_list; 00064 mle_neigh_table_entry_t *allocated_buffer; 00065 uint8_t buffer_size; 00066 mle_entry_user_entry_remove_notify *remove_cb; 00067 mle_entry_link_keep_alive *keep_alive_cb; 00068 mle_entry_link_keep_alive *challenge_cb; 00069 mle_entry_interface_activate *interface_is_active; 00070 ns_list_link_t link; /*!< List link entry */ 00071 } mle_table_class_t; 00072 00073 static NS_LIST_DEFINE(mle_table_calss_list, mle_table_class_t, link); 00074 00075 static int8_t mle_tasklet_id = -1; 00076 00077 static arm_event_storage_t *mle_class_timer_storage = NULL; 00078 00079 static mle_neigh_table_entry_t *mle_class_neighbor_get(mle_neigh_table_list_t *mle_table, const uint8_t *address, addrtype_t type); 00080 static mle_neigh_table_entry_t *mle_class_get_free_entry(mle_neigh_table_list_t *mle_table); 00081 static bool mle_class_neighbor_validate(mle_neigh_table_list_t *mle_table, const mle_neigh_table_entry_t *entry); 00082 static void mle_event_handler(arm_event_s *event); 00083 00084 00085 static bool mle_table_timer_start(void) 00086 { 00087 if (!mle_class_timer_storage) { 00088 00089 arm_event_s event = { 00090 .receiver = mle_tasklet_id, 00091 .sender = 0, 00092 .event_id = 0, 00093 .data_ptr = NULL, 00094 .event_type = ARM_MLE_TTL_TIMER, 00095 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00096 }; 00097 00098 mle_class_timer_storage = eventOS_event_timer_request_every(&event, eventOS_event_timer_ms_to_ticks(MLE_TIMER_TICKS_MS)); 00099 if (!mle_class_timer_storage) { 00100 tr_error("Mle timer start fail"); 00101 return false; 00102 } 00103 } 00104 00105 return true; 00106 } 00107 00108 static void mle_table_timer_stop(void) 00109 { 00110 if (mle_class_timer_storage && ns_list_is_empty(&mle_table_calss_list)) { 00111 eventOS_cancel(mle_class_timer_storage); 00112 mle_class_timer_storage = NULL; 00113 } 00114 } 00115 00116 00117 static void mle_table_remove_free_indirect_table(int8_t interface_id, mle_neigh_table_entry_t *entry_ptr) 00118 { 00119 protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id); 00120 if (!cur_interface) { 00121 return; 00122 } 00123 //Free firts by defined short address 00124 if (entry_ptr->short_adr < 0xfffe) { 00125 uint8_t temp_address[2]; 00126 common_write_16_bit(entry_ptr->short_adr, temp_address); 00127 lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, temp_address, ADDR_802_15_4_SHORT ); 00128 } 00129 lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, entry_ptr->mac64, ADDR_802_15_4_LONG ); 00130 } 00131 00132 static void mle_table_class_list_free(mle_table_class_t *mle_table_class) { 00133 00134 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_table_class->mle_table) { 00135 ns_list_remove(&mle_table_class->mle_table, cur); 00136 //Clean Indirect queue 00137 mle_table_remove_free_indirect_table(mle_table_class->interfaceId, cur); 00138 //Call Remove callback 00139 mle_table_class->remove_cb(mle_table_class->interfaceId, cur); 00140 //Removes ETX neighbor 00141 etx_neighbor_remove(mle_table_class->interfaceId, cur); 00142 ns_list_add_to_start(&mle_table_class->free_enty_list, cur); 00143 } 00144 topo_trace(TOPOLOGY_MLE, NULL, TOPO_CLEAR); 00145 } 00146 00147 static void mle_table_class_free(mle_table_class_t *main_list) 00148 { 00149 ns_list_remove(&mle_table_calss_list, main_list); 00150 mle_table_class_list_free(main_list); 00151 //Free list buffer 00152 ns_dyn_mem_free(main_list->allocated_buffer); 00153 ns_dyn_mem_free(main_list); 00154 mle_table_timer_stop(); 00155 } 00156 00157 00158 00159 static int8_t mle_table_class_table_buffer_allocate(mle_table_class_t *mle_class, uint8_t list_size) 00160 { 00161 mle_neigh_table_entry_t *list_buffer = ns_dyn_mem_alloc(sizeof(mle_neigh_table_entry_t) * list_size); 00162 if (!list_buffer) { 00163 return -1; 00164 } 00165 00166 mle_class->allocated_buffer = list_buffer; //Save storaged 00167 ns_list_init(&mle_class->free_enty_list); 00168 ns_list_init(&mle_class->mle_table); 00169 for (uint8_t i = 0; i< list_size; i++) { 00170 memset(list_buffer, 0, sizeof(mle_neigh_table_entry_t)); 00171 00172 list_buffer->attribute_index = i; 00173 //Add to list 00174 ns_list_add_to_end(&mle_class->free_enty_list,list_buffer); 00175 list_buffer++; 00176 } 00177 return 0; 00178 } 00179 00180 00181 static mle_table_class_t * mle_table_class_allocate(int8_t interfaceId, uint8_t list_size) 00182 { 00183 mle_table_class_t *newClass = ns_dyn_mem_alloc(sizeof(mle_table_class_t)); 00184 00185 if (newClass) { 00186 memset(newClass, 0, sizeof(mle_table_class_t)); 00187 if (mle_table_class_table_buffer_allocate(newClass,list_size) != 0) { 00188 ns_dyn_mem_free(newClass); 00189 return NULL; 00190 } 00191 newClass->interfaceId = interfaceId; 00192 newClass->buffer_size = list_size; 00193 } 00194 return newClass; 00195 } 00196 00197 static mle_table_class_t * mle_table_class_discover(int8_t interface_id) { 00198 ns_list_foreach(mle_table_class_t, cur_mle_class, &mle_table_calss_list) { 00199 if (cur_mle_class->interfaceId == interface_id) { 00200 return cur_mle_class; 00201 } 00202 } 00203 return NULL; 00204 } 00205 00206 static int8_t mle_class_event_handler_init(void) { 00207 if (mle_tasklet_id == -1) { 00208 //GENERATE TASKLET 00209 mle_tasklet_id = eventOS_event_handler_create(&mle_event_handler, ARM_MLE_INIT); 00210 00211 } 00212 00213 return mle_tasklet_id; 00214 } 00215 00216 int8_t mle_class_init(int8_t interface_id, uint8_t table_size, mle_entry_user_entry_remove_notify *remove_cb, mle_entry_link_keep_alive *keep_alive_cb, mle_entry_interface_activate *interface_is_active) 00217 { 00218 //Discover from the list 00219 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00220 //Clean list and set function pointer call backs 00221 if (mle_class_ptr) { 00222 mle_class_ptr->remove_cb = remove_cb; 00223 mle_class_ptr->keep_alive_cb = keep_alive_cb; 00224 mle_class_ptr->challenge_cb = NULL; 00225 mle_class_ptr->interface_is_active = interface_is_active; 00226 if (mle_class_ptr->buffer_size != table_size) { //Clean tabs only when table size is different 00227 mle_table_class_list_free(mle_class_ptr); 00228 ns_dyn_mem_free(mle_class_ptr->allocated_buffer); 00229 mle_class_ptr->allocated_buffer = NULL; 00230 //Reallocate 00231 if (mle_table_class_table_buffer_allocate(mle_class_ptr,table_size) != 0) { 00232 ns_list_remove(&mle_table_calss_list, mle_class_ptr); 00233 ns_dyn_mem_free(mle_class_ptr); 00234 return -2; 00235 } 00236 mle_class_ptr->buffer_size = table_size; 00237 } 00238 return 0; 00239 } 00240 00241 if (mle_class_event_handler_init() < 0) { 00242 return -2; 00243 } 00244 00245 if (!mle_table_timer_start()) { 00246 return -2; 00247 } 00248 00249 mle_class_ptr = mle_table_class_allocate(interface_id, table_size); 00250 //Allocate new 00251 if (!mle_class_ptr) { 00252 return -2; 00253 } 00254 00255 tr_debug("MLE service init size %d", table_size); 00256 mle_class_ptr->remove_cb = remove_cb; 00257 mle_class_ptr->keep_alive_cb = keep_alive_cb; 00258 mle_class_ptr->challenge_cb = NULL; 00259 mle_class_ptr->interface_is_active = interface_is_active; 00260 ns_list_add_to_end(&mle_table_calss_list, mle_class_ptr); 00261 return 0; 00262 00263 } 00264 00265 int8_t mle_class_router_challenge(int8_t interface_id,mle_entry_link_keep_alive *challenge_cb) 00266 { 00267 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00268 //Clean list and set function pointer call backs 00269 if (!mle_class_ptr) { 00270 return -1; 00271 } 00272 mle_class_ptr->challenge_cb = challenge_cb; 00273 return 0; 00274 } 00275 00276 bool mle_class_exists_for_interface(int8_t interface_id) { 00277 00278 if (mle_table_class_discover(interface_id)) { 00279 return true; 00280 } 00281 00282 return false; 00283 } 00284 00285 int8_t mle_class_deallocate(int8_t interface_id) 00286 { 00287 //Discover from the list 00288 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00289 //Clean list and set function pointer call backs 00290 if (!mle_class_ptr) { 00291 return -1; 00292 } 00293 00294 mle_table_class_free(mle_class_ptr); 00295 return 0; 00296 00297 } 00298 00299 int8_t mle_class_list_clean(int8_t interface_id) 00300 { 00301 //Discover from the list 00302 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00303 //Clean list and set function pointer call backs 00304 if (!mle_class_ptr) { 00305 return -1; 00306 } 00307 00308 mle_table_class_list_free(mle_class_ptr); 00309 return 0; 00310 00311 } 00312 00313 int8_t mle_class_mode_set(int8_t interface_id,mle_class_user_mode mode) 00314 { 00315 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00316 //Clean list and set function pointer call backs 00317 if (!mle_class_ptr) { 00318 return -1; 00319 } 00320 mle_class_ptr->mode = mode; 00321 00322 return 0; 00323 } 00324 00325 int8_t mle_class_set_new_key_pending(int8_t interface_id) 00326 { 00327 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00328 00329 if (!mle_class_ptr) { 00330 return -1; 00331 } 00332 00333 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_class_ptr->mle_table) { 00334 cur->new_key_pending = true; 00335 } 00336 00337 return 0; 00338 } 00339 00340 int16_t mle_class_free_entry_count_get(int8_t interface_id) 00341 { 00342 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00343 //Clean list and set function pointer call backs 00344 if (!mle_class_ptr) { 00345 return 0; 00346 } 00347 return ns_list_count(&(mle_class_ptr->free_enty_list)); 00348 00349 } 00350 00351 int16_t mle_class_sleepy_entry_count_get(int8_t interface_id) 00352 { 00353 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00354 00355 if (!mle_class_ptr) { 00356 return 0; 00357 } 00358 00359 uint16_t count = 0; 00360 00361 ns_list_foreach(mle_neigh_table_entry_t, entry, &mle_class_ptr->mle_table) { 00362 if (!(entry->mode & MLE_RX_ON_IDLE)) { 00363 count++; 00364 } 00365 } 00366 00367 return count; 00368 } 00369 00370 int16_t mle_class_rfd_entry_count_get(int8_t interface_id) 00371 { 00372 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00373 00374 if (!mle_class_ptr) { 00375 return 0; 00376 } 00377 00378 uint16_t count = 0; 00379 00380 ns_list_foreach(mle_neigh_table_entry_t, entry, &mle_class_ptr->mle_table) { 00381 if ((entry->mode & MLE_DEV_MASK) == MLE_RFD_DEV) { 00382 count++; 00383 } 00384 } 00385 00386 return count; 00387 } 00388 00389 mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_t linkMargin, const uint8_t *ipv6Address, bool allocateNew, bool *new_entry_allocated) 00390 { 00391 // Check it really is LL64 (not LL16) 00392 00393 if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX , 8) != 0) { 00394 return NULL; //Mot Link Local Address 00395 } 00396 00397 if (memcmp((ipv6Address + 8), ADDR_SHORT_ADR_SUFFIC , 6) == 0) { 00398 return NULL; 00399 } 00400 // map 00401 uint8_t temporary_mac64[8]; 00402 memcpy(temporary_mac64, (ipv6Address + 8), 8); 00403 temporary_mac64[0] ^= 2; 00404 00405 return mle_class_get_entry_by_mac64(interface_id, linkMargin, temporary_mac64, allocateNew, new_entry_allocated); 00406 } 00407 00408 mle_neigh_table_entry_t *mle_class_discover_entry_by_ll64(int8_t interface_id, const uint8_t *ipv6Address) 00409 { 00410 00411 // Check it really is LL64 (not LL16) 00412 00413 if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX , 8) != 0) { 00414 return NULL; //Mot Link Local Address 00415 } 00416 00417 if (memcmp((ipv6Address + 8), ADDR_SHORT_ADR_SUFFIC , 6) == 0) { 00418 return NULL; 00419 } 00420 // map 00421 uint8_t temporary_mac64[8]; 00422 memcpy(temporary_mac64, (ipv6Address + 8), 8); 00423 temporary_mac64[0] ^= 2; 00424 00425 return mle_class_get_by_link_address(interface_id, temporary_mac64, ADDR_802_15_4_LONG ); 00426 } 00427 00428 00429 mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated) 00430 { 00431 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00432 //Clean list and set function pointer call backs 00433 if (!mle_class_ptr) { 00434 return NULL; 00435 } 00436 00437 if (new_entry_allocated) { 00438 *new_entry_allocated = false; 00439 } 00440 00441 mle_neigh_table_entry_t *ret_val = mle_class_neighbor_get(&mle_class_ptr->mle_table, mac64, ADDR_802_15_4_LONG ); 00442 00443 00444 /* Look for existing entry */ 00445 if (ret_val) { 00446 ret_val->link_margin = ret_val->link_margin + linkMargin - (ret_val->link_margin >> THREAD_LINK_MARGIN_SCALING); 00447 return ret_val; 00448 } 00449 00450 if (allocateNew) { 00451 ret_val = mle_class_get_free_entry(&mle_class_ptr->free_enty_list); 00452 00453 if (ret_val) { 00454 //Add to active list 00455 ns_list_add_to_start(&mle_class_ptr->mle_table, ret_val); 00456 topo_trace(TOPOLOGY_MLE, mac64, TOPO_ADD); 00457 ret_val->link_margin = linkMargin << THREAD_LINK_MARGIN_SCALING; 00458 memcpy(ret_val->mac64, mac64, 8); 00459 if (new_entry_allocated) { 00460 *new_entry_allocated = true; 00461 } 00462 } 00463 } 00464 return ret_val; 00465 } 00466 00467 static mle_neigh_table_entry_t *mle_class_neighbor_get_by_attribute_index(mle_neigh_table_list_t *mle_table, uint8_t attribute_index) 00468 { 00469 00470 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00471 if (cur->attribute_index == attribute_index) { 00472 return cur; 00473 } 00474 } 00475 return NULL; 00476 } 00477 00478 static bool mle_class_neighbor_validate(mle_neigh_table_list_t *mle_table, const mle_neigh_table_entry_t *entry) 00479 { 00480 00481 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00482 if (cur == entry) { 00483 return true; 00484 } 00485 } 00486 return false; 00487 } 00488 00489 static mle_neigh_table_entry_t *mle_class_neighbor_get(mle_neigh_table_list_t *mle_table, const uint8_t *address, addrtype_t type) 00490 { 00491 uint16_t short_id; 00492 if (type == ADDR_802_15_4_SHORT ) { 00493 short_id = common_read_16_bit(address); 00494 } 00495 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00496 00497 if (type == ADDR_802_15_4_SHORT ) { 00498 if (cur->short_adr == short_id) { 00499 return cur; 00500 } 00501 } else { 00502 if (memcmp(cur->mac64, address, 8) == 0) { 00503 return cur; 00504 } 00505 } 00506 00507 } 00508 return NULL; 00509 } 00510 00511 static mle_neigh_table_entry_t *mle_class_get_free_entry(mle_neigh_table_list_t *mle_table) 00512 { 00513 mle_neigh_table_entry_t *mle_entry = ns_list_get_first(mle_table); 00514 if (mle_entry) { 00515 //Remove from the list 00516 ns_list_remove(mle_table, mle_entry); 00517 uint8_t attribute_id = mle_entry->attribute_index; 00518 memset(mle_entry, 0, sizeof(mle_neigh_table_entry_t)); 00519 mle_entry->attribute_index = attribute_id; 00520 mle_entry->short_adr = 0xffff; 00521 mle_entry->mode = MLE_FFD_DEV | MLE_RX_ON_IDLE; 00522 mle_entry->holdTime = 7; 00523 mle_entry->last_contact_time = protocol_core_monotonic_time; 00524 mle_entry->mle_frame_counter = 0; 00525 mle_entry->last_key_sequence = 0; 00526 mle_entry->new_key_pending = false; 00527 mle_entry->medium_ttl_challenge = false; 00528 } 00529 00530 return mle_entry; 00531 } 00532 00533 00534 00535 mle_neigh_table_entry_t *mle_class_get_by_link_address(int8_t interface_id, const uint8_t *address, addrtype_t type) 00536 { 00537 switch (type) { 00538 case ADDR_802_15_4_SHORT : 00539 case ADDR_802_15_4_LONG : 00540 00541 break; 00542 default: 00543 return NULL; 00544 } 00545 00546 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00547 //Clean list and set function pointer call backs 00548 if (!mle_class_ptr) { 00549 return NULL; 00550 } 00551 00552 return mle_class_neighbor_get(&mle_class_ptr->mle_table, address, type); 00553 00554 } 00555 00556 mle_neigh_table_entry_t *mle_class_get_by_device_attribute_id(int8_t interface_id, uint8_t attribute_index) 00557 { 00558 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00559 //Clean list and set function pointer call backs 00560 if (!mle_class_ptr) { 00561 return NULL; 00562 } 00563 00564 return mle_class_neighbor_get_by_attribute_index(&mle_class_ptr->mle_table, attribute_index); 00565 00566 } 00567 00568 int8_t mle_class_remove_entry(int8_t interface_id, mle_neigh_table_entry_t *entry) 00569 { 00570 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00571 //Clean list and set function pointer call backs 00572 if (!mle_class_ptr) { 00573 return -1; 00574 } 00575 00576 //Validate Pointer 00577 if (!mle_class_neighbor_validate(&mle_class_ptr->mle_table, entry)) { 00578 return -2; 00579 } 00580 //Remove from list 00581 ns_list_remove(&mle_class_ptr->mle_table, entry); 00582 //Free Indirect Queue 00583 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, entry); 00584 //Call Remove callback 00585 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, entry); 00586 topo_trace(TOPOLOGY_MLE, entry->ext64, TOPO_REMOVE); 00587 00588 //Removes ETX neighbor 00589 etx_neighbor_remove(interface_id, entry); 00590 //Add to free list 00591 ns_list_add_to_start(&mle_class_ptr->free_enty_list, entry); 00592 return 0; 00593 } 00594 00595 int8_t mle_class_remove_neighbour(int8_t interface_id, const uint8_t *address, addrtype_t type) 00596 { 00597 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00598 //Clean list and set function pointer call backs 00599 if (!mle_class_ptr) { 00600 return -1; 00601 } 00602 00603 mle_neigh_table_entry_t * entry = mle_class_get_by_link_address(interface_id, address, type); 00604 if (!entry) { 00605 return -2; 00606 } 00607 //Remove from list 00608 ns_list_remove(&mle_class_ptr->mle_table, entry); 00609 //Free Indirect Queue 00610 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, entry); 00611 //Call Remove callback 00612 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, entry); 00613 00614 topo_trace(TOPOLOGY_MLE, entry->ext64, TOPO_REMOVE); 00615 00616 //Removes ETX neighbor 00617 etx_neighbor_remove(interface_id, entry); 00618 //Add to free list 00619 ns_list_add_to_start(&mle_class_ptr->free_enty_list, entry); 00620 00621 return 0; 00622 00623 } 00624 00625 00626 00627 static void mle_class_table_ttl(uint16_t ticks, mle_table_class_t *mle_class_ptr) 00628 { 00629 uint16_t new_ttl; 00630 bool challengeCheck; 00631 bool remove_entry; 00632 00633 //validate that interface is still active 00634 if (!mle_class_ptr->interface_is_active(mle_class_ptr->interfaceId)) { 00635 return; 00636 } 00637 00638 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_class_ptr->mle_table) { 00639 new_ttl = 0; 00640 remove_entry = false; 00641 switch (mle_class_ptr->mode) { 00642 case MLE_CLASS_END_DEVICE: 00643 if (cur->priorityFlag) { 00644 challengeCheck = true; 00645 } else { 00646 challengeCheck = false; 00647 } 00648 break; 00649 case MLE_CLASS_ROUTER: //Router and sleepy end device never do challenge 00650 default: 00651 challengeCheck = false; 00652 break; 00653 } 00654 00655 if (challengeCheck) { 00656 if (cur->ttl > MLE_TABLE_CHALLENGE_TIMER || cur->ttl < MLE_TABLE_CHALLENGE_TIMER) { 00657 new_ttl = ticks + MLE_TABLE_CHALLENGE_TIMER; 00658 } 00659 00660 if (cur->ttl <= new_ttl) { 00661 if (cur->ttl != 1) { 00662 if (mle_class_ptr->keep_alive_cb(mle_class_ptr->interfaceId, cur->mac64) != 0) { 00663 cur->ttl--; 00664 if (cur->ttl == 1) { 00665 remove_entry = true; 00666 } 00667 } else { 00668 cur->ttl = 1; //Lock retries here 00669 } 00670 } 00671 } else { 00672 cur->ttl -= ticks; 00673 } 00674 } else { 00675 if (ticks >= cur->ttl) { 00676 00677 remove_entry = true; 00678 } else { 00679 cur->ttl -= ticks; 00680 } 00681 } 00682 00683 if (remove_entry) { 00684 //Silence delete 00685 //Remove from list 00686 ns_list_remove(&mle_class_ptr->mle_table, cur); 00687 //Free Indirect Queue 00688 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, cur); 00689 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, cur); 00690 topo_trace(TOPOLOGY_MLE, cur->ext64, TOPO_REMOVE); 00691 //Removes ETX neighbor 00692 etx_neighbor_remove(mle_class_ptr->interfaceId, cur); 00693 //Add to free list 00694 ns_list_add_to_start(&mle_class_ptr->free_enty_list, cur); 00695 00696 } 00697 } // for each entry 00698 00699 //Router to Router Challenge timeout for big network and FHSS systems which could loose broadcast messages. 00700 if (mle_class_ptr->challenge_cb && mle_class_ptr->mode == MLE_CLASS_ROUTER) { 00701 //Calculate timeout trigger 00702 uint8_t challenge_count = 0; 00703 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_class_ptr->mle_table) { 00704 if (((cur->mode & MLE_DEV_MASK) == MLE_FFD_DEV) && !cur->medium_ttl_challenge) { 00705 //Challenge Neighbour 00706 if (cur->ttl < (cur->timeout_rx / 2)) { 00707 if (mle_class_ptr->challenge_cb(mle_class_ptr->interfaceId, cur->mac64) != 0) { 00708 tr_error("Router2Router challenge start fail"); 00709 return; 00710 } 00711 cur->medium_ttl_challenge = true; 00712 if (++challenge_count == 2) { 00713 //trig only 2 active / 4 second period. 00714 return; 00715 } 00716 } 00717 } 00718 } 00719 } 00720 } 00721 00722 00723 mle_neigh_table_list_t *mle_class_active_list_get(int8_t interface_id) 00724 { 00725 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00726 //Clean list and set function pointer call backs 00727 if (!mle_class_ptr) { 00728 return NULL; 00729 } 00730 return &mle_class_ptr->mle_table; 00731 } 00732 00733 uint16_t mle_class_active_neigh_counter(int8_t interface_id) 00734 { 00735 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00736 //Clean list and set function pointer call backs 00737 if (!mle_class_ptr) { 00738 return 0xffff; 00739 } 00740 00741 00742 return ns_list_count(&mle_class_ptr->mle_table); 00743 } 00744 00745 uint8_t *mle_general_write_source_address(uint8_t *ptr, protocol_interface_info_entry_t *cur) 00746 { 00747 if (cur->global_address_available) { 00748 uint16_t mac16 = mac_helper_mac16_address_get(cur); 00749 if (mac16 < 0xfffe) { 00750 ptr = mle_tlv_write_source_address(ptr, mac16); 00751 } 00752 } 00753 return ptr; 00754 } 00755 00756 uint8_t *mle_general_write_link_layer_framecounter(uint8_t *ptr, protocol_interface_info_entry_t *cur) 00757 { 00758 uint32_t temp_counter; 00759 mac_helper_link_frame_counter_read(cur->id, &temp_counter); 00760 return mle_tlv_write_link_layer_framecount(ptr, temp_counter); 00761 } 00762 00763 static void mle_event_handler(arm_event_s *event) 00764 { 00765 switch (event->event_type) { 00766 case ARM_MLE_INIT: 00767 tr_debug("MLE Tasklet Generated"); 00768 break; 00769 00770 case ARM_MLE_TTL_TIMER: 00771 //Do list in future for each of mle user 00772 //Set here mle class ttl update 00773 ns_list_foreach_safe(mle_table_class_t, mle_clas_entry, &mle_table_calss_list) { 00774 mle_class_table_ttl(1, mle_clas_entry); 00775 } 00776 00777 00778 break; 00779 } 00780 } 00781 00782 bool mle_neigh_entry_frame_counter_update(mle_neigh_table_entry_t *entry_temp, uint8_t *tlv_ptr, uint16_t tlv_length, protocol_interface_info_entry_t *cur, uint8_t key_id) 00783 { 00784 mle_tlv_info_t mle_tlv_info; 00785 uint32_t frame_counter; 00786 if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_LL_FRAME_COUNTER, &mle_tlv_info) != 4) { 00787 if (cur->mac_parameters->SecurityEnabled) { 00788 return false; 00789 } else { 00790 frame_counter = 0; 00791 } 00792 } else { 00793 frame_counter = common_read_32_bit(mle_tlv_info.dataPtr); 00794 } 00795 00796 mac_helper_devicetable_set(entry_temp, cur, frame_counter, key_id, false); 00797 return true; 00798 } 00799 00800 void mle_entry_timeout_update(mle_neigh_table_entry_t *entry_temp, uint32_t timeout_tlv) 00801 { 00802 if (timeout_tlv > 86400) { 00803 timeout_tlv = 86400; 00804 } else if (timeout_tlv == 0) { 00805 timeout_tlv = 500; 00806 } 00807 timeout_tlv /= MLE_TIMER_TICKS_SECONDS; 00808 timeout_tlv++; 00809 entry_temp->timeout_rx = timeout_tlv; 00810 mle_entry_timeout_refresh(entry_temp); 00811 } 00812 00813 void mle_entry_timeout_refresh(mle_neigh_table_entry_t *entry_temp) 00814 { 00815 entry_temp->ttl = entry_temp->timeout_rx; 00816 entry_temp->last_contact_time = protocol_core_monotonic_time; 00817 entry_temp->medium_ttl_challenge = false; 00818 } 00819 00820 static void mle_refresh_entry(mle_neigh_table_entry_t *neig_info, bool dataPollConfirmation) 00821 { 00822 if (!neig_info) { 00823 return; 00824 } 00825 if (!neig_info->handshakeReady) { 00826 tr_debug("refresh:Link Handshake not ready yet"); 00827 return; 00828 } 00829 00830 neig_info->last_contact_time = protocol_core_monotonic_time; 00831 neig_info->medium_ttl_challenge = false; 00832 00833 if (dataPollConfirmation) { 00834 if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) { 00835 neig_info->ttl = neig_info->timeout_rx; 00836 } 00837 } else { 00838 neig_info->ttl = neig_info->timeout_rx; 00839 } 00840 } 00841 00842 mle_neigh_table_entry_t *mle_refresh_entry_timeout(int8_t interfaceId, const uint8_t *addressPtr, addrtype_t addressType, bool dataPollConfirmation) 00843 { 00844 mle_neigh_table_entry_t * neigh_info = mle_class_get_by_link_address(interfaceId, addressPtr, addressType); 00845 mle_refresh_entry(neigh_info, dataPollConfirmation); 00846 return neigh_info; 00847 } 00848 00849 #endif /* NO_MLE */
Generated on Tue Jul 12 2022 12:45:32 by
