Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_common.c Source File

thread_common.c

00001 /*
00002  * Copyright (c) 2014-2015, 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #include "nsconfig.h"
00030 #ifdef HAVE_THREAD
00031 #include <string.h>
00032 #include <ns_types.h>
00033 #include <nsdynmemLIB.h>
00034 #include "eventOS_event.h"
00035 #include "randLIB.h"
00036 #include "common_functions.h"
00037 
00038 #include "NWK_INTERFACE/Include/protocol.h"
00039 #include "net_thread_test.h"
00040 #include "libDHCPv6/libDHCPv6.h"
00041 #include "libDHCPv6/libDHCPv6_server.h"
00042 #include "ns_trace.h"
00043 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00044 #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
00045 #include "6LoWPAN/Thread/thread_common.h"
00046 #include "6LoWPAN/Thread/thread_beacon.h"
00047 #include "6LoWPAN/Thread/thread_leader_service.h"
00048 #include "6LoWPAN/Thread/thread_routing.h"
00049 #include "6LoWPAN/Thread/thread_dhcpv6_client.h"
00050 #include "6LoWPAN/Thread/thread_discovery.h"
00051 #include "6LoWPAN/Thread/thread_bootstrap.h"
00052 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00053 #include "6LoWPAN/Thread/thread_lowpower_private_api.h"
00054 #include "6LoWPAN/Thread/thread_extension.h"
00055 #include "6LoWPAN/Thread/thread_bbr_api_internal.h"
00056 #include "6LoWPAN/Thread/thread_border_router_api_internal.h"
00057 #include "6LoWPAN/Thread/thread_nd.h"
00058 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00059 #include "6LoWPAN/Thread/thread_joiner_application.h"
00060 #include "6LoWPAN/Thread/thread_management_internal.h"
00061 #include "6LoWPAN/Thread/thread_management_client.h"
00062 #include "6LoWPAN/Thread/thread_management_server.h"
00063 #include "6LoWPAN/Thread/thread_resolution_client.h"
00064 #include "6LoWPAN/Thread/thread_address_registration_client.h"
00065 #include "6LoWPAN/Thread/thread_resolution_client.h"
00066 #include <6LoWPAN/Thread/thread_extension_bootstrap.h>
00067 #include "MLE/mle.h"
00068 #include "Service_Libs/mle_service/mle_service_security.h"
00069 #include "Service_Libs/blacklist/blacklist.h"
00070 #include "6LoWPAN/Thread/thread_network_synch.h"
00071 #include "6LoWPAN/Thread/thread_config.h"
00072 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00073 #include "thread_meshcop_lib.h"
00074 #include "thread_management_if.h"
00075 #include "ipv6_stack/protocol_ipv6.h"
00076 #include "Common_Protocols/ipv6.h"
00077 #include "Common_Protocols/icmpv6.h"
00078 #include "MLE/mle.h"
00079 #include "MLE/mle_tlv.h"
00080 #include "Service_Libs/nd_proxy/nd_proxy.h"
00081 #include "Service_Libs/mle_service/mle_service_api.h"
00082 #include "6LoWPAN/MAC/mac_helper.h"
00083 #include "6LoWPAN/MAC/mac_pairwise_key.h"
00084 #include "6LoWPAN/MAC/mac_data_poll.h"
00085 #include "Service_Libs/etx/etx.h"
00086 #include "Core/include/address.h"
00087 #include "6LoWPAN/Thread/thread_nvm_store.h"
00088 
00089 #define TRACE_GROUP "thrd"
00090 
00091 #define ID_MASK_UPDATE_MIN (10 * 10) /* 1 minute */
00092 #define LEADER_DATA_UPDATE_MIN (10 * 10) /* 10 seconds */
00093 
00094 /* Parent priority bits in Connectivity TLV flags byte */
00095 #define CONNECTIVITY_PP_MASK     0xC0    // Parent priority
00096 #define CONNECTIVITY_PP_LOW      0xC0
00097 #define CONNECTIVITY_PP_MEDIUM   0x00
00098 #define CONNECTIVITY_PP_HIGH     0x40
00099 #define CONNECTIVITY_PP_INVALID  0x80
00100 
00101 uint8_t thread_version = THREAD_PROTOCOL_VERSION;
00102 
00103 thread_leader_data_t *thread_leader_data_generate(void);
00104 thread_parent_info_t *thread_parent_data_allocate(thread_info_t *info);
00105 static uint8_t * thread_joining_port_tlv_write(uint16_t port, uint8_t *ptr);
00106 static uint8_t * thread_commissioner_port_tlv_write(uint16_t port, uint8_t *ptr);
00107 static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, mle_neigh_table_entry_t *neighbor);
00108 static void thread_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason);
00109 
00110 /* Helper functions*/
00111 /* Ceil log2 function */
00112 uint16_t thread_log2_aprx(uint32_t n)
00113 {
00114     if (n == 0) {
00115         return 0;
00116     }
00117     uint16_t val = 0;
00118     --n;
00119     while (n > 0 && val < 255) {
00120         ++val;
00121         n >>= 1;
00122     }
00123     return val;
00124 }
00125 
00126 
00127 
00128 void thread_anycast_address_policy_update(const thread_info_t *thread_info, bool addPolicy)
00129 {
00130     uint8_t ipv6_address[16] = {0};
00131 
00132     thread_addr_write_mesh_local_16(ipv6_address, 0xfc00, thread_info);
00133 
00134     if (addPolicy) {
00135         tr_debug("Thread Add AnycastAddress Policy");
00136         addr_policy_table_add_entry(ipv6_address, 118, 20, 40);
00137     } else {
00138         addr_policy_table_delete_entry(ipv6_address, 118);
00139     }
00140 }
00141 
00142 /**
00143  * Thread key request for MLE Message
00144  *
00145  */
00146 uint8_t *thread_management_key_request_with_sequence(int8_t interface_id, uint8_t keyId, uint32_t keySequnce)
00147 {
00148     protocol_interface_info_entry_t *cur;
00149     uint8_t *keyPtr = NULL;
00150     link_configuration_s *linkConfiguration;
00151     linkConfiguration = thread_joiner_application_get_config(interface_id);
00152     if (!linkConfiguration) {
00153         return NULL;
00154     }
00155 
00156     cur = protocol_stack_interface_info_get_by_id(interface_id);
00157     if (cur && cur->thread_info) {
00158         if (cur->thread_info->masterSecretMaterial.valid_Info) {
00159             if (keySequnce == linkConfiguration->key_sequence) {
00160                 if (mle_service_security_default_key_id_get(interface_id) == keyId) {
00161                     keyPtr =  mle_service_security_default_key_get(interface_id);
00162                 }
00163             } else if (keySequnce == (linkConfiguration->key_sequence + 1)) {
00164                 if (mle_service_security_next_key_id_get(interface_id) == keyId) {
00165                     keyPtr =  mle_service_security_next_key_get(interface_id);
00166                 }
00167             }
00168 
00169             if (!keyPtr) {
00170                 tr_debug("Gen temporary key id %"PRIu8" seq %"PRIu32, keyId, keySequnce);
00171                 thread_key_get(linkConfiguration->master_key, cur->thread_info->masterSecretMaterial.historyKey, keySequnce);
00172                 cur->thread_info->masterSecretMaterial.historyKeyId = keyId;
00173                 cur->thread_info->masterSecretMaterial.historyKeyValid = false;
00174                 keyPtr = cur->thread_info->masterSecretMaterial.historyKey;
00175             }
00176         }
00177     }
00178     return keyPtr;
00179 }
00180 uint8_t * thread_mle_service_security_notify_cb(int8_t interface_id, mle_security_event_t event, uint8_t keyId)
00181 {
00182     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
00183     if (!interface) {
00184         return NULL;
00185     }
00186     switch (event) {
00187         case MLE_SEC_MAX_FRAME_COUNTER_REACHED :
00188 
00189             break;
00190         case MLE_SEC_KEY_UPDATE_NOTIFY :
00191 
00192             mac_helper_security_key_swap_next_to_default(interface);
00193 
00194             if (thread_info(interface)) {
00195                 thread_security_update_from_mac(interface);
00196             }
00197             break;
00198 
00199         case MLE_SEC_UNKNOWN_KEY :
00200             return thread_management_key_request(interface_id,keyId);
00201     }
00202     return NULL;
00203 }
00204 int8_t thread_bootstrap_up(protocol_interface_info_entry_t *cur)
00205 {
00206     int8_t ret_val = -1;
00207 
00208     if (!cur) {
00209         return -1;
00210     }
00211 
00212     if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) {
00213         tr_debug("Interface not yet fully configured");
00214         return -5;
00215     }
00216 
00217     protocol_6lowpan_register_handlers(cur);
00218     addr_interface_set_ll64(cur, NULL);
00219     thread_interface_up(cur);
00220     ret_val = nwk_6lowpan_up(cur);
00221 
00222     cur->nwk_nd_re_scan_count = 0;
00223 
00224     return ret_val;
00225 }
00226 
00227 int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur)
00228 {
00229     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
00230         return -1;
00231     }
00232 
00233     tr_debug("SET thread Idle");
00234     //stop polling
00235     mac_data_poll_disable(cur);
00236     //Clean routers from mle table
00237     thread_clean_all_routers_from_neighbor_list(cur->id);
00238     // store frame counters
00239     if (cur->thread_info) {
00240         thread_nvm_fast_data_t fast_data;
00241         memset(&fast_data,0,sizeof(thread_nvm_fast_data_t));
00242         link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00243         if(linkConfiguration) {
00244             fast_data.seq_counter = linkConfiguration->key_sequence;
00245         }
00246         mac_helper_link_frame_counter_read(cur->id, &fast_data.mac_frame_counter);
00247         fast_data.mle_frame_counter=mle_service_security_get_frame_counter(cur->id);
00248         thread_nvm_store_fast_data_write(&fast_data);
00249         thread_joiner_application_configuration_nvm_save(cur->id);
00250         mac_pairwise_key_flush_list(cur->id);
00251         thread_discovery_reset(cur->id);
00252         thread_bootstrap_stop(cur);
00253         mle_service_interface_unregister(cur->id);
00254         thread_management_server_delete(cur->id);
00255         thread_joiner_application_deinit(cur->id);
00256         thread_management_client_delete(cur->id);
00257         //free network Data
00258         thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage);
00259         //free local also here
00260         thread_network_local_data_free_and_clean(&cur->thread_info->localServerDataBase, cur->id);
00261         thread_network_data_base_init(&cur->thread_info->networkDataStorage);
00262         cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
00263     }
00264 
00265     if (nd_proxy_downstream_interface_unregister(cur->id) == -1) {
00266         tr_warn("nd proxy unregister failed");
00267     }
00268     return nwk_6lowpan_down(cur);
00269 }
00270 
00271 
00272 bool thread_addr_is_mesh_local(const uint8_t *addr, const protocol_interface_info_entry_t *cur)
00273 {
00274     thread_info_t *info = cur ? cur->thread_info : NULL;
00275     if (info && info->threadPrivatePrefixInfo.ulaValid) {
00276         return memcmp(info->threadPrivatePrefixInfo.ulaPrefix, addr, 8) == 0;
00277     }
00278     return false;
00279 }
00280 
00281 bool thread_on_mesh_route_possible_add(thread_attach_device_mode_e threadMode)
00282 {
00283     bool addRoute;
00284     if ((threadMode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) || (threadMode == THREAD_DEVICE_MODE_END_DEVICE)) {
00285         addRoute = false;
00286     } else {
00287         addRoute = true;
00288     }
00289 
00290     return addRoute;
00291 }
00292 
00293 bool thread_addr_is_mesh_local_16(const uint8_t *addr, const protocol_interface_info_entry_t *cur)
00294 {
00295     return thread_addr_is_mesh_local(addr, cur) && memcmp(addr + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0;
00296 }
00297 
00298 uint8_t *thread_addr_write_mesh_local_16(uint8_t ip_addr_out[16], uint16_t addr16, const thread_info_t *info)
00299 {
00300     if (!info->threadPrivatePrefixInfo.ulaValid) {
00301         return NULL;
00302     }
00303     memcpy(ip_addr_out + 8, ADDR_SHORT_ADR_SUFFIC, 6);
00304     common_write_16_bit(addr16, ip_addr_out + 14);
00305     return memcpy(ip_addr_out, info->threadPrivatePrefixInfo.ulaPrefix, 8);
00306 }
00307 
00308 bool thread_leader_data_parse(uint8_t *ptr, uint16_t dataLength, thread_leader_data_t *leaderDataBuf)
00309 {
00310     mle_tlv_info_t mle_tlv_info;
00311     if (mle_tlv_option_discover(ptr, dataLength, MLE_TYPE_LEADER_DATA, &mle_tlv_info) == 8) {
00312         uint8_t *t_ptr = mle_tlv_info.dataPtr;
00313         leaderDataBuf->partitionId = common_read_32_bit(t_ptr);
00314         t_ptr += 4;
00315         leaderDataBuf->weighting = *t_ptr++;
00316         leaderDataBuf->dataVersion = *t_ptr++;
00317         leaderDataBuf->stableDataVersion = *t_ptr++;
00318         leaderDataBuf->leaderRouterId = *t_ptr;
00319         return true;
00320     }
00321     return false;
00322 }
00323 
00324 bool thread_connectivity_tlv_parse(uint8_t *ptr, uint16_t dataLength, thread_connectivity_t *connectivityTlv)
00325 {
00326     mle_tlv_info_t mle_tlv_info;
00327     int tlv_length = mle_tlv_option_discover(ptr, dataLength, MLE_TYPE_CONNECTIVITY, &mle_tlv_info);
00328     if (tlv_length >= 7) {
00329         uint8_t *t_ptr = mle_tlv_info.dataPtr;
00330         uint8_t flags = *t_ptr++;
00331         switch (flags & CONNECTIVITY_PP_MASK)  {
00332             case CONNECTIVITY_PP_LOW:
00333                 connectivityTlv->parentPriority = THREAD_CONNECTIVITY_TLV_PARENT_PRIORITY_LOW;
00334                 break;
00335             case CONNECTIVITY_PP_HIGH:
00336                 connectivityTlv->parentPriority = THREAD_CONNECTIVITY_TLV_PARENT_PRIORITY_HIGH;
00337                 break;
00338             case CONNECTIVITY_PP_MEDIUM:
00339             default:
00340                 connectivityTlv->parentPriority = THREAD_CONNECTIVITY_TLV_PARENT_PRIORITY_MEDIUM;
00341                 break;
00342         }
00343         connectivityTlv->linkQuality3 = *t_ptr++;
00344         connectivityTlv->linkQuality2 = *t_ptr++;
00345         connectivityTlv->linkQuality1 = *t_ptr++;
00346         connectivityTlv->leaderCost = *t_ptr++;
00347         connectivityTlv->idSequence = *t_ptr++;
00348         connectivityTlv->activeRouters = *t_ptr++;
00349         if (tlv_length >= 10) {
00350             connectivityTlv->SEDBufferSize = common_read_16_bit(t_ptr);
00351             t_ptr += 2;
00352             connectivityTlv->SEDDatagramCount = *t_ptr++;
00353         } else {
00354             connectivityTlv->SEDBufferSize = THREAD_SED_BUFFER_MIN_SIZE;
00355             connectivityTlv->SEDDatagramCount = THREAD_SED_DATAGRAM_MIN_COUNT;
00356         }
00357         return true;
00358     }
00359     return false;
00360 }
00361 
00362 void thread_calculate_key_guard_timer(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, bool is_init)
00363 {
00364     uint32_t key_rotation = linkConfiguration ? linkConfiguration->key_rotation : 0;
00365 
00366     if (is_init && key_rotation < 3600) {
00367         tr_warn("Attempted to set key rotation time smaller than 1 hour.");
00368         key_rotation = 3600;
00369     }
00370 
00371     cur->thread_info->masterSecretMaterial.keyRotation = key_rotation;
00372     cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = is_init ? 0 : (key_rotation * 0.93);
00373 }
00374 
00375 thread_leader_data_t *thread_leader_data_generate(void)
00376 {
00377     thread_leader_data_t *leader_data;
00378     leader_data = ns_dyn_mem_alloc(sizeof(thread_leader_data_t));
00379     return leader_data;
00380 }
00381 
00382 thread_leader_data_t *thread_leader_data_get(thread_info_t *info)
00383 {
00384     if (info->thread_leader_data == NULL) {
00385         info->thread_leader_data = thread_leader_data_generate();
00386     }
00387     return info->thread_leader_data;
00388 }
00389 
00390 thread_parent_info_t *thread_parent_data_allocate(thread_info_t *info)
00391 {
00392     thread_parent_info_t *parent_data;
00393     if (!info->thread_endnode_parent) {
00394         info->thread_endnode_parent = ns_dyn_mem_alloc(sizeof(thread_parent_info_t));
00395     }
00396 
00397     parent_data = info->thread_endnode_parent;
00398     if (parent_data) {
00399         memset(parent_data,0,sizeof(thread_parent_info_t));
00400     }
00401     return parent_data;
00402 }
00403 
00404 void thread_dynamic_reed_initialize(thread_router_select_t *routerSelect)
00405 {
00406     routerSelect->jitterTimerActive = false;
00407     routerSelect->possibleDefaultParent = 0xff;
00408     routerSelect->routerDowngradeThresHold = ROUTER_DOWNGRADE_THRESHOLD;
00409     routerSelect->routerUpgradeThresHold = ROUTER_UPGRADE_THRESHOLD;
00410     routerSelect->reedAdvertisementInterval = REED_ADVERTISEMENT_INTERVAL;
00411     routerSelect->reedAdvertisementJitterInterval = REED_ADVERTISEMENT_MAX_JITTER;
00412     routerSelect->reedAdvertisementTimeout = NULL;
00413 }
00414 
00415 bool thread_leader_commissioner_create(thread_info_t *thread_info)
00416 {
00417     thread_info->registered_commissioner.commissioner_valid = false;
00418     thread_info->registered_commissioner.session_id = randLIB_get_16bit();
00419     ns_dyn_mem_free(thread_info->registered_commissioner.commissioner_id_ptr);
00420     thread_info->registered_commissioner.commissioner_id_ptr = NULL;
00421     eventOS_timeout_cancel(thread_info->registered_commissioner.commissioner_timeout);
00422     thread_info->registered_commissioner.commissioner_timeout = NULL;
00423     thread_info->registered_commissioner.commissioner_registration = THREAD_COMMISSIONER_NOT_REGISTERED;
00424     thread_info->registered_commissioner.steering_data_len = 0;
00425     return true;
00426 }
00427 
00428 
00429 void thread_data_base_init(thread_info_t *thread_info, int8_t interfaceId)
00430 {
00431     if (!thread_info) {
00432         return;
00433     }
00434     (void) interfaceId;
00435 
00436     thread_leader_commissioner_create(thread_info);
00437     thread_info->rfc6775 = false;
00438     thread_info->threadPrivatePrefixInfo.ulaValid = false;
00439     thread_info->routerIdReqCoapID = 0;
00440     thread_info->networkDataRequested = false;
00441     thread_info->proactive_an_timer = 0;
00442 
00443     thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
00444     thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
00445     thread_routing_reset(&thread_info->routing);
00446 }
00447 
00448 int thread_info_allocate_and_init(protocol_interface_info_entry_t *cur)
00449 {
00450     if (thread_bootstrap_tasklet_init(cur) != 0) {
00451         return -1;
00452     }
00453 
00454     if (!cur->thread_info) {
00455         cur->thread_info = ns_dyn_mem_alloc(sizeof(thread_info_t));
00456         if (!cur->thread_info) {
00457             return -1;
00458         }
00459         memset(cur->thread_info, 0, sizeof(thread_info_t));
00460 
00461         cur->thread_info->interface_id = cur->id;
00462         cur->thread_info->testMaxActiveRouterIdLimit = 32;
00463         cur->thread_info->version = thread_version; // Default implementation version
00464         cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
00465         cur->thread_info->childUpdateReqTimer = -1;
00466 
00467         thread_routing_init(&cur->thread_info->routing);
00468         thread_network_local_server_data_base_init(&cur->thread_info->localServerDataBase);
00469         memset(&cur->thread_info->registered_commissioner,0,sizeof(thread_commissioner_t));
00470         thread_dynamic_reed_initialize(&cur->thread_info->routerSelectParameters);
00471         thread_extension_allocate(cur);
00472         ns_list_init(&cur->thread_info->childIdReqPending);
00473         ns_list_init(&cur->thread_info->child_mcast_list);
00474         if (!thread_leader_data_get(cur->thread_info)){
00475             return -1;
00476         }
00477     } else {
00478         thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage);
00479         thread_network_local_data_free_and_clean(&cur->thread_info->localServerDataBase, cur->id);
00480         thread_leader_service_leader_data_free(cur->thread_info);
00481         thread_data_base_init(cur->thread_info, cur->id);
00482         thread_dynamic_reed_initialize(&cur->thread_info->routerSelectParameters);
00483     }
00484     thread_network_data_base_init(&cur->thread_info->networkDataStorage);
00485     //SET Thread Bootstrap Up & Down
00486     cur->if_up = thread_bootstrap_up;
00487     cur->if_down = thread_bootstrap_down;
00488     cur->mac_parameters->beacon_ind = thread_beacon_indication;
00489     cur->mac_parameters->mac_in_direct_entry_timeout = 30000;
00490     cur->thread_info->routerShortAddress = 0xfffe; //Default value Not Router
00491     //memset(cur->thread_info->lastValidRouteMask, 0, (N_THREAD_ROUTERS+7)/8);
00492     cur->thread_info->releaseRouterId = false;
00493 
00494     // Test data
00495     cur->thread_info->testRandomPartitionId = 0;
00496 
00497     return 0;
00498 }
00499 
00500 void thread_info_deallocate(protocol_interface_info_entry_t *cur)
00501 {
00502     if (cur->thread_info) {
00503         //Release DHCPv6 leasequery Service
00504         thread_nd_service_delete(cur->id);
00505         thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage);
00506         thread_network_local_data_free_and_clean(&cur->thread_info->localServerDataBase, cur->id);
00507         thread_leader_service_leader_data_free(cur->thread_info);
00508         thread_data_base_init(cur->thread_info, cur->id);
00509         thread_routing_free(&cur->thread_info->routing);
00510         thread_extension_free(cur);
00511         thread_extension_bootstrap_free(cur);
00512         if (cur->thread_info->thread_endnode_parent) {
00513             ns_dyn_mem_free(cur->thread_info->thread_endnode_parent);
00514             cur->thread_info->thread_endnode_parent = NULL;
00515         }
00516         ns_dyn_mem_free(cur->thread_info);
00517         cur->thread_info = 0;
00518         cur->mesh_callbacks = NULL;
00519     }
00520 }
00521 
00522 thread_leader_info_t *thread_allocate_and_init_leader_private_data(void)
00523 {
00524     thread_leader_info_t *leader_info = ns_dyn_mem_alloc(sizeof(thread_leader_info_t));
00525     if (leader_info) {
00526         leader_info->leader_id_seq_timer = ID_SEQUENCE_PERIOD;
00527     }
00528     return leader_info;
00529 }
00530 
00531 thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality)
00532 {
00533     switch (quality) {
00534         case QUALITY_20dB:
00535             return 1;
00536         case QUALITY_10dB:
00537             return 2;
00538         case QUALITY_2dB:
00539             return 4;
00540         default:
00541         case QUALITY_BAD:
00542             return THREAD_COST_INFINITE;
00543     }
00544 }
00545 
00546 thread_route_cost_t thread_link_cost_sum(thread_route_cost_t a, thread_route_cost_t b)
00547 {
00548     if (a == THREAD_COST_INFINITE || b == THREAD_COST_INFINITE) {
00549         return THREAD_COST_INFINITE;
00550     }
00551 
00552     if (a + b > THREAD_MAX_ROUTE_COST) {
00553         return THREAD_COST_INFINITE;
00554     }
00555 
00556     return a + b;
00557 }
00558 
00559 thread_link_quality_e thread_link_margin_to_quality(thread_link_margin_t margin)
00560 {
00561     if (margin > (20 << THREAD_LINK_MARGIN_SCALING)) {
00562         return QUALITY_20dB;
00563     } else if (margin > (10 << THREAD_LINK_MARGIN_SCALING)) {
00564         return QUALITY_10dB;
00565     } else if (margin > (2 << THREAD_LINK_MARGIN_SCALING)) {
00566         return QUALITY_2dB;
00567     } else {
00568         return QUALITY_BAD;
00569     }
00570 }
00571 
00572 uint_fast8_t thread_sum_rx_path_cost_and_link_cost(uint8_t inMargim, uint8_t outMargin, uint8_t pathCost)
00573 {
00574     thread_route_cost_t linkCost, rxCost;
00575     if (inMargim < outMargin) {
00576         linkCost = thread_link_quality_to_cost(thread_link_margin_to_quality(inMargim));
00577     } else {
00578         linkCost = thread_link_quality_to_cost(thread_link_margin_to_quality(outMargin));
00579     }
00580     rxCost = pathCost;
00581 
00582     return thread_link_cost_sum(linkCost, rxCost);
00583 }
00584 
00585 thread_registered_mcast_addr_t *thread_registered_mcast_addr_entry_allocate(void)
00586 {
00587     thread_registered_mcast_addr_t *addr = ns_dyn_mem_alloc(sizeof(thread_registered_mcast_addr_t));
00588 
00589     if (addr) {
00590         memset(addr, 0, sizeof(thread_registered_mcast_addr_t));
00591         ns_list_init(&addr->children);
00592     }
00593 
00594     return addr;
00595 }
00596 
00597 thread_mcast_child_t *thread_mcast_addr_child_entry_allocate(void)
00598 {
00599     thread_mcast_child_t *child = ns_dyn_mem_alloc(sizeof(thread_mcast_child_t));
00600 
00601     if (child) {
00602         memset(child, 0, sizeof(thread_mcast_child_t));
00603     }
00604 
00605     return child;
00606 }
00607 
00608 void thread_registered_mcast_addr_entry_clean(protocol_interface_info_entry_t *cur)
00609 {
00610     ns_list_foreach_safe(thread_registered_mcast_addr_t, entry, &cur->thread_info->child_mcast_list) {
00611         ns_list_remove(&cur->thread_info->child_mcast_list, entry);
00612 
00613         ns_list_foreach_safe(thread_mcast_child_t, child, &entry->children) {
00614             ns_list_remove(&entry->children, child);
00615             ns_dyn_mem_free(child);
00616         }
00617 
00618         ns_dyn_mem_free(entry);
00619     }
00620 }
00621 
00622 void thread_child_mcast_entries_remove(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
00623 {
00624     ns_list_foreach_safe(thread_registered_mcast_addr_t, entry, &cur->thread_info->child_mcast_list) {
00625         ns_list_foreach_safe(thread_mcast_child_t, child, &entry->children) {
00626             if (memcmp(child->mac64, mac64, 8) == 0) {
00627                 ns_list_remove(&entry->children, child);
00628                 ns_dyn_mem_free(child);
00629             }
00630         }
00631     }
00632 
00633     // Remove empty multicast address entries
00634     ns_list_foreach_safe(thread_registered_mcast_addr_t, entry, &cur->thread_info->child_mcast_list) {
00635         if (ns_list_is_empty(&entry->children)) {
00636             ns_list_remove(&cur->thread_info->child_mcast_list, entry);
00637             ns_dyn_mem_free(entry);
00638         }
00639     }
00640 }
00641 
00642 thread_registered_mcast_addr_t *thread_registered_mcast_addr_entry_find(protocol_interface_info_entry_t *cur, const uint8_t *mcast_addr)
00643 {
00644     ns_list_foreach(thread_registered_mcast_addr_t, entry, &cur->thread_info->child_mcast_list) {
00645         if (memcmp(entry->address, mcast_addr, 16) == 0) {
00646             return entry;
00647         }
00648     }
00649 
00650     return NULL;
00651 }
00652 
00653 thread_mcast_child_t *thread_child_mcast_entry_find(thread_mcast_children_list_t *children, const uint8_t *mac64)
00654 {
00655     ns_list_foreach(thread_mcast_child_t, entry, children) {
00656         if (memcmp(entry->mac64, mac64, 8) == 0) {
00657             return entry;
00658         }
00659     }
00660 
00661     return NULL;
00662 }
00663 
00664 thread_mcast_child_t *thread_child_mcast_entry_get(protocol_interface_info_entry_t *cur, const uint8_t *mcast_addr, const uint8_t *mac64)
00665 {
00666     mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, mac64, ADDR_802_15_4_LONG );
00667 
00668     if (!mle_entry) {
00669         tr_error("No MLE entry.");
00670         return NULL;
00671     }
00672 
00673     if (mle_entry->mode & MLE_RX_ON_IDLE) {
00674         /* Not a sleepy child */
00675         tr_debug("Not a sleepy child");
00676         return NULL;
00677     }
00678 
00679     thread_registered_mcast_addr_t *addr = thread_registered_mcast_addr_entry_find(cur, mcast_addr);
00680 
00681     if (!addr) {
00682         addr = thread_registered_mcast_addr_entry_allocate();
00683 
00684         if (addr) {
00685             memcpy(addr->address, mcast_addr, 16);
00686             ns_list_add_to_end(&cur->thread_info->child_mcast_list, addr);
00687         } else {
00688             return NULL;
00689         }
00690     }
00691 
00692     thread_mcast_child_t *child = thread_child_mcast_entry_find(&addr->children, mac64);
00693 
00694     if (!child) {
00695         child = thread_mcast_addr_child_entry_allocate();
00696 
00697         if (child) {
00698             memcpy(child->mac64, mac64, 8);
00699             ns_list_add_to_end(&addr->children, child);
00700         } else {
00701             return NULL;
00702         }
00703     }
00704 
00705     return child;
00706 }
00707 
00708 void thread_child_id_request_info_init(thread_pending_child_id_req_t *child_info)
00709 {
00710     if (child_info) {
00711         child_info->routeReq = false;
00712         child_info->networkDataReq = false;
00713         child_info->shortAddressReq = false;
00714     }
00715 }
00716 
00717 thread_pending_child_id_req_t *thread_child_id_request_allocate(void)
00718 {
00719     thread_pending_child_id_req_t *req = ns_dyn_mem_alloc(sizeof(thread_pending_child_id_req_t));
00720     thread_child_id_request_info_init(req);
00721     return req;
00722 }
00723 
00724 void thread_child_id_request_entry_clean(protocol_interface_info_entry_t *cur)
00725 {
00726     ns_list_foreach_safe(thread_pending_child_id_req_t, entry, &cur->thread_info->childIdReqPending) {
00727         ns_list_remove(&cur->thread_info->childIdReqPending, entry);
00728         ns_dyn_mem_free(entry);
00729     }
00730 }
00731 
00732 thread_pending_child_id_req_t *thread_child_id_request_entry_get(protocol_interface_info_entry_t *cur, uint8_t *euid64)
00733 {
00734     thread_pending_child_id_req_t *req;
00735     ns_list_foreach(thread_pending_child_id_req_t, entry, &cur->thread_info->childIdReqPending) {
00736         if (memcmp(entry->euid64, euid64, 8) == 0) {
00737             thread_child_id_request_info_init(entry);
00738             return entry;
00739         }
00740     }
00741     req = thread_child_id_request_allocate();
00742     if (req) {
00743         tr_debug("Add to list ID REQ");
00744         memcpy(req->euid64, euid64, 8);
00745         ns_list_add_to_end(&cur->thread_info->childIdReqPending, req);
00746     }
00747     return req;
00748 }
00749 
00750 thread_pending_child_id_req_t *thread_child_id_request_entry_get_from_the_list(protocol_interface_info_entry_t *cur)
00751 {
00752     thread_pending_child_id_req_t *req;
00753 
00754     req = ns_list_get_first(&cur->thread_info->childIdReqPending);
00755     if (req) {
00756         ns_list_remove(&cur->thread_info->childIdReqPending, req);
00757     }
00758 
00759     return req;
00760 
00761 }
00762 
00763 void thread_child_id_request_entry_remove(protocol_interface_info_entry_t *cur, thread_pending_child_id_req_t *entry)
00764 {
00765     if (entry) {
00766         ns_list_remove(&cur->thread_info->childIdReqPending, entry);
00767         ns_dyn_mem_free(entry);
00768     }
00769 }
00770 
00771 int thread_init(protocol_interface_info_entry_t *cur)
00772 {
00773     if (!cur->thread_info) {
00774         return -1;
00775     }
00776 
00777     if (thread_mle_class_init(cur->id) != 0) {
00778         return -1;
00779     }
00780 
00781     // set mle security - first allocate instance and then set security
00782     mle_service_security_instance_allocate(cur->id);
00783     if (mle_service_security_init(cur->id, 5,
00784             0,
00785             thread_management_key_request_with_sequence,
00786             thread_mle_service_security_notify_cb) != 0) {
00787         tr_error("Mle Service security init Fail");
00788         return -1;
00789     }
00790 
00791     mle_class_router_challenge(cur->id, NULL);
00792 
00793     if (etx_accum_failures_callback_register(cur->nwk_id, cur->id, 1, thread_tx_failure_handler) != 1) {
00794         return -1;
00795     }
00796 
00797     addr_notification_register(thread_address_notification_cb);
00798 
00799     thread_leader_service_leader_data_free(cur->thread_info);
00800     thread_data_base_init(cur->thread_info, cur->id);
00801     mac_helper_pib_boolean_set(cur,macThreadForceLongAddressForBeacon , true);
00802     mac_helper_mac16_address_set(cur, 0xffff);
00803     mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
00804     return 0;
00805 }
00806 
00807 int thread_attach_ready(protocol_interface_info_entry_t *cur)
00808 {
00809     if (!cur->thread_info) {
00810         return -1;
00811     }
00812 
00813     switch (cur->thread_info->thread_attached_state) {
00814         case THREAD_STATE_CONNECTED:
00815         case THREAD_STATE_CONNECTED_ROUTER:
00816             return 0;
00817             break;
00818         default:
00819             break;
00820     }
00821 
00822     return -1;
00823 }
00824 
00825 bool thread_attach_active_router(protocol_interface_info_entry_t *cur)
00826 {
00827     if(cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
00828         return true;
00829     }
00830 
00831     return false;
00832 }
00833 
00834 bool thread_scan_mask_validation(protocol_interface_info_entry_t *cur, uint8_t mask)
00835 {
00836     uint8_t maskCompare = 0;
00837 
00838     if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) {
00839         return false;
00840     }
00841 
00842     switch (cur->thread_info->thread_attached_state) {
00843         case THREAD_STATE_CONNECTED_ROUTER:
00844             maskCompare  = 0x80;
00845             break;
00846         case THREAD_STATE_CONNECTED:
00847             maskCompare = 0x40;
00848             break;
00849         default:
00850             maskCompare = 0;
00851             break;
00852     }
00853     return (mask & maskCompare);
00854 }
00855 
00856 int thread_route_ready_to_leader(protocol_interface_info_entry_t *cur)
00857 {
00858     int retVal = -1;
00859     switch (cur->thread_info->thread_attached_state) {
00860         case THREAD_STATE_CONNECTED_ROUTER:
00861             if (cur->thread_info->leader_private_data) {
00862                 //We are the leader
00863                 retVal = 0;
00864             } else if (thread_routing_cost_get_by_router_id(&cur->thread_info->routing, cur->thread_info->thread_leader_data->leaderRouterId) != 0) {
00865                 retVal = 0;
00866             }
00867             break;
00868         case THREAD_STATE_CONNECTED:
00869             if (cur->thread_info->thread_endnode_parent) {
00870                 retVal = 0;
00871             }
00872             break;
00873         default:
00874             break;
00875     }
00876     return retVal;
00877 }
00878 static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur, uint16_t seconds)
00879 {
00880     if (cur->thread_info->childUpdateReqTimer == -1) {
00881         return;
00882     }
00883 
00884     if (cur->thread_info->childUpdateReqTimer > seconds) {
00885         cur->thread_info->childUpdateReqTimer -= seconds;
00886     } else {
00887         cur->thread_info->childUpdateReqTimer = 0;
00888     }
00889 
00890     if (cur->thread_info->childUpdateReqTimer == 0) {
00891         thread_bootstrap_child_update_trig(cur);
00892         cur->thread_info->childUpdateReqTimer = -1; // disable
00893     }
00894 }
00895 
00896 static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16_t seconds)
00897 {
00898     if (cur->thread_info->masterSecretMaterial.keySwitchGuardTimer > seconds) {
00899         cur->thread_info->masterSecretMaterial.keySwitchGuardTimer -= seconds;
00900     } else {
00901         cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = 0;
00902     }
00903 
00904     if (cur->thread_info->masterSecretMaterial.keyRotation > seconds) {
00905         cur->thread_info->masterSecretMaterial.keyRotation -= seconds;
00906     } else {
00907         cur->thread_info->masterSecretMaterial.keyRotation = 0;
00908     }
00909 
00910     if (cur->thread_info->masterSecretMaterial.keyRotation == 0) {
00911         link_configuration_s *linkConfiguration;
00912         linkConfiguration = thread_joiner_application_get_config(cur->id);
00913 
00914         if (!linkConfiguration) {
00915             return;
00916         }
00917 
00918         tr_debug("thrKeyRotation == 0: sync key material by %"PRIu32, linkConfiguration->key_sequence + 1);
00919         thread_management_key_sets_calc(cur, linkConfiguration, linkConfiguration->key_sequence + 1);
00920         thread_calculate_key_guard_timer(cur, linkConfiguration, false);
00921     }
00922 }
00923 
00924 void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
00925 {
00926     uint8_t leader_address[16];
00927     uint8_t commissioner_address[16];
00928     uint16_t commissioner_port;
00929     thread_info_t *thread_info = cur->thread_info;
00930 
00931     if (!thread_info) {
00932         return;
00933     }
00934 
00935     blacklist_ttl_update(ticks);
00936 
00937     // if we have pending configurations timer is made for it.
00938     thread_joiner_application_seconds_timer(cur->id, ticks);
00939     thread_resolution_client_timer(cur->id, ticks);
00940     thread_key_switch_timer(cur, ticks);
00941     thread_child_update_req_timer(cur, ticks);
00942 
00943     if (!thread_bootstrap_should_register_address(cur)) {
00944         /* Only FTD refreshes the address registration timer */
00945         thread_address_registration_timer(cur, ticks);
00946     }
00947 
00948     if (thread_attach_ready(cur) != 0) {
00949         return;
00950     }
00951     // Store all Dynamic information periodically. Now saved every 1s
00952     thread_bootstrap_dynamic_configuration_save(cur);
00953 
00954     // TODO should this be somewhere else? in joiner application?
00955     if (thread_joiner_application_next_active_config_exists(cur->id)) {
00956         thread_management_get_leader_address(cur->id, leader_address);
00957         thread_management_client_active_set(cur->id, leader_address);
00958         thread_joiner_application_next_active_config_delete(cur->id);
00959     }
00960 
00961     if (thread_joiner_application_next_pending_config_exists(cur->id)) {
00962         thread_management_get_leader_address(cur->id, leader_address);
00963         thread_management_client_pending_set(cur->id, leader_address );
00964         thread_joiner_application_next_pending_config_delete(cur->id);
00965     }
00966 
00967     // Check if we need to make application provisioning
00968     if (PROVISIONING_STATUS_NOT_DONE == thread_joiner_application_provisioning_get(cur->id) &&
00969         thread_management_get_commissioner_address(cur->id, commissioner_address, &commissioner_port) == 0) {
00970         // Provisioning not done and commissioner is present
00971         thread_management_client_provision_request(cur->id,  commissioner_address, commissioner_port);
00972     }
00973 
00974 
00975     // add more checks here when to become router
00976     // If we are doing attach to new partition, do not upgrade
00977     if(cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
00978         return;
00979     }
00980 
00981     thread_router_bootstrap_timer(cur, ticks);
00982     thread_border_router_seconds_timer(cur->id, ticks);
00983     thread_bbr_seconds_timer(cur->id, ticks);
00984     thread_lowpower_timer(cur, ticks);
00985     thread_nvm_store_seconds_timer(ticks);
00986 
00987     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
00988         nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
00989     }
00990 }
00991 
00992 void thread_network_data_request_send(protocol_interface_info_entry_t *cur, uint8_t *requestDstAddress, bool delaydTrig)
00993 {
00994     thread_info_t *thread_info = cur->thread_info;
00995     uint8_t req_tlv = MLE_TYPE_NETWORK_DATA;
00996 
00997     if (!cur->thread_info) {
00998         return;
00999     }
01000 
01001     tr_debug("Send MLE network data request");
01002 
01003     if(cur->thread_info->networkDataRequested){
01004         tr_debug("Pending data request found");
01005         return;
01006     }
01007 
01008     cur->thread_info->networkDataRequested = true;
01009 
01010     thread_tlv_request(thread_info->interface_id, requestDstAddress,delaydTrig, &req_tlv, 1);
01011 }
01012 
01013 void thread_timer(protocol_interface_info_entry_t *cur, uint8_t ticks)
01014 {
01015     thread_info_t *thread_info = cur->thread_info;
01016     if (!thread_info) {
01017         return;
01018     }
01019 
01020     if (thread_i_am_router(cur)) {
01021 
01022         if (thread_routing_timer(thread_info, ticks)) {
01023             thread_router_bootstrap_mle_advertise(cur);
01024         }
01025 
01026     } else {
01027 
01028     }
01029 }
01030 
01031 /* This test is used to indicate that we're following the Thread 1.0 oddities
01032  * arising from not having LL16 addresses on the mesh. For example, LL16
01033  * addresses go through the MAC and only one radio hop, and UL16/GP16 addresses
01034  * have special semantics on the PAN.
01035  */
01036 bool thread_insist_that_mesh_isnt_a_link(const protocol_interface_info_entry_t *cur)
01037 {
01038     return cur->thread_info && !cur->thread_info->rfc6775;
01039 }
01040 
01041 int8_t thread_beacon_create_payload(struct protocol_interface_info_entry *cur)
01042 {
01043     uint8_t *ptr;
01044     uint8_t payload_len;
01045     link_configuration_s *leader_link_setup;
01046     thread_management_server_data_t server_data;
01047 
01048     leader_link_setup = thread_joiner_application_get_config(cur->id);
01049 
01050     if (!leader_link_setup) {
01051         return -1;
01052     }
01053 
01054     if(!(leader_link_setup->securityPolicy & SECURITY_POLICY_BEACON_PAYLOAD_ENABLED)){
01055         mac_helper_beacon_payload_reallocate(cur, 0);
01056         return mac_helper_beacon_payload_register(cur);
01057     }
01058     if (thread_management_server_commisoner_data_get(cur->id, &server_data) != 0) {
01059         return mac_helper_beacon_payload_register(cur);
01060     }
01061 
01062     payload_len = 2/*header*/ + 16/*Network id*/ + 8/*extented PANID*/;
01063 
01064     if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len) {
01065         payload_len += cur->thread_info->registered_commissioner.steering_data_len + 2;
01066     }
01067 
01068     if (server_data.joiner_router_enabled) {
01069         payload_len +=  4/*Joiner UDP port*/;
01070     }
01071     if((leader_link_setup->securityPolicy & SECURITY_POLICY_NATIVE_COMMISSIONING_ALLOWED)){
01072         payload_len +=  4/*Commissioner UDP port*/;
01073     }
01074 
01075     ptr = mac_helper_beacon_payload_reallocate(cur, payload_len);
01076     if (!ptr) {
01077         return -1;
01078     }
01079 
01080     *ptr++ = THREAD_BEACON_PROTOCOL_ID;
01081     *ptr = THREAD_BEACON_PROTOCOL_VERSION << THREAD_BEACON_VERSION_SHIFT;
01082 
01083     if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) {
01084         *ptr |= THREAD_BEACON_JOINING_PERMITTED_BIT;    // permit join bit set on
01085     }
01086     if((leader_link_setup->securityPolicy & SECURITY_POLICY_NATIVE_COMMISSIONING_ALLOWED)){
01087         *ptr |= THREAD_BEACON_NATIVE_COMMISSIONER_BIT;
01088     }
01089     ptr++;
01090     memcpy(ptr, leader_link_setup->name, 16);
01091     ptr += 16;
01092     memcpy(ptr, leader_link_setup->extented_pan_id, 8);
01093     ptr += 8;
01094 
01095     if (server_data.joiner_router_enabled) {
01096         /* MESHCOP_TLV_JOINER_UDP_PORT */
01097         ptr = thread_joining_port_tlv_write(server_data.joiner_router_port, ptr);
01098     }
01099     if((leader_link_setup->securityPolicy & SECURITY_POLICY_NATIVE_COMMISSIONING_ALLOWED)){
01100         /* MESHCOP_TLV_COMMISSIONER_UDP_PORT */
01101         ptr = thread_commissioner_port_tlv_write(server_data.commissioner_port, ptr);
01102     }
01103 
01104 
01105     if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0){
01106         ptr = thread_nd_commission_data_write_steering_data(ptr, cur->thread_info->registered_commissioner.steering_data, cur->thread_info->registered_commissioner.steering_data_len);
01107     }
01108 
01109     return mac_helper_beacon_payload_register(cur);
01110 }
01111 
01112 uint8_t thread_beacon_indication(uint8_t *ptr, uint8_t len, protocol_interface_info_entry_t *cur)
01113 {
01114     (void)ptr;
01115     (void)len;
01116     (void)cur;
01117     return 1;
01118 }
01119 
01120 static uint8_t *thread_linkquality_write(int8_t interface_id, uint8_t *buffer)
01121 {
01122     uint8_t lqi1 = 0, lqi2 = 0, lqi3 = 0;
01123     thread_link_quality_e thread_link_quality;
01124     mle_neigh_table_list_t *neigh_list = mle_class_active_list_get(interface_id);
01125 
01126     ns_list_foreach(mle_neigh_table_entry_t, cur, neigh_list) {
01127         if (thread_is_router_addr(cur->short_adr)) {
01128             // Only count routers to link quality
01129             thread_link_quality = thread_link_margin_to_quality(cur->link_margin);
01130             switch (thread_link_quality) {
01131                 case QUALITY_20dB:
01132                     lqi3++;
01133                     break;
01134                 case QUALITY_10dB:
01135                     lqi2++;
01136                     break;
01137                 case QUALITY_2dB:
01138                     lqi1++;
01139                     break;
01140                 case QUALITY_BAD:
01141                     break;
01142 
01143             }
01144         }
01145     }
01146 
01147     *buffer++ = lqi3;
01148     *buffer++ = lqi2;
01149     *buffer++ = lqi1;
01150     return buffer;
01151 }
01152 
01153 uint8_t thread_route_option_size(protocol_interface_info_entry_t *cur)
01154 {
01155     return 2 + MLE_ROUTE_MIN_OPTION_LEN + thread_routing_get_route_data_size(cur);
01156 
01157 }
01158 uint8_t *thread_route_option_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
01159 {
01160     uint8_t *len_ptr;
01161     uint8_t *saved_ptr;
01162 
01163     saved_ptr = ptr;
01164     *ptr++ = MLE_TYPE_ROUTE;
01165     len_ptr = ptr++;
01166     /* ptr now points to ID sequence */
01167 
01168     /* Can write the data straight into the buffer */
01169     if (thread_routing_get_route_data(cur,
01170                                       ptr, /* ptr to ID sequence (1 byte) */
01171                                       ptr + 1, /* ptr to ID mask (MLE_ROUTE_ID_MASK_SIZE bytes) */
01172                                       ptr + MLE_ROUTE_MIN_OPTION_LEN, /* ptr to router table data */
01173                                       len_ptr) != 0) /* ptr to length */ { /* 0 -> SUCCESS */
01174         /* Point to beginning of buffer again */
01175         ptr = saved_ptr;
01176     } else {
01177         /* Function sets length to router table length - adjust for ID sequence and ID mask length */
01178         *len_ptr += MLE_ROUTE_MIN_OPTION_LEN;
01179         /* Advance buffer pointer past value field */
01180         ptr += *len_ptr;
01181     }
01182 
01183     return ptr;
01184 }
01185 
01186 uint8_t *thread_connectivity_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur, uint8_t mode)
01187 {
01188     thread_info_t *thread = thread_info(cur);
01189     //Set Connectivity
01190     *ptr++ = MLE_TYPE_CONNECTIVITY;
01191     *ptr++ = 10;
01192 
01193     // determine parent priority
01194     if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && (3*mle_class_rfd_entry_count_get(cur->id) > 2*THREAD_MAX_MTD_CHILDREN)) {
01195         *ptr++ = CONNECTIVITY_PP_LOW;
01196     } else if (!(mode & MLE_RX_ON_IDLE) && (3*mle_class_sleepy_entry_count_get(cur->id) > 2*THREAD_MAX_SED_CHILDREN)) {
01197         *ptr++ = CONNECTIVITY_PP_LOW;
01198     } else if (3*thread_router_bootstrap_child_count_get(cur) > 2*thread->maxChildCount) {
01199         // 1/3 of the child capacity remaining, PP=low
01200         *ptr++ = CONNECTIVITY_PP_LOW;
01201     } else if (mle_class_free_entry_count_get(cur->id) < THREAD_FREE_MLE_ENTRY_THRESHOLD) {
01202         // If only few entries available in the MLE table, change priority to low
01203         *ptr++ = CONNECTIVITY_PP_LOW;
01204     } else {
01205         *ptr++ = CONNECTIVITY_PP_MEDIUM;
01206     }
01207 
01208     ptr = thread_linkquality_write(cur->id, ptr);
01209 
01210     // Route Cost To leader
01211     if (thread->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER){
01212         // Leader cost
01213         *ptr++ = thread_routing_cost_get_by_router_id(&thread->routing, thread->thread_leader_data->leaderRouterId);
01214         //Router ID sequence
01215         *ptr++ = thread->routing.router_id_sequence;
01216     } else {
01217         // Leader cost when attached as child (REED,FED,SED,MED)
01218         *ptr++ = thread->thread_endnode_parent->pathCostToLeader;
01219         //Router ID sequence
01220         if (thread->routing.router_id_sequence_valid) {
01221             *ptr++ = thread->routing.router_id_sequence;
01222         } else {// We dont know the correct value
01223             *ptr++ = 0;
01224         }
01225     }
01226 
01227     // active Routers
01228     uint8_t activeRouters = 0;
01229     if (cur->thread_info->leader_private_data) {
01230         activeRouters = thread_routing_count_active_routers_from_mask(cur->thread_info->leader_private_data->master_router_id_mask);
01231     } else if (thread->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ) {
01232         activeRouters = thread_routing_count_active_routers(&thread->routing);
01233     }
01234     *ptr++ = activeRouters;
01235 
01236     //Set SED Buffer size and datagram count
01237     ptr = common_write_16_bit(THREAD_SED_BUFFER_SIZE, ptr);
01238     *ptr++ = THREAD_SED_DATAGRAM_COUNT;
01239 
01240     return ptr;
01241 }
01242 
01243 uint16_t thread_network_data_tlv_length(protocol_interface_info_entry_t *cur, bool fullist)
01244 {
01245     if (fullist) {
01246         return cur->thread_info->networkDataStorage.network_data_len;
01247     }
01248 
01249     return thread_network_data_generate_stable_set(cur, NULL);
01250 }
01251 
01252 uint16_t thread_network_data_generate_stable_set(protocol_interface_info_entry_t *cur, uint8_t *result_ptr)
01253 {
01254     uint8_t *dptr;
01255     uint16_t network_data_len = 0;
01256     uint8_t length;
01257     uint8_t type;
01258 
01259     dptr = cur->thread_info->networkDataStorage.network_data;
01260     uint16_t network_data_length = cur->thread_info->networkDataStorage.network_data_len;
01261 
01262     tr_debug("Generating stable set from network data of size %d",
01263              cur->thread_info->networkDataStorage.network_data_len);
01264 
01265     while (network_data_length) {
01266         if (network_data_length >= 2) {
01267             type = *dptr++;
01268             length = *dptr++;
01269 
01270             if (length == 0) {
01271                 // 0 is not valid length for TLV
01272                 return 0;
01273             }
01274 
01275             if (!(type & THREAD_NWK_STABLE_DATA)) {
01276                 // Skip this TLV altogether...
01277                 network_data_length -= 2 + length;
01278                 dptr += length;
01279                 continue;
01280             }
01281 
01282             type &= THREAD_NWK_DATA_TYPE_MASK;
01283             network_data_length -= 2;
01284 
01285             if (network_data_length < length) {
01286                 tr_error("Length error");
01287                 return 0;
01288             }
01289 
01290             // Set length ready for next check
01291             network_data_length -= length;
01292 
01293             if (type == THREAD_NWK_DATA_TYPE_PREFIX) {
01294                 uint8_t *length_ptr = NULL;
01295                 length -= 2;
01296 
01297                 uint8_t prefix_bytes_len = prefixBits_to_bytes(*(dptr+1));
01298 
01299                 if (prefix_bytes_len > length) {
01300                     return 0;
01301                 }
01302 
01303                 length -= prefix_bytes_len;
01304 
01305                 if (result_ptr) {
01306                     *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01307                     length_ptr = result_ptr;
01308                     result_ptr++;
01309                     memcpy(result_ptr, dptr, 2 + prefix_bytes_len);
01310                     result_ptr += 2 + prefix_bytes_len;
01311                 }
01312                 dptr += 2 + prefix_bytes_len;
01313 
01314                 network_data_len += 2 + 2 + prefix_bytes_len;
01315                 uint16_t total_tlv_length = 2 + prefix_bytes_len;
01316 
01317                 uint8_t context_id = thread_border_router_prefix_context_id(dptr, length);
01318                 tr_debug("Resolved Context ID: %d", context_id);
01319 
01320                 while (length > 2) {
01321                     type = *dptr++;
01322                     uint8_t subLength = *dptr++;
01323                     thread_border_router_tlv_entry_t genericService;
01324 
01325                     if (!(type & THREAD_NWK_STABLE_DATA)) {
01326                         // Skip this sub-TLV altogether...
01327                         dptr += subLength;
01328                         length -= 2 + subLength;
01329                         continue;
01330                     }
01331 
01332                     type &= THREAD_NWK_DATA_TYPE_MASK;
01333                     length -= 2;
01334 
01335                     tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength));
01336                     total_tlv_length += 2 + subLength;
01337                     network_data_len += 2 + subLength;
01338                     tr_debug("Total TLV length: %d", total_tlv_length);
01339                     if (subLength <= length) {
01340                         length -= subLength;
01341                         if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) {
01342                             if (result_ptr) {
01343                                 *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01344                                 *result_ptr++ = subLength;
01345                             }
01346                             while (subLength) {
01347                                 dptr += 2;
01348                                 uint16_t flags = common_read_16_bit(dptr);
01349                                 dptr += 2;
01350                                 subLength -= THREAD_BORDER_ROUTER_TLV_LENGTH;
01351                                 genericService.P_dhcp = ((flags >> THREAD_P_DHCP_BIT_MOVE) & 1);
01352                                 if (result_ptr) {
01353                                     if (genericService.P_dhcp) {
01354                                         result_ptr = common_write_16_bit(0xfc00 | context_id, result_ptr);
01355                                     } else {
01356                                         result_ptr = common_write_16_bit(0xfffe, result_ptr);
01357                                     }
01358                                     result_ptr = common_write_16_bit(flags, result_ptr);
01359                                 }
01360                             }
01361                         } else if (type == THREAD_NWK_DATA_TYPE_ROUTE) {
01362                             if (result_ptr) {
01363                                 *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01364                                 *result_ptr++ = subLength;
01365                             }
01366                             while (subLength) {
01367                                 dptr += 2;
01368                                 uint8_t preference = *dptr++;
01369                                 subLength -= THREAD_HAS_ROUTE_TLV_LENGTH;
01370                                 if (result_ptr) {
01371                                     result_ptr = common_write_16_bit(0xfffe, result_ptr);
01372                                     *result_ptr++ = preference;
01373                                 }
01374                             }
01375                         } else {
01376                             if (result_ptr) {
01377                                 *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01378                                 *result_ptr++ = subLength;
01379                                 memcpy(result_ptr, dptr, subLength);
01380                                 result_ptr += subLength;
01381                             }
01382 
01383                             dptr += subLength;
01384                         }
01385 
01386                     } else {
01387                         tr_error("Length fail");
01388                         return 0;
01389                     }
01390                 }
01391 
01392                 if (result_ptr) {
01393                     *length_ptr = total_tlv_length;
01394                 }
01395 
01396             } else if (type == THREAD_NWK_DATA_TYPE_SERVICE_DATA) {
01397                 uint8_t * length_ptr = NULL;
01398                 uint16_t total_tlv_length = 0;
01399                 uint16_t copy_length = 1;
01400                 uint8_t T = (*dptr) >> 7;
01401                 uint8_t S_id = *dptr & 0x0f;
01402 
01403                 if (!T) {
01404                     network_data_len += 4;
01405                     total_tlv_length += 4;
01406                     copy_length += 4;
01407                     length -= 4;
01408                 }
01409 
01410                 uint16_t service_data_length = *(dptr+copy_length);
01411 
01412                 if (result_ptr) {
01413                     *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01414                     length_ptr = result_ptr;
01415                     result_ptr++;
01416                     memcpy(result_ptr, dptr, 1 + copy_length + service_data_length);
01417                     result_ptr += 1 + copy_length + service_data_length;
01418                 }
01419                 network_data_len += 2 + 2 + service_data_length;
01420                 total_tlv_length += 2 + service_data_length;
01421                 dptr += 1 + copy_length + service_data_length;
01422                 length -= 2 + service_data_length;
01423 
01424                 while (length > 2) {
01425                     type = *dptr++;
01426                     uint8_t subLength = *dptr++;
01427 
01428                     if (!(type & THREAD_NWK_STABLE_DATA)) {
01429                         // Skip this sub-TLV altogether...
01430                         length -= 2 + subLength;
01431                         dptr += subLength;
01432                         continue;
01433                     }
01434 
01435                     length -= 2;
01436                     type &= THREAD_NWK_DATA_TYPE_MASK;
01437 
01438                     if (subLength <= length) {
01439                         tr_debug("SubType: %02x, length: %d, data: %s", type, length, trace_array(dptr, subLength));
01440                         total_tlv_length += 2 + subLength;
01441                         network_data_len += 2 + subLength;
01442                         length -= subLength;
01443                         if (result_ptr) {
01444                             *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01445                             *result_ptr++ = subLength;
01446                             uint8_t *rloc_ptr = result_ptr;
01447                             // Copy the remaining
01448                             memcpy(result_ptr, dptr, subLength);
01449                             result_ptr += subLength;
01450                             // Copy RLOC but replace with ALOC
01451                             common_write_16_bit(0xfc10 | S_id, rloc_ptr);
01452                         }
01453                         dptr += subLength;
01454                     } else {
01455                         tr_debug("Server sub-TLV parse fail!");
01456                         return 0;
01457                     }
01458                 }
01459 
01460                 if (result_ptr) {
01461                     *length_ptr = total_tlv_length;
01462                 }
01463             } else {
01464                 tr_debug("Unknown TLV: %d, length: %d", type, length);
01465                 network_data_len += 2 + length;
01466                 if (result_ptr) {
01467                     *result_ptr++ = type | THREAD_NWK_STABLE_DATA;
01468                     *result_ptr++ = length;
01469                     memcpy(result_ptr, dptr, length);
01470                     result_ptr += length;
01471                 }
01472                 dptr += length;
01473             }
01474         } else {
01475             tr_error("Length failure");
01476             return 0;
01477         }
01478     }
01479 
01480     return network_data_len;
01481 }
01482 
01483 uint16_t thread_network_data_tlv_size(protocol_interface_info_entry_t *cur, bool fullist)
01484 {
01485     uint16_t length = thread_network_data_tlv_length(cur, fullist);
01486 
01487     if (length > 254) {
01488         // 2 extra bytes for extended TLV format
01489         length += 2;
01490     }
01491 
01492     return length;
01493 }
01494 
01495 uint8_t *thread_network_data_tlv_write(protocol_interface_info_entry_t *cur, uint8_t *ptr, bool fulllist)
01496 {
01497     uint16_t length = thread_network_data_tlv_length(cur, fulllist);
01498     *ptr++ = MLE_TYPE_NETWORK_DATA;
01499 
01500     if (length > 254) {
01501         *ptr++ = 0xff;
01502         ptr = common_write_16_bit(length, ptr);
01503     } else {
01504         *ptr++ = length;
01505     }
01506 
01507     if (fulllist) {
01508         if (cur->thread_info->networkDataStorage.network_data_len > 0) {
01509             memcpy(ptr, cur->thread_info->networkDataStorage.network_data,
01510                    cur->thread_info->networkDataStorage.network_data_len);
01511             ptr += cur->thread_info->networkDataStorage.network_data_len;
01512         }
01513         return ptr;
01514     }
01515 
01516     uint16_t size = thread_network_data_generate_stable_set(cur, ptr);
01517     return ptr + size;
01518 }
01519 
01520 uint8_t *thread_active_timestamp_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
01521 {
01522     link_configuration_s *configuration;
01523 
01524     configuration = thread_joiner_application_get_config(cur->id);
01525     if (!configuration) {
01526         tr_error("No configuration");
01527         return ptr;
01528     }
01529     *ptr++ = MLE_TYPE_ACTIVE_TIMESTAMP;
01530     *ptr++ = 8;
01531     ptr = common_write_64_bit(configuration->timestamp, ptr);
01532     return ptr;
01533 }
01534 
01535 uint16_t thread_active_operational_dataset_size(protocol_interface_info_entry_t *cur)
01536 {
01537     return 2 + thread_joiner_application_active_config_length(cur->id, NULL, 0, mle_active_configuration_dataset_ignore_tlvs, mle_active_configuration_dataset_ignore_tlvs_size());
01538 }
01539 
01540 uint8_t *thread_active_operational_dataset_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
01541 {
01542     int length;
01543     length = thread_joiner_application_active_config_length(cur->id, NULL, 0, mle_active_configuration_dataset_ignore_tlvs, mle_active_configuration_dataset_ignore_tlvs_size());
01544     if (length < 1) {
01545         return ptr;
01546     }
01547     *ptr++ = MLE_TYPE_OPERATIONAL_DATASET;
01548     *ptr++ = length;
01549     ptr = thread_joiner_application_active_config_write(cur->id, ptr, NULL, 0, mle_active_configuration_dataset_ignore_tlvs, mle_active_configuration_dataset_ignore_tlvs_size());
01550 
01551     return ptr;
01552 }
01553 bool thread_active_operational_dataset_process(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t len, uint64_t dataset_timestamp)
01554 {
01555     //make a copy of the incoming timestamp
01556     uint64_t timestamp;
01557     link_configuration_s *link_configuration;
01558 
01559     if(!cur || !cur->thread_info || !ptr || !len){
01560         return false;
01561     }
01562     link_configuration = thread_joiner_application_get_config(cur->id);
01563     if (!link_configuration) {
01564         return false;
01565     }
01566     tr_debug("process Active dataset");
01567     timestamp = thread_joiner_application_active_timestamp_get(cur->id);
01568 
01569     if (timestamp > dataset_timestamp) {
01570         tr_debug("We have newer timestamp");
01571         thread_joiner_application_next_active_config_save(cur->id);
01572     }
01573     if (timestamp == dataset_timestamp) {
01574         // No changes required
01575         return false;
01576     }
01577     tr_debug("Update Active dataset");
01578     // New active operational dataset received;
01579     thread_joiner_application_update_configuration(cur->id, ptr, len, false);
01580     thread_joiner_application_active_timestamp_set(cur->id,dataset_timestamp);
01581     thread_configuration_thread_activate(cur,link_configuration);
01582     thread_joiner_application_configuration_nvm_save(cur->id);
01583     return true;
01584 }
01585 
01586 uint8_t thread_pending_timestamp_tlv_size(protocol_interface_info_entry_t *cur)
01587 {
01588     if (!thread_joiner_application_pending_config_timestamp_get(cur->id) ) {
01589         return 0;
01590     }
01591     return 2 + 8;
01592 }
01593 
01594 uint8_t *thread_pending_timestamp_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
01595 {
01596     uint64_t pending_timestamp;
01597 
01598     pending_timestamp = thread_joiner_application_pending_config_timestamp_get(cur->id);
01599     if (!pending_timestamp ) {
01600         return ptr;
01601     }
01602     *ptr++ = MLE_TYPE_PENDING_TIMESTAMP;
01603     *ptr++ = 8;
01604     ptr = common_write_64_bit(pending_timestamp, ptr);
01605     return ptr;
01606 }
01607 
01608 uint16_t thread_pending_operational_dataset_size(protocol_interface_info_entry_t *cur)
01609 {
01610 
01611     if (!thread_joiner_application_pending_config_exists(cur->id)) {
01612         return 0;
01613     }
01614     // Pending set always includes delay timer but not pending timestamp
01615     return thread_joiner_application_pending_config_length(cur->id, NULL, 0, mle_pending_configuration_dataset_ignore_tlvs, mle_pending_configuration_dataset_ignore_tlvs_size());
01616 }
01617 
01618 uint8_t *thread_pending_operational_dataset_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
01619 {
01620     int dataset_length;
01621     if (!thread_joiner_application_pending_config_exists(cur->id)) {
01622         return ptr;
01623     }
01624 
01625     dataset_length = thread_joiner_application_pending_config_length(cur->id, NULL, 0, mle_pending_configuration_dataset_ignore_tlvs, mle_pending_configuration_dataset_ignore_tlvs_size());
01626     if (dataset_length < 1) {
01627         return ptr;
01628     }
01629     *ptr++ = MLE_TYPE_PENDING_OPERATIONAL_DATASET;
01630     *ptr++ = dataset_length;
01631     ptr = thread_joiner_application_pending_config_build(cur->id, ptr, NULL, 0, mle_pending_configuration_dataset_ignore_tlvs, mle_pending_configuration_dataset_ignore_tlvs_size());
01632     return ptr;
01633 }
01634 
01635 bool thread_pending_operational_dataset_process(protocol_interface_info_entry_t *cur, uint64_t mle_pending_timestamp, uint8_t *ptr, uint16_t len)
01636 {
01637     uint32_t delay_timer;
01638 
01639     if(!cur || !cur->thread_info ){
01640         return false;
01641     }
01642     tr_debug("process pending dataset");
01643     if( !ptr || !len){
01644         // No pending set received
01645         return false;
01646     }
01647 
01648     if (4 > thread_meshcop_tlv_data_get_uint32(ptr, len,MESHCOP_TLV_DELAY_TIMER, &delay_timer)){
01649         tr_warn("Delay timer not present");
01650         return false;
01651     }
01652 
01653     if (mle_pending_timestamp < thread_joiner_application_pending_config_timestamp_get(cur->id) ) {
01654         // Saving this config for later use first we get the current active
01655         tr_debug("save pending set for future");
01656         thread_joiner_application_next_pending_config_save(cur->id);
01657     }
01658 
01659     if( 0 != thread_joiner_application_pending_config_create(cur->id, ptr, len)){
01660         tr_error("pending set creation failed");
01661         return false;
01662     }
01663     tr_debug("updating pending dataset");
01664     thread_joiner_application_pending_config_timestamp_set(cur->id,mle_pending_timestamp);
01665     thread_joiner_application_pending_config_enable(cur->id,delay_timer);
01666     return true;
01667 }
01668 
01669 uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur)
01670 {
01671     if (!cur || !cur->thread_info || !cur->thread_info->thread_leader_data) {
01672         return 0;
01673     }
01674     return 9;
01675 }
01676 
01677 uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur)
01678 {
01679     if (!cur || !cur->thread_info || !cur->thread_info->thread_leader_data) {
01680         return ptr;
01681     }
01682     *ptr++ = MLE_TYPE_LEADER_DATA; /* MLE TLV Type */
01683     *ptr++ = 8; /* MLE TLV Value: NWD:LDR TLV Length (7) */
01684     ptr = common_write_32_bit(cur->thread_info->thread_leader_data->partitionId, ptr);
01685     *ptr++ = cur->thread_info->thread_leader_data->weighting;
01686     *ptr++ = cur->thread_info->thread_leader_data->dataVersion;
01687     *ptr++ = cur->thread_info->thread_leader_data->stableDataVersion;
01688     *ptr++ = cur->thread_info->thread_leader_data->leaderRouterId;
01689     return ptr;
01690 }
01691 
01692 uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur)
01693 {
01694     uint8_t thread_realm_local_mcast_addr[16];
01695     lowpan_context_t *ctx;
01696     uint8_t *address_len_ptr;
01697 
01698     if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE &&
01699         thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
01700         // No address registration for others than MED or SED
01701         return ptr;
01702     }
01703     *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION;
01704     address_len_ptr = ptr++;
01705 
01706     *address_len_ptr = 0;
01707 
01708     // Register all global addressess
01709     ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
01710 
01711         if (*address_len_ptr > 148 ) {
01712             // Maximum length of address registrations
01713             continue;
01714         }
01715         if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL) {
01716             ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address);
01717             if (ctx) {
01718                 //Write TLV to list
01719                 *ptr++ = (ctx->cid | 0x80);
01720                 memcpy(ptr, e->address + 8, 8);
01721                 ptr += 8;
01722                 *address_len_ptr += 9;
01723             } else {
01724                 *ptr++ = 0;
01725                 memcpy(ptr, e->address, 16);
01726                 ptr += 16;
01727                 *address_len_ptr += 17;
01728 
01729             }
01730         }
01731     }
01732 
01733     /* Registers multicast addresses to the parent */
01734     thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3);
01735 
01736     ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups)
01737     {
01738         if (*address_len_ptr > 148) {
01739             // Maximum length of address registrations
01740             continue;
01741         }
01742         if (addr_ipv6_multicast_scope(entry->group) < IPV6_SCOPE_REALM_LOCAL) {
01743             /* Skip Link Local multicast address */
01744             continue;
01745         }
01746 
01747         if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) {
01748             /* Skip well-known realm-local all Thread nodes multicast address */
01749             continue;
01750         }
01751         if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) {
01752             /* Skip All MPL Forwarders address */
01753             continue;
01754         }
01755         if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_NODES)) {
01756             /* Skip Mesh local all nodes */
01757             continue;
01758         }
01759         if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_ROUTERS)) {
01760             /* Skip Mesh local all routers */
01761             continue;
01762         }
01763 
01764         *ptr++ = 0;
01765         memcpy(ptr, entry->group, 16);
01766         ptr += 16;
01767         *address_len_ptr += 17;
01768     }
01769     if (*address_len_ptr == 0) {
01770         // No address added remove type and length
01771         ptr -= 2;
01772     }
01773     return ptr;
01774 
01775 }
01776 
01777 int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64)
01778 {
01779     uint16_t buf_id;
01780     uint32_t keySequence;
01781     uint8_t *ptr;
01782     mle_message_timeout_params_t timeout;
01783 
01784     buf_id = mle_service_msg_allocate(interface->id, 32, false, MLE_COMMAND_REJECT);
01785     if (buf_id == 0) {
01786         return -1;
01787     }
01788 
01789     thread_management_get_current_keysequence(interface->id, &keySequence);
01790     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
01791 
01792     mle_service_set_msg_destination_address(buf_id, ll64);
01793 
01794     ptr = mle_service_get_data_pointer(buf_id);
01795 
01796     // write status TLV
01797     *ptr++ = MLE_TYPE_STATUS;
01798     *ptr++ = 1;
01799     *ptr++ = MLE_STATUS_ERROR;
01800 
01801     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
01802         tr_debug("Buffer overflow at message write");
01803     }
01804 
01805     timeout.retrans_max = 0;
01806     timeout.timeout_init = 0;
01807     timeout.timeout_max = 0;
01808     timeout.delay = MLE_NO_DELAY;
01809 
01810     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
01811 
01812     return mle_service_send_message(buf_id);
01813 
01814 }
01815 
01816 static uint8_t * thread_joining_port_tlv_write(uint16_t port, uint8_t *ptr)
01817 {
01818     *ptr++ = MESHCOP_TLV_JOINER_UDP_PORT;
01819     *ptr++ = 2;
01820     return common_write_16_bit(port, ptr);
01821 }
01822 
01823 static uint8_t * thread_commissioner_port_tlv_write(uint16_t port, uint8_t *ptr)
01824 {
01825     *ptr++ = MESHCOP_TLV_COMMISSIONER_UDP_PORT;
01826     *ptr++ = 2;
01827     return common_write_16_bit(port, ptr);
01828 }
01829 
01830 static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, mle_neigh_table_entry_t *neighbor)
01831 {
01832     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(nwk_id);
01833 
01834     tr_debug("In Thread TX_FAIL handler, accumulated_failures=%d", accumulated_failures);
01835 
01836     if (!cur || !cur->thread_info) {
01837         return;
01838     }
01839 
01840     if (accumulated_failures >= THREAD_MAC_TRANSMISSIONS*THREAD_FAILED_CHILD_TRANSMISSIONS) {
01841         thread_reset_neighbour_info(cur, neighbor);
01842     }
01843 }
01844 
01845 /* Called when MLE link to neighbour lost, or ETX callback says link is bad */
01846 void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *neighbour)
01847 {
01848     thread_parent_info_t *thread_endnode_parent = thread_info(cur)->thread_endnode_parent;
01849 
01850     if (!thread_i_am_router(cur) && thread_endnode_parent && thread_endnode_parent->shortAddress == neighbour->short_adr) {
01851         tr_warn("End device lost Parent!\n");
01852         if(cur->nwk_bootstrap_state != ER_CHILD_ID_REQ) {
01853             thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
01854         }
01855     }
01856 
01857     thread_routing_remove_link(cur, neighbour->short_adr);
01858     thread_router_bootstrap_reset_child_info(cur, neighbour);
01859     protocol_6lowpan_release_long_link_address_from_neighcache(cur, neighbour->mac64);
01860     mac_helper_devicetable_remove(cur->mac_api, neighbour->attribute_index);
01861 }
01862 
01863 uint8_t thread_get_router_count_from_route_tlv(mle_tlv_info_t *routeTlv)
01864 {
01865     if (!routeTlv)
01866         return 0;
01867 
01868     if (routeTlv->tlvLen < (MLE_ROUTE_ID_MASK_SIZE + 1))
01869         return 0;
01870 
01871     if (!routeTlv->dataPtr)
01872         return 0;
01873 
01874     return routeTlv->tlvLen - MLE_ROUTE_ID_MASK_SIZE - 1;
01875 }
01876 
01877 static void thread_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason)
01878 {
01879     if (thread_attach_ready(interface) != 0) {
01880         return;
01881     }
01882 
01883     if (reason != ADDR_CALLBACK_DAD_COMPLETE && reason != ADDR_CALLBACK_DELETED) {
01884         return;
01885     }
01886 
01887     if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_REALM_LOCAL) {
01888         tr_debug("Global address changed: %s", trace_ipv6(addr->address));
01889 
01890         if (thread_bootstrap_should_register_address(interface)) {
01891             interface->thread_info->childUpdateReqTimer = 1;
01892         } else {
01893             if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
01894                 /* Send address notification (our parent doesn't do that for us) */
01895                 thread_extension_address_registration(interface, addr->address, NULL);
01896             }
01897         }
01898     }
01899 }
01900 
01901 void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added)
01902 {
01903     (void) addr_added;
01904 
01905     group->mld_timer = 0;
01906 
01907     if (thread_attach_ready(interface) != 0) {
01908         return;
01909     }
01910 
01911     tr_debug("Thread multicast address changed: %s", trace_ipv6(group->group));
01912 
01913     if (thread_bootstrap_should_register_address(interface)) {
01914         /* Trigger Child Update Request only if MTD child's multicast address change */
01915         if (addr_ipv6_multicast_scope(group->group) > IPV6_SCOPE_LINK_LOCAL) {
01916             interface->thread_info->childUpdateReqTimer = 1;
01917         }
01918     } else {
01919         thread_extension_mcast_subscrition_change(interface, group, addr_added);
01920     }
01921 }
01922 
01923 void thread_old_partition_data_purge(protocol_interface_info_entry_t *cur)
01924 {
01925     /* Partition has been changed. Wipe out data related to old partition */
01926     thread_management_client_pending_coap_request_kill(cur->id);
01927 
01928     /* Reset previous routing information */
01929     thread_routing_reset(&cur->thread_info->routing);
01930 
01931     /* Flush address cache */
01932     ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
01933 
01934 }
01935 
01936 #endif
01937