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) 00390 { 00391 00392 // Check it really is LL64 (not LL16) 00393 00394 if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX , 8) != 0) { 00395 return NULL; //Mot Link Local Address 00396 } 00397 00398 if (memcmp((ipv6Address + 8), ADDR_SHORT_ADR_SUFFIC , 6) == 0) { 00399 return NULL; 00400 } 00401 // map 00402 uint8_t temporary_mac64[8]; 00403 memcpy(temporary_mac64, (ipv6Address + 8), 8); 00404 temporary_mac64[0] ^= 2; 00405 00406 return mle_class_get_entry_by_mac64(interface_id, linkMargin, temporary_mac64,allocateNew); 00407 } 00408 00409 00410 mle_neigh_table_entry_t *mle_class_discover_entry_by_ll64(int8_t interface_id, const uint8_t *ipv6Address) 00411 { 00412 00413 // Check it really is LL64 (not LL16) 00414 00415 if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX , 8) != 0) { 00416 return NULL; //Mot Link Local Address 00417 } 00418 00419 if (memcmp((ipv6Address + 8), ADDR_SHORT_ADR_SUFFIC , 6) == 0) { 00420 return NULL; 00421 } 00422 // map 00423 uint8_t temporary_mac64[8]; 00424 memcpy(temporary_mac64, (ipv6Address + 8), 8); 00425 temporary_mac64[0] ^= 2; 00426 00427 return mle_class_get_by_link_address(interface_id, temporary_mac64, ADDR_802_15_4_LONG ); 00428 } 00429 00430 00431 mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew) 00432 { 00433 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00434 //Clean list and set function pointer call backs 00435 if (!mle_class_ptr) { 00436 return NULL; 00437 } 00438 00439 mle_neigh_table_entry_t *ret_val = mle_class_neighbor_get(&mle_class_ptr->mle_table, mac64, ADDR_802_15_4_LONG ); 00440 00441 00442 /* Look for existing entry */ 00443 if (ret_val) { 00444 ret_val->link_margin = ret_val->link_margin + linkMargin - (ret_val->link_margin >> THREAD_LINK_MARGIN_SCALING); 00445 return ret_val; 00446 } 00447 00448 if (allocateNew) { 00449 ret_val = mle_class_get_free_entry(&mle_class_ptr->free_enty_list); 00450 00451 if (ret_val) { 00452 //Add to active list 00453 ns_list_add_to_start(&mle_class_ptr->mle_table, ret_val); 00454 topo_trace(TOPOLOGY_MLE, mac64, TOPO_ADD); 00455 ret_val->link_margin = linkMargin << THREAD_LINK_MARGIN_SCALING; 00456 memcpy(ret_val->mac64, mac64, 8); 00457 } 00458 } 00459 return ret_val; 00460 } 00461 00462 static mle_neigh_table_entry_t *mle_class_neighbor_get_by_attribute_index(mle_neigh_table_list_t *mle_table, uint8_t attribute_index) 00463 { 00464 00465 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00466 if (cur->attribute_index == attribute_index) { 00467 return cur; 00468 } 00469 } 00470 return NULL; 00471 } 00472 00473 static bool mle_class_neighbor_validate(mle_neigh_table_list_t *mle_table, const mle_neigh_table_entry_t *entry) 00474 { 00475 00476 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00477 if (cur == entry) { 00478 return true; 00479 } 00480 } 00481 return false; 00482 } 00483 00484 static mle_neigh_table_entry_t *mle_class_neighbor_get(mle_neigh_table_list_t *mle_table, const uint8_t *address, addrtype_t type) 00485 { 00486 uint16_t short_id; 00487 if (type == ADDR_802_15_4_SHORT ) { 00488 short_id = common_read_16_bit(address); 00489 } 00490 ns_list_foreach(mle_neigh_table_entry_t, cur, mle_table) { 00491 00492 if (type == ADDR_802_15_4_SHORT ) { 00493 if (cur->short_adr == short_id) { 00494 return cur; 00495 } 00496 } else { 00497 if (memcmp(cur->mac64, address, 8) == 0) { 00498 return cur; 00499 } 00500 } 00501 00502 } 00503 return NULL; 00504 } 00505 00506 static mle_neigh_table_entry_t *mle_class_get_free_entry(mle_neigh_table_list_t *mle_table) 00507 { 00508 mle_neigh_table_entry_t *mle_entry = ns_list_get_first(mle_table); 00509 if (mle_entry) { 00510 //Remove from the list 00511 ns_list_remove(mle_table, mle_entry); 00512 uint8_t attribute_id = mle_entry->attribute_index; 00513 memset(mle_entry, 0, sizeof(mle_neigh_table_entry_t)); 00514 mle_entry->attribute_index = attribute_id; 00515 mle_entry->short_adr = 0xffff; 00516 mle_entry->mode = MLE_FFD_DEV | MLE_RX_ON_IDLE; 00517 mle_entry->holdTime = 7; 00518 mle_entry->last_contact_time = protocol_core_monotonic_time; 00519 mle_entry->mle_frame_counter = 0; 00520 mle_entry->last_key_sequence = 0; 00521 mle_entry->new_key_pending = false; 00522 mle_entry->medium_ttl_challenge = false; 00523 } 00524 00525 return mle_entry; 00526 } 00527 00528 00529 00530 mle_neigh_table_entry_t *mle_class_get_by_link_address(int8_t interface_id, const uint8_t *address, addrtype_t type) 00531 { 00532 switch (type) { 00533 case ADDR_802_15_4_SHORT : 00534 case ADDR_802_15_4_LONG : 00535 00536 break; 00537 default: 00538 return NULL; 00539 } 00540 00541 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00542 //Clean list and set function pointer call backs 00543 if (!mle_class_ptr) { 00544 return NULL; 00545 } 00546 00547 return mle_class_neighbor_get(&mle_class_ptr->mle_table, address, type); 00548 00549 } 00550 00551 mle_neigh_table_entry_t *mle_class_get_by_device_attribute_id(int8_t interface_id, uint8_t attribute_index) 00552 { 00553 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00554 //Clean list and set function pointer call backs 00555 if (!mle_class_ptr) { 00556 return NULL; 00557 } 00558 00559 return mle_class_neighbor_get_by_attribute_index(&mle_class_ptr->mle_table, attribute_index); 00560 00561 } 00562 00563 int8_t mle_class_remove_entry(int8_t interface_id, mle_neigh_table_entry_t *entry) 00564 { 00565 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00566 //Clean list and set function pointer call backs 00567 if (!mle_class_ptr) { 00568 return -1; 00569 } 00570 00571 //Validate Pointer 00572 if (!mle_class_neighbor_validate(&mle_class_ptr->mle_table, entry)) { 00573 return -2; 00574 } 00575 //Remove from list 00576 ns_list_remove(&mle_class_ptr->mle_table, entry); 00577 //Free Indirect Queue 00578 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, entry); 00579 //Call Remove callback 00580 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, entry); 00581 topo_trace(TOPOLOGY_MLE, entry->ext64, TOPO_REMOVE); 00582 00583 //Removes ETX neighbor 00584 etx_neighbor_remove(interface_id, entry); 00585 //Add to free list 00586 ns_list_add_to_start(&mle_class_ptr->free_enty_list, entry); 00587 return 0; 00588 } 00589 00590 int8_t mle_class_remove_neighbour(int8_t interface_id, const uint8_t *address, addrtype_t type) 00591 { 00592 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00593 //Clean list and set function pointer call backs 00594 if (!mle_class_ptr) { 00595 return -1; 00596 } 00597 00598 mle_neigh_table_entry_t * entry = mle_class_get_by_link_address(interface_id, address, type); 00599 if (!entry) { 00600 return -2; 00601 } 00602 //Remove from list 00603 ns_list_remove(&mle_class_ptr->mle_table, entry); 00604 //Free Indirect Queue 00605 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, entry); 00606 //Call Remove callback 00607 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, entry); 00608 00609 topo_trace(TOPOLOGY_MLE, entry->ext64, TOPO_REMOVE); 00610 00611 //Removes ETX neighbor 00612 etx_neighbor_remove(interface_id, entry); 00613 //Add to free list 00614 ns_list_add_to_start(&mle_class_ptr->free_enty_list, entry); 00615 00616 return 0; 00617 00618 } 00619 00620 00621 00622 static void mle_class_table_ttl(uint16_t ticks, mle_table_class_t *mle_class_ptr) 00623 { 00624 uint16_t new_ttl; 00625 bool challengeCheck; 00626 bool remove_entry; 00627 00628 //validate that interface is still active 00629 if (!mle_class_ptr->interface_is_active(mle_class_ptr->interfaceId)) { 00630 return; 00631 } 00632 00633 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_class_ptr->mle_table) { 00634 new_ttl = 0; 00635 remove_entry = false; 00636 switch (mle_class_ptr->mode) { 00637 case MLE_CLASS_END_DEVICE: 00638 if (cur->priorityFlag) { 00639 challengeCheck = true; 00640 } else { 00641 challengeCheck = false; 00642 } 00643 break; 00644 case MLE_CLASS_ROUTER: //Router and sleepy end device never do challenge 00645 default: 00646 challengeCheck = false; 00647 break; 00648 } 00649 00650 if (challengeCheck) { 00651 if (cur->ttl > MLE_TABLE_CHALLENGE_TIMER || cur->ttl < MLE_TABLE_CHALLENGE_TIMER) { 00652 new_ttl = ticks + MLE_TABLE_CHALLENGE_TIMER; 00653 } 00654 00655 if (cur->ttl <= new_ttl) { 00656 if (cur->ttl != 1) { 00657 if (mle_class_ptr->keep_alive_cb(mle_class_ptr->interfaceId, cur->mac64) != 0) { 00658 cur->ttl--; 00659 if (cur->ttl == 1) { 00660 remove_entry = true; 00661 } 00662 } else { 00663 cur->ttl = 1; //Lock retries here 00664 } 00665 } 00666 } else { 00667 cur->ttl -= ticks; 00668 } 00669 } else { 00670 if (ticks >= cur->ttl) { 00671 00672 remove_entry = true; 00673 } else { 00674 cur->ttl -= ticks; 00675 } 00676 } 00677 00678 if (remove_entry) { 00679 //Silence delete 00680 //Remove from list 00681 ns_list_remove(&mle_class_ptr->mle_table, cur); 00682 //Free Indirect Queue 00683 mle_table_remove_free_indirect_table(mle_class_ptr->interfaceId, cur); 00684 mle_class_ptr->remove_cb(mle_class_ptr->interfaceId, cur); 00685 topo_trace(TOPOLOGY_MLE, cur->ext64, TOPO_REMOVE); 00686 //Removes ETX neighbor 00687 etx_neighbor_remove(mle_class_ptr->interfaceId, cur); 00688 //Add to free list 00689 ns_list_add_to_start(&mle_class_ptr->free_enty_list, cur); 00690 00691 } 00692 } // for each entry 00693 00694 //Router to Router Challenge timeout for big network and FHSS systems which could loose broadcast messages. 00695 if (mle_class_ptr->challenge_cb && mle_class_ptr->mode == MLE_CLASS_ROUTER) { 00696 //Calculate timeout trigger 00697 uint8_t challenge_count = 0; 00698 ns_list_foreach_safe(mle_neigh_table_entry_t, cur, &mle_class_ptr->mle_table) { 00699 if (((cur->mode & MLE_DEV_MASK) == MLE_FFD_DEV) && !cur->medium_ttl_challenge) { 00700 //Challenge Neighbour 00701 if (cur->ttl < (cur->timeout_rx / 2)) { 00702 if (mle_class_ptr->challenge_cb(mle_class_ptr->interfaceId, cur->mac64) != 0) { 00703 tr_error("Router2Router challenge start fail"); 00704 return; 00705 } 00706 cur->medium_ttl_challenge = true; 00707 if (++challenge_count == 2) { 00708 //trig only 2 active / 4 second period. 00709 return; 00710 } 00711 } 00712 } 00713 } 00714 } 00715 } 00716 00717 00718 mle_neigh_table_list_t *mle_class_active_list_get(int8_t interface_id) 00719 { 00720 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00721 //Clean list and set function pointer call backs 00722 if (!mle_class_ptr) { 00723 return NULL; 00724 } 00725 return &mle_class_ptr->mle_table; 00726 } 00727 00728 uint16_t mle_class_active_neigh_counter(int8_t interface_id) 00729 { 00730 mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id); 00731 //Clean list and set function pointer call backs 00732 if (!mle_class_ptr) { 00733 return 0xffff; 00734 } 00735 00736 00737 return ns_list_count(&mle_class_ptr->mle_table); 00738 } 00739 00740 uint8_t *mle_general_write_source_address(uint8_t *ptr, protocol_interface_info_entry_t *cur) 00741 { 00742 if (cur->global_address_available) { 00743 uint16_t mac16 = mac_helper_mac16_address_get(cur); 00744 if (mac16 < 0xfffe) { 00745 ptr = mle_tlv_write_source_address(ptr, mac16); 00746 } 00747 } 00748 return ptr; 00749 } 00750 00751 uint8_t *mle_general_write_link_layer_framecounter(uint8_t *ptr, protocol_interface_info_entry_t *cur) 00752 { 00753 uint32_t temp_counter; 00754 mac_helper_link_frame_counter_read(cur->id, &temp_counter); 00755 return mle_tlv_write_link_layer_framecount(ptr, temp_counter); 00756 } 00757 00758 static void mle_event_handler(arm_event_s *event) 00759 { 00760 switch (event->event_type) { 00761 case ARM_MLE_INIT: 00762 tr_debug("MLE Tasklet Generated"); 00763 break; 00764 00765 case ARM_MLE_TTL_TIMER: 00766 //Do list in future for each of mle user 00767 //Set here mle class ttl update 00768 ns_list_foreach_safe(mle_table_class_t, mle_clas_entry, &mle_table_calss_list) { 00769 mle_class_table_ttl(1, mle_clas_entry); 00770 } 00771 00772 00773 break; 00774 } 00775 } 00776 00777 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) 00778 { 00779 mle_tlv_info_t mle_tlv_info; 00780 uint32_t frame_counter; 00781 if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_LL_FRAME_COUNTER, &mle_tlv_info) != 4) { 00782 if (cur->mac_parameters->SecurityEnabled) { 00783 return false; 00784 } else { 00785 frame_counter = 0; 00786 } 00787 } else { 00788 frame_counter = common_read_32_bit(mle_tlv_info.dataPtr); 00789 } 00790 00791 mac_helper_devicetable_set(entry_temp, cur, frame_counter, key_id); 00792 return true; 00793 } 00794 00795 void mle_entry_timeout_update(mle_neigh_table_entry_t *entry_temp, uint32_t timeout_tlv) 00796 { 00797 if (timeout_tlv > 86400) { 00798 timeout_tlv = 86400; 00799 } else if (timeout_tlv == 0) { 00800 timeout_tlv = 500; 00801 } 00802 timeout_tlv /= MLE_TIMER_TICKS_SECONDS; 00803 timeout_tlv++; 00804 entry_temp->timeout_rx = timeout_tlv; 00805 mle_entry_timeout_refresh(entry_temp); 00806 } 00807 00808 void mle_entry_timeout_refresh(mle_neigh_table_entry_t *entry_temp) 00809 { 00810 entry_temp->ttl = entry_temp->timeout_rx; 00811 entry_temp->last_contact_time = protocol_core_monotonic_time; 00812 entry_temp->medium_ttl_challenge = false; 00813 } 00814 00815 static void mle_refresh_entry(mle_neigh_table_entry_t *neig_info, bool dataPollConfirmation) 00816 { 00817 if (!neig_info) { 00818 return; 00819 } 00820 if (!neig_info->handshakeReady) { 00821 tr_debug("refresh:Link Handshake not ready yet"); 00822 return; 00823 } 00824 00825 neig_info->last_contact_time = protocol_core_monotonic_time; 00826 neig_info->medium_ttl_challenge = false; 00827 00828 if (dataPollConfirmation) { 00829 if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) { 00830 neig_info->ttl = neig_info->timeout_rx; 00831 } 00832 } else { 00833 neig_info->ttl = neig_info->timeout_rx; 00834 } 00835 } 00836 00837 mle_neigh_table_entry_t *mle_refresh_entry_timeout(int8_t interfaceId, const uint8_t *addressPtr, addrtype_t addressType, bool dataPollConfirmation) 00838 { 00839 mle_neigh_table_entry_t * neigh_info = mle_class_get_by_link_address(interfaceId, addressPtr, addressType); 00840 mle_refresh_entry(neigh_info, dataPollConfirmation); 00841 return neigh_info; 00842 } 00843 00844 #endif /* NO_MLE */
Generated on Tue Jul 12 2022 12:22:12 by
