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.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
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 13:03:04 by
