BA / Mbed OS BaBoRo1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mle.c Source File

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 */