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