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_bootstrap.c
00001 /* 00002 * Copyright (c) 2014-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 00030 /* 00031 * \file thread_bootstrap.c 00032 * \brief Add short description about this file!!! 00033 * 00034 */ 00035 #include "nsconfig.h" 00036 #ifdef HAVE_THREAD 00037 #include <string.h> 00038 #include <ns_types.h> 00039 #include <nsdynmemLIB.h> 00040 #include "eventOS_event.h" 00041 #include "eventOS_event_timer.h" 00042 #include "randLIB.h" 00043 #include "ns_sha256.h" 00044 #include "common_functions.h" 00045 #include "NWK_INTERFACE/Include/protocol.h" 00046 #include "net_thread_test.h" 00047 #include "ipv6_stack/protocol_ipv6.h" 00048 #include "libDHCPv6/libDHCPv6.h" 00049 #include "libDHCPv6/libDHCPv6_server.h" 00050 #include "ns_trace.h" 00051 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00052 #include "6LoWPAN/Thread/thread_common.h" 00053 #include "6LoWPAN/Thread/thread_routing.h" 00054 #include "6LoWPAN/Thread/thread_nd.h" 00055 #include "6LoWPAN/Thread/thread_bootstrap.h" 00056 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00057 #include "6LoWPAN/Thread/thread_discovery.h" 00058 #include "6LoWPAN/Thread/thread_leader_service.h" 00059 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00060 #include "6LoWPAN/Thread/thread_management_internal.h" 00061 #include "6LoWPAN/Thread/thread_management_server.h" 00062 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00063 #include "6LoWPAN/Thread/thread_network_synch.h" 00064 #include "6LoWPAN/Thread/thread_joiner_application.h" 00065 #include "6LoWPAN/Thread/thread_extension.h" 00066 #include "6LoWPAN/Thread/thread_extension_bbr.h" 00067 #include "6LoWPAN/Thread/thread_management_client.h" 00068 #include "6LoWPAN/Thread/thread_address_registration_client.h" 00069 #include "6LoWPAN/Thread/thread_joiner_application.h" 00070 #include "6LoWPAN/Thread/thread_bbr_api_internal.h" 00071 #include "6LoWPAN/Thread/thread_border_router_api_internal.h" 00072 #include "6LoWPAN/Thread/thread_beacon.h" 00073 #include "6LoWPAN/Thread/thread_nvm_store.h" 00074 #include "6LoWPAN/Thread/thread_extension_bootstrap.h" 00075 #include "6LoWPAN/MAC/mac_helper.h" 00076 #include "6LoWPAN/Thread/thread_mle_message_handler.h" 00077 #include "mac_api.h" 00078 #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up 00079 #include "thread_management_if.h" 00080 #include "thread_border_router_api.h" 00081 #include "thread_tmfcop_lib.h" 00082 #include "Common_Protocols/ipv6.h" 00083 #include "Common_Protocols/icmpv6.h" 00084 #include "Common_Protocols/icmpv6_radv.h" 00085 #include "MPL/mpl.h" 00086 #include "MLE/mle.h" 00087 #include "MLE/mle_tlv.h" 00088 #include "thread_dhcpv6_client.h" 00089 #include "thread_config.h" 00090 #include "thread_meshcop_lib.h" 00091 #include "multicast_api.h" 00092 #include "mlme.h" 00093 #include "Service_Libs/nd_proxy/nd_proxy.h" 00094 #include "Service_Libs/blacklist/blacklist.h" 00095 #include "6LoWPAN/MAC/mac_data_poll.h" 00096 00097 #define TRACE_GROUP "thbs" 00098 00099 //#define EXTRA_DEBUG_INFO 00100 #ifdef EXTRA_DEBUG_INFO 00101 #define tr_debug_extra(...) tr_debug(__VA_ARGS__) 00102 #else 00103 #define tr_debug_extra(...) 00104 #endif 00105 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur); 00106 00107 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur_interface); 00108 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration); 00109 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur); 00110 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur); 00111 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state); 00112 static void thread_bootsrap_network_discovery_failure(int8_t interface_id); 00113 00114 static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur); 00115 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info); 00116 00117 00118 00119 static bool thread_interface_is_active(int8_t interface_id) { 00120 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00121 if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { 00122 return false; 00123 } 00124 00125 return true; 00126 } 00127 00128 static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur) 00129 { 00130 protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id); 00131 if (!cur_interface) { 00132 return; 00133 } 00134 thread_reset_neighbour_info(cur_interface, cur); 00135 } 00136 00137 int8_t thread_mle_class_init(int8_t interface_id) 00138 { 00139 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00140 if (!cur) { 00141 return -1; 00142 } 00143 00144 mac_description_storage_size_t buffer; 00145 //Read MAC device table sizes 00146 if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) { 00147 return -1; 00148 } 00149 00150 if (buffer.key_description_table_size < 4) { 00151 return -1; 00152 } 00153 00154 if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_host_bootstrap_child_update, &thread_interface_is_active) != 0) { 00155 return -1; 00156 } 00157 00158 mle_class_router_challenge(interface_id, NULL); 00159 00160 //Defined well know neighbour for discovery 00161 00162 return 0; 00163 } 00164 00165 00166 00167 uint8_t thread_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur) 00168 { 00169 uint8_t mle_mode = 0; 00170 if (!thread_info(cur)) { 00171 return 0; 00172 } 00173 if (cur->mac_parameters->RxOnWhenIdle) { 00174 mle_mode |= MLE_RX_ON_IDLE; 00175 } 00176 00177 if (thread_info(cur)->requestFullNetworkData) { 00178 mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET); 00179 } 00180 if (thread_joiner_application_provisioning_get(cur->id) == PROVISIONING_STATUS_NOT_DONE) { 00181 // if provisioning is not done Sleepy devices need to temporarily request full network data 00182 // To receive commissioner information 00183 mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET); 00184 } 00185 00186 /* We always send secured data requests */ 00187 mle_mode |= MLE_THREAD_SECURED_DATA_REQUEST; 00188 00189 switch (thread_info(cur)->thread_device_mode) { 00190 case THREAD_DEVICE_MODE_ROUTER: 00191 case THREAD_DEVICE_MODE_FULL_END_DEVICE: 00192 mle_mode |= MLE_FFD_DEV; 00193 break; 00194 00195 default: 00196 break; 00197 } 00198 00199 00200 return mle_mode; 00201 } 00202 00203 /** 00204 * Return lower (worse) of the two margins. 00205 */ 00206 uint8_t thread_parent_margin_calc(uint8_t marginFromParent, uint8_t marginToParent) 00207 { 00208 if (marginFromParent > marginToParent) { 00209 return marginToParent; 00210 } else { 00211 return marginFromParent; 00212 } 00213 } 00214 00215 uint8_t thread_compute_link_margin(int8_t rssi) 00216 { 00217 if (rssi < -94) { 00218 return 0; 00219 } 00220 00221 return (rssi + 94); 00222 } 00223 00224 uint8_t thread_calculate_link_margin(int8_t dbm, uint8_t compLinkMarginFromParent) 00225 { 00226 uint8_t compLinkMarginToParent; 00227 uint8_t newLqi; 00228 00229 compLinkMarginToParent = thread_compute_link_margin(dbm); 00230 //Calculate New Combined LQI 00231 newLqi = thread_parent_margin_calc(compLinkMarginFromParent, compLinkMarginToParent); 00232 return newLqi; 00233 } 00234 00235 bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp) 00236 { 00237 if (entry_temp && thread_info(cur)->thread_endnode_parent) { 00238 if(memcmp(entry_temp->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) == 0) { 00239 return true; 00240 } 00241 } 00242 return false; 00243 } 00244 00245 bool thread_bootstrap_request_network_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, uint16_t short_address) 00246 { 00247 bool requestNetworkdata = false; 00248 thread_leader_data_t *leadeInfo = thread_info(cur)->thread_leader_data; 00249 00250 if (thread_info(cur)->thread_endnode_parent->shortAddress != short_address) { 00251 return false; 00252 } 00253 00254 if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) { 00255 tr_debug("Learn new Network Data"); 00256 requestNetworkdata = true; 00257 thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1; 00258 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1; 00259 } 00260 else if (common_serial_number_greater_8(leaderData->dataVersion, leadeInfo->dataVersion)) { 00261 requestNetworkdata = true; 00262 00263 } else if (common_serial_number_greater_8(leaderData->stableDataVersion, leadeInfo->stableDataVersion)) { 00264 requestNetworkdata = true; 00265 00266 } 00267 00268 // Version number is updated when new network data is learned to avoid synchronization problems 00269 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId; 00270 thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId; 00271 if (requestNetworkdata) { 00272 thread_bootstrap_parent_network_data_request(cur, true); 00273 } 00274 return true; 00275 } 00276 00277 bool thread_instance_id_matches(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) 00278 { 00279 if (thread_info(cur)->thread_leader_data) { 00280 if (thread_info(cur)->thread_leader_data->partitionId == leaderData->partitionId) { 00281 return true; 00282 } 00283 } 00284 return false; 00285 } 00286 00287 static int thread_router_check_previous_partition_info(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv) 00288 { 00289 if (!routeTlv || !routeTlv->dataPtr || !routeTlv->tlvLen || !leaderData) { 00290 //check for parameters 00291 return -1; 00292 } 00293 if ((leaderData->partitionId == cur->thread_info->previous_partition_info.partitionId) && 00294 (leaderData->weighting == cur->thread_info->previous_partition_info.weighting) && 00295 (routeTlv->dataPtr[0] == cur->thread_info->previous_partition_info.idSequence)) { 00296 //drop the advertisement from previuos partition 00297 return 1; 00298 } 00299 else { 00300 //do not drop the advertisement 00301 return 0; 00302 } 00303 } 00304 int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uint8_t heard_partition_routers, thread_leader_data_t *heard_partition_leader_data, mle_tlv_info_t *routeTlv) 00305 { 00306 uint8_t active_routers = 0; 00307 thread_leader_data_t *current_leader_data = NULL; 00308 00309 /* if there scanned parent, then the comparison is between parent responses so retrieve the previously scanned parent info 00310 * else comparison is between existing leader data and heard advertisement leader data so retrieve existing leader data 00311 */ 00312 if (thread_info(cur)->thread_attach_scanned_parent) { 00313 current_leader_data = &thread_info(cur)->thread_attach_scanned_parent->leader_data; 00314 active_routers = thread_info(cur)->thread_attach_scanned_parent->activeRouters; 00315 } else { 00316 current_leader_data = thread_info(cur)->thread_leader_data; 00317 active_routers = thread_routing_count_active_routers(&thread_info(cur)->routing); 00318 } 00319 00320 if (!current_leader_data) { 00321 tr_warn("There is no leader data present"); 00322 return -2; 00323 } 00324 00325 if (1 == thread_router_check_previous_partition_info(cur, heard_partition_leader_data, routeTlv)) { 00326 tr_debug("Dropping advertisement from old partition without sequence number increase"); 00327 return -2; 00328 } 00329 00330 /*Rule 0: If we are going to form Higher partition than heard we dont try to attach to lower ones 00331 */ 00332 if (thread_extension_enabled(cur) && 00333 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00334 if (heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) { 00335 tr_debug("Heard a lower weight partition"); 00336 return -2; 00337 } 00338 if (heard_partition_leader_data->weighting > thread_info(cur)->partition_weighting) { 00339 return 2; 00340 } 00341 } 00342 00343 if ((heard_partition_routers == 0 && active_routers == 1) && thread_am_router(cur)) { 00344 //heard a REED and I am a lonely router in a singleton partition, so merge 00345 tr_debug("Heard a REED and I am a singleton - merge"); 00346 return 2; 00347 } 00348 00349 //Rule 1: A non-singleton Thread Network Partition always has higher priority than a singleton Thread Network Partition 00350 if (heard_partition_routers > 1 && active_routers == 1) { 00351 tr_debug("Heard a nonsingleton and i am a singleton"); 00352 return 2; 00353 } 00354 if (active_routers > 1 && heard_partition_routers == 1) { 00355 return -2; 00356 } 00357 00358 /*Rule 2: When comparing two singleton or two non-singleton Thread Network Partitions, 00359 the one with the higher 8-bit weight value has higher priority. */ 00360 if (heard_partition_leader_data->weighting > current_leader_data->weighting) { 00361 tr_debug("Heard a greater weighting"); 00362 return 2; 00363 } 00364 00365 if (heard_partition_leader_data->weighting < current_leader_data->weighting) { 00366 return -2; 00367 } 00368 00369 /*Rule 3: When comparing two singleton or two non-singleton Thread Network Partitions that have the same 8-bit weight value, 00370 * the one with the higher Partition ID, considered as unsigned 32-bit numbers, has higher priority. 00371 */ 00372 if (heard_partition_leader_data->partitionId > current_leader_data->partitionId){ 00373 tr_debug("Heard a greater partition id"); 00374 return 2; 00375 } 00376 00377 if (heard_partition_leader_data->partitionId < current_leader_data->partitionId) { 00378 return -2; 00379 } 00380 00381 return -2; 00382 } 00383 00384 int thread_leader_data_validation(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv) 00385 { 00386 if (!thread_info(cur)->thread_leader_data) { 00387 return -1; 00388 } 00389 if ((thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) || 00390 (thread_info(cur)->thread_leader_data->weighting != leaderData->weighting)) { 00391 uint8_t routers_in_route_tlv = thread_get_router_count_from_route_tlv(routeTlv); 00392 //partition checks 00393 return thread_bootstrap_partition_process(cur,routers_in_route_tlv,leaderData, routeTlv); 00394 } 00395 00396 //Should check is there new version numbers 00397 if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion) || 00398 common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) { 00399 // Version number increased by some-one else -> there is leader in the network 00400 if (thread_info(cur)->leader_private_data) { 00401 tr_error("Another leader detected -> bootstrap"); 00402 thread_bootstrap_reset_restart(cur->id); 00403 return -1; 00404 } 00405 tr_debug("NEW Network Data available"); 00406 return 1; 00407 } 00408 00409 return 0; 00410 } 00411 00412 void thread_bootstrap_all_nodes_address_generate(uint8_t multicast_address[16],uint8_t prefix[8], uint8_t scope) 00413 { 00414 memset(multicast_address, 0, 16); 00415 multicast_address[0] = 0xff; 00416 multicast_address[1] = 0x30 | scope; //Thread specification says p and t bits are 1 00417 multicast_address[2] = 0x00; //Reserved 00418 multicast_address[3] = 0x40; //Prefix length 64 bits 00419 memcpy(&multicast_address[4], prefix,8); 00420 multicast_address[15] = 1; 00421 } 00422 00423 void thread_bootstrap_all_nodes_multicast_register(protocol_interface_info_entry_t *cur) 00424 { 00425 uint8_t multicast_address[16]; 00426 00427 switch (cur->thread_info->thread_device_mode) { 00428 #ifdef HAVE_THREAD_ROUTER 00429 case THREAD_DEVICE_MODE_ROUTER: 00430 cur->if_special_multicast_forwarding = thread_router_bootstrap_multicast_forwarder_enable; 00431 break; 00432 #endif 00433 00434 default: 00435 cur->if_special_multicast_forwarding = NULL; 00436 break; 00437 } 00438 00439 // Register to link local all thread nodes multicast 00440 thread_bootstrap_all_nodes_address_generate(multicast_address,cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); 00441 tr_debug("Register multicast address: %s",trace_ipv6(multicast_address)); 00442 addr_add_group(cur, multicast_address); 00443 00444 // Register to mesh local all thread nodes multicast 00445 thread_bootstrap_all_nodes_address_generate(multicast_address,cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); 00446 tr_debug("Register multicast address: %s",trace_ipv6(multicast_address)); 00447 addr_add_group(cur, multicast_address); 00448 } 00449 00450 void thread_bootstrap_all_nodes_multicast_unregister(protocol_interface_info_entry_t *cur) 00451 { 00452 uint8_t multicast_address[16]; 00453 00454 if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) { 00455 //Prefix not valid do not delete 00456 return; 00457 } 00458 // Unregister to link local all thread nodes multicast 00459 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 2); 00460 tr_debug("Free multicast address: %s",trace_ipv6(multicast_address)); 00461 //multicast_free_address(multicast_address); 00462 addr_remove_group(cur, multicast_address); 00463 00464 // Unregister to mesh local all thread nodes multicast 00465 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); 00466 tr_debug("Free multicast address: %s",trace_ipv6(multicast_address)); 00467 //multicast_free_address(multicast_address); 00468 addr_remove_group(cur, multicast_address); 00469 } 00470 00471 void thread_end_device_mode_set(protocol_interface_info_entry_t *cur, bool sleepy) 00472 { 00473 if (sleepy) { 00474 cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; 00475 mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE); 00476 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false); 00477 } else { 00478 cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; 00479 mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE); 00480 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); 00481 } 00482 } 00483 00484 00485 int8_t nwk_thread_host_control(protocol_interface_info_entry_t *cur, net_host_mode_t mode, uint32_t delay) 00486 { 00487 int8_t ret_val = 0; 00488 //Check IF Bootsrap Ready and type is Host 00489 00490 if (cur == NULL || cur->rfd_poll_info == NULL) { 00491 return -1; 00492 } 00493 00494 nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info; 00495 switch (mode) { 00496 case NET_HOST_FAST_POLL_MODE: 00497 //fast mode 00498 //Check Host current sleep state 00499 if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) { 00500 tr_debug("Enable Fast poll mode. Init Poll timer and period"); 00501 thread_end_device_mode_set(cur, true); 00502 mac_poll_timer_trig(delay, cur); 00503 rf_ptr->nwk_app_poll_time = 300; 00504 rf_ptr->host_mode = NET_HOST_FAST_POLL_MODE; 00505 } 00506 break; 00507 00508 case NET_HOST_RX_ON_IDLE: 00509 // Non-sleep mode 00510 thread_end_device_mode_set(cur, false); 00511 rf_ptr->host_mode = NET_HOST_RX_ON_IDLE; 00512 break; 00513 00514 default: 00515 ret_val = -1; 00516 break; 00517 } 00518 00519 return ret_val; 00520 } 00521 00522 void thread_set_link_local_address(protocol_interface_info_entry_t *cur) 00523 { 00524 ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { 00525 if(memcmp(addr->address, ADDR_LINK_LOCAL_PREFIX,8) == 0) { 00526 tr_debug("deleting address %s", trace_ipv6(addr->address)); 00527 ns_list_remove(&cur->ip_addresses, addr); 00528 ns_dyn_mem_free(addr); 00529 } 00530 } 00531 00532 /* Fix EUId64 also to start use 0*/ 00533 memcpy(cur->iid_eui64, cur->mac, 8); 00534 cur->iid_eui64[0] ^= 2; 00535 addr_interface_set_ll64(cur, NULL); 00536 } 00537 00538 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00539 { 00540 uint8_t key_material[32]; 00541 uint8_t key_index; 00542 00543 tr_debug("MAC SET Security Mode"); 00544 00545 if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE) || !(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) { 00546 return -1; 00547 } 00548 mac_helper_security_key_clean(cur); 00549 mac_helper_default_security_level_set(cur, 5); 00550 mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX); 00551 00552 cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY; 00553 cur->mac_parameters->mac_configured_sec_level = 5; 00554 cur->thread_info->masterSecretMaterial.historyKeyValid = false; 00555 cur->thread_info->masterSecretMaterial.valid_Info = true; 00556 // Update the guard timer value 00557 thread_calculate_key_guard_timer(cur, linkConfiguration, true); 00558 //Define KEY's 00559 thread_key_get(linkConfiguration->master_key, key_material, linkConfiguration->key_sequence); 00560 key_index = THREAD_KEY_INDEX(linkConfiguration->key_sequence); 00561 //Set Keys 00562 mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX); 00563 //Add Security to MLE service 00564 mle_service_security_set_security_key(cur->id, key_material, key_index, true); 00565 //Gen also Next Key 00566 thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence); 00567 return 0; 00568 } 00569 00570 void thread_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator) 00571 { 00572 mlme_start_t start_req; 00573 memset(&start_req, 0, sizeof(mlme_start_t)); 00574 00575 cur->mac_parameters->pan_id = panid; 00576 cur->mac_parameters->mac_channel = channel; 00577 00578 start_req.PANId = panid; 00579 start_req.LogicalChannel = channel; 00580 start_req.BeaconOrder = 0x0f; 00581 start_req.SuperframeOrder = 0x0f; 00582 start_req.PANCoordinator = coordinator; 00583 00584 thread_discovery_responser_enable(cur->id, coordinator); 00585 00586 if (cur->mac_api) { 00587 cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void*)&start_req); 00588 } 00589 } 00590 00591 int thread_configuration_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid,uint8_t *extended_random_mac) 00592 { 00593 ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); 00594 mac_helper_mac64_set(cur, extended_random_mac); 00595 thread_set_link_local_address(cur); 00596 00597 //SET Thread default here 00598 mac_helper_mac_mlme_max_retry_set(cur->id, THREAD_MAX_FRAME_RETRIES); 00599 00600 bool coordinator = (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER); 00601 thread_bootstrap_mac_activate(cur, channel, panid, coordinator); 00602 00603 mac_data_poll_init(cur); 00604 00605 return 0; 00606 } 00607 00608 int thread_configuration_6lowpan_activate(protocol_interface_info_entry_t *cur ) 00609 { 00610 tr_debug("6lowpan configure"); 00611 cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION; 00612 cur->configure_flags |= INTERFACE_SECURITY_DEFINED; 00613 return 0; 00614 } 00615 00616 static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t *cur, const link_configuration_s *conf) 00617 { 00618 tr_debug("Updating ML addresses and prefix information."); 00619 uint8_t address[16]; 00620 00621 if (cur->thread_info->threadPrivatePrefixInfo.ulaValid && 00622 memcmp(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 00623 conf->mesh_local_ula_prefix, 8) != 0) { 00624 // Current prefix is valid and old vs. new different: update old addresses 00625 // Update the addresses in the neighbor cache (replace the old ULA prefix part) 00626 ns_list_foreach(ipv6_neighbour_t, entry, &cur->ipv6_neighbour_cache.list) { 00627 tr_debug("Neighbor cache address: %s", trace_ipv6(entry->ip_address)); 00628 if (bitsequal(entry->ip_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) { 00629 memcpy(entry->ip_address, conf->mesh_local_ula_prefix, 8); 00630 tr_debug("Updated to %s.", trace_ipv6(entry->ip_address)); 00631 } 00632 } 00633 00634 // Delete the ML64 address 00635 thread_delete_ml64_address(cur); 00636 00637 // Free previously registered multicast addresses 00638 thread_bootstrap_all_nodes_multicast_unregister(cur); 00639 00640 // In-place replace all other mesh local addresses... 00641 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 00642 tr_debug("IP address: %s", trace_ipv6(e->address)); 00643 if (bitsequal(e->address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) { 00644 memcpy(address, conf->mesh_local_ula_prefix, 8); 00645 memcpy(address+8, e->address+8, 8); 00646 tr_debug("Updated to: %s", trace_ipv6(address)); 00647 addr_add(cur, address, e->prefix_len, e->source, e->valid_lifetime, e->preferred_lifetime, true); 00648 addr_delete_entry(cur, e); 00649 } 00650 } 00651 } 00652 00653 // Set new ML-EID and ULA prefix 00654 uint8_t *ml_eid = thread_joiner_application_ml_eid_get(cur->id); 00655 memcpy(cur->iid_slaac, ml_eid, 8); 00656 00657 arm_thread_private_ula_prefix_set(cur, conf->mesh_local_ula_prefix); 00658 00659 // Generate new ML64 address 00660 thread_generate_ml64_address(cur); 00661 // Generate new domain address 00662 thread_extension_address_generate(cur); 00663 00664 // Register multicast addresses 00665 thread_bootstrap_all_nodes_multicast_register(cur); 00666 00667 // Register leader anycast address (if we are the leader) 00668 thread_router_bootstrap_anycast_address_register(cur); 00669 00670 thread_bootstrap_routing_activate(cur); 00671 } 00672 00673 int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00674 { 00675 tr_debug("thread configure"); 00676 00677 // Update existing mesh-local addresses and the ML prefix 00678 thread_bootstrap_ml_address_update(cur, linkConfiguration); 00679 00680 //Define Default Contexts 00681 lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true); 00682 00683 thread_extension_activate(cur); 00684 00685 thread_extension_bbr_route_update(cur); 00686 00687 blacklist_clear(); 00688 00689 blacklist_params_set( 00690 THREAD_BLACKLIST_ENTRY_LIFETIME, 00691 THREAD_BLACKLIST_TIMER_MAX_TIMEOUT, 00692 THREAD_BLACKLIST_TIMER_TIMEOUT, 00693 THREAD_BLACKLIST_ENTRY_MAX_NBR, 00694 THREAD_BLACKLIST_PURGE_NBR, 00695 THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT); 00696 00697 return 0; 00698 } 00699 00700 int thread_configuration_mle_activate(protocol_interface_info_entry_t *cur) 00701 { 00702 tr_debug("thread MLE configure"); 00703 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 00704 return 0; 00705 } 00706 00707 int thread_configuration_mle_disable(protocol_interface_info_entry_t *cur) 00708 { 00709 tr_debug("thread MLE disable"); 00710 mle_service_interface_receiver_handler_update(cur->id, NULL); 00711 return 0; 00712 } 00713 00714 int thread_mle_service_register(int8_t interface_id, uint8_t *mac64 ) 00715 { 00716 if (mle_service_interface_register(interface_id,thread_mle_parent_discover_receive_cb, mac64,8) != 0) { 00717 tr_error("Mle Service init Fail"); 00718 return -1; 00719 } 00720 mle_service_set_frame_counter_check(true); 00721 mle_service_set_fragmented_msg_ll_security(true); 00722 return 0; 00723 } 00724 00725 int thread_link_configuration_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00726 { 00727 //Generate Beacon Payload from active configuration 00728 if (thread_beacon_create_payload(cur) != 0) { 00729 return -1; 00730 } 00731 00732 if (thread_configuration_mac_activate(cur, linkConfiguration->rfChannel, linkConfiguration->panId,thread_joiner_application_random_mac_get(cur->id))) { 00733 return -1; 00734 } 00735 00736 thread_configuration_thread_activate(cur, linkConfiguration); 00737 thread_configuration_security_activate(cur, linkConfiguration); 00738 thread_configuration_6lowpan_activate(cur); 00739 return 0; 00740 } 00741 00742 int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp, uint16_t selected_channel) 00743 { 00744 uint8_t *ptr; 00745 uint8_t channel_tlv[3]; 00746 mle_message_timeout_params_t timeout; 00747 uint32_t keySequence; 00748 uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_DATASET_ANNOUNCE); 00749 if (buf_id == 0) { 00750 return -1; 00751 } 00752 00753 mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_NODES); 00754 00755 thread_management_get_current_keysequence(cur->id, &keySequence); 00756 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00757 mle_service_set_msg_link_layer_security_mode(buf_id, true); 00758 00759 ptr = mle_service_get_data_pointer(buf_id); 00760 00761 ptr = thread_meshcop_tlv_data_write_uint64(ptr,MLE_TYPE_ACTIVE_TIMESTAMP, timestamp); 00762 ptr = thread_meshcop_tlv_data_write_uint16(ptr,MLE_TYPE_PANID, panid); 00763 channel_tlv[0] = channel_page; 00764 common_write_16_bit(channel, &channel_tlv[1]); 00765 ptr = thread_meshcop_tlv_data_write(ptr,MLE_TYPE_CHANNEL, 3, channel_tlv); 00766 00767 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 00768 tr_debug("Buffer overflow at message write"); 00769 } 00770 //SET packet channel 00771 mle_service_set_msg_rf_channel(buf_id, selected_channel); 00772 00773 timeout.retrans_max = 0; 00774 timeout.timeout_init = 0; 00775 timeout.timeout_max = 0; 00776 timeout.delay = MLE_NO_DELAY; 00777 00778 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00779 mle_service_set_msg_panid(buf_id, 0xffff); 00780 mle_service_send_message(buf_id); 00781 return 0; 00782 } 00783 static void thread_announce_ntf_cb(void* arg) 00784 { 00785 if(!arg) 00786 return; 00787 protocol_interface_info_entry_t *cur = arg; 00788 cur->thread_info->announcement_info->timer = NULL; 00789 thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00790 } 00791 00792 static void thread_announce_success_cb(void* arg) 00793 { 00794 // We come here when we have succesfully attached to announced channel and then we announce this back 00795 protocol_interface_info_entry_t *cur = arg; 00796 00797 if (!cur || !cur->thread_info->announcement_info) { 00798 return; 00799 } 00800 00801 cur->thread_info->announcement_info->timer = NULL; 00802 cur->thread_info->announcement_info->announce_success = false; 00803 thread_bootstrap_announcement_start(cur, cur->thread_info->announcement_info->channel_page, cur->thread_info->announcement_info->channel, 3, cur->thread_info->announcement_info->period); 00804 } 00805 00806 void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period) 00807 { 00808 if (!cur->thread_info->announcement_info ) { 00809 cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t)); 00810 } 00811 if (!cur->thread_info->announcement_info ) { 00812 return; 00813 } 00814 tr_info("Start announcement ch: %d",channel); 00815 cur->thread_info->announcement_info->channel = channel; 00816 cur->thread_info->announcement_info->period = period; 00817 cur->thread_info->announcement_info->channel_page = channel_page; 00818 cur->thread_info->announcement_info->count = count; 00819 cur->thread_info->announcement_info->timer = NULL; 00820 cur->thread_info->announcement_info->announce_success = false; 00821 cur->thread_info->announcement_info->timestamp = 0; 00822 thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00823 } 00824 void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp) 00825 { 00826 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 00827 00828 if (!linkConfiguration) { 00829 tr_error("No link configuration!"); 00830 return; 00831 } 00832 00833 tr_debug("Attach to new channel %u", channel); 00834 00835 /* 00836 * Save the old info and make a timer to announce it to old channels once if attachment is succesfull 00837 * When we receive attach fail 00838 */ 00839 if (!cur->thread_info->announcement_info ) { 00840 cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t)); 00841 } 00842 if (!cur->thread_info->announcement_info ) { 00843 return; 00844 } 00845 cur->thread_info->announcement_info->channel = linkConfiguration->rfChannel; 00846 cur->thread_info->announcement_info->channel_page = linkConfiguration->channel_page; 00847 cur->thread_info->announcement_info->panid = linkConfiguration->panId; 00848 cur->thread_info->announcement_info->count = 1; 00849 cur->thread_info->announcement_info->period = 1000; 00850 cur->thread_info->announcement_info->timestamp = timestamp; 00851 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb,20000, cur); 00852 // TODO check timer value 00853 cur->thread_info->announcement_info->announce_success = true; 00854 linkConfiguration->channel_page = channel_page; 00855 linkConfiguration->rfChannel = channel; 00856 linkConfiguration->panId = panid; 00857 thread_joiner_application_link_configuration_store(cur->id, linkConfiguration); 00858 thread_bootstrap_reset_restart(cur->id); 00859 } 00860 00861 static const trickle_params_t thread_mpl_data_trickle_params = 00862 { 00863 .Imin = 1, /* 50ms */ 00864 .Imax = 2, /* 100ms */ 00865 .k = 0, 00866 .TimerExpirations = 2 /* MPL core knows to suppress to 0 for non-routers */ 00867 }; 00868 00869 static const trickle_params_t thread_mpl_control_trickle_params = 00870 { 00871 .Imin = 11, 00872 .Imax = 5 * 60 * 20, 00873 .k = 0, 00874 .TimerExpirations = 0 00875 }; 00876 00877 void thread_interface_init(protocol_interface_info_entry_t *cur) 00878 { 00879 thread_discovery_reset(cur->id); 00880 thread_routing_set_mesh_callbacks(cur); 00881 thread_dhcp_client_init(cur->id); 00882 thread_management_client_init(cur->id); 00883 thread_address_registration_init(); 00884 cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT; 00885 cur->mpl_seed_set_entry_lifetime = 90; 00886 cur->mpl_proactive_forwarding = true; 00887 cur->mpl_control_trickle_params = thread_mpl_control_trickle_params; 00888 cur->mpl_data_trickle_params = thread_mpl_data_trickle_params; 00889 cur->mpl_seed = true; 00890 cur->mpl_treat_realm_domains_as_one = true; 00891 cur->if_ns_transmit = thread_nd_ns_transmit; 00892 cur->if_special_forwarding = thread_nd_special_forwarding; 00893 cur->if_snoop = thread_nd_snoop; 00894 cur->if_icmp_handler = thread_nd_icmp_handler; 00895 cur->ipv6_neighbour_cache.send_nud_probes = false; 00896 cur->ipv6_neighbour_cache.recv_addr_reg = true; 00897 cur->send_mld = false; 00898 cur->ip_multicast_as_mac_unicast_to_parent = true; 00899 if (!cur->thread_info->routerShortAddress) { 00900 cur->thread_info->routerShortAddress = 0xfffe; 00901 } 00902 if (cur->thread_info->thread_attach_scanned_parent) { 00903 mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id); 00904 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 00905 cur->thread_info->thread_attach_scanned_parent = NULL; 00906 } 00907 //Disable Always RPL 00908 rpl_control_remove_domain_from_interface(cur); 00909 mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL); 00910 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_NODES); 00911 cur->nwk_nd_re_scan_count = 5; 00912 00913 } 00914 00915 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur) 00916 { 00917 thread_routing_reset(&cur->thread_info->routing); 00918 mac_helper_mac16_address_set(cur, 0xffff); 00919 00920 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) { 00921 tr_debug("Set ASPIRING Router Mode"); 00922 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_ROUTER; 00923 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 00924 } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST && 00925 cur->thread_info->end_device_link_synch ) { 00926 tr_debug("Set FED Mode"); 00927 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_FULL_END_DEVICE; 00928 } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) { 00929 tr_debug("Set ASPIRING Sleepy Host Mode"); 00930 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE; 00931 //SET Sleepy Host To RX on Idle mode for bootsrap 00932 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 00933 cur->thread_info->childUpdateReqTimer = 0.8 * cur->thread_info->host_link_timeout; 00934 } else { 00935 tr_debug("Set End node Mode"); 00936 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE; 00937 } 00938 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 00939 } 00940 00941 int8_t thread_bootsrap_event_trig(thread_bootsrap_event_type_e event_type, int8_t Id, arm_library_event_priority_e priority) 00942 { 00943 arm_event_s event = { 00944 .receiver = Id, 00945 .sender = 0, 00946 .event_type = event_type, 00947 .priority = priority, 00948 }; 00949 return eventOS_event_send(&event); 00950 } 00951 00952 void thread_bootstrap_reset_restart(int8_t interface) 00953 { 00954 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); 00955 if (!cur) { 00956 return; 00957 } 00958 00959 if (cur->nwk_bootstrap_state == ER_MLE_SYNCH) { 00960 thread_network_synch_data_free(cur->id); 00961 } 00962 thread_nd_service_disable(interface); 00963 thread_routing_deactivate(&cur->thread_info->routing); 00964 //TODO: clear CoAP resending queue 00965 thread_bootsrap_event_trig(THREAD_BOOTSTRAP_RESET, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00966 } 00967 00968 void thread_tasklet(arm_event_s *event) 00969 { 00970 00971 protocol_interface_info_entry_t *cur = 0; 00972 thread_bootsrap_event_type_e event_type; 00973 event_type = (thread_bootsrap_event_type_e)event->event_type; 00974 cur = protocol_stack_interface_info_get_by_bootstrap_id(event->receiver); 00975 if (!cur) { 00976 tr_debug("Thread task unknown"); 00977 return; 00978 } 00979 00980 switch (event_type) { 00981 case THREAD_INIT_EVENT: 00982 tr_debug_extra("Thread SM THREAD_INIT_EVENT"); 00983 tr_debug("Thread task Init"); 00984 break; 00985 00986 case THREAD_BOOTSTRAP_RESET: 00987 //Reset Current Thread state 00988 tr_debug_extra("Thread SM THREAD_BOOTSTRAP_RESET"); 00989 if (thread_bootstrap_reset(cur) == 0) { 00990 tr_debug("Thread Attached"); 00991 } else { 00992 tr_debug("Stop Bootsrap and send event"); 00993 } 00994 break; 00995 00996 case THREAD_ATTACH_READY: 00997 tr_debug_extra("Thread SM THREAD_ATTACH_READY"); 00998 thread_bootstrap_attached_finish(cur); 00999 break; 01000 case THREAD_ATTACH_UPGRADE_REED: 01001 tr_debug_extra("Thread SM THREAD_ATTACH_UPGRADE_REED"); 01002 if (thread_router_bootstrap_child_count_get(cur) > 0) { 01003 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_PARENT_PARTITION_CHANGE); 01004 } else { 01005 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_TOO_FEW_ROUTERS); 01006 } 01007 01008 break; 01009 01010 case THREAD_ATTACH_DOWNGRADE_ROUTER: 01011 tr_debug_extra("Thread SM THREAD_ATTACH_DOWNGRADE_ROUTER"); 01012 thread_bootstrap_attach_start(cur->id, THREAD_REATTACH_REED); 01013 break; 01014 01015 case THREAD_ATTACH_ACTIVE_ROUTER: 01016 tr_debug_extra("Thread SM THREAD_ATTACH_ACTIVE_ROUTER"); 01017 thread_bootstrap_all_nodes_multicast_register(cur); 01018 thread_router_bootstrap_anycast_address_register(cur); 01019 thread_router_bootstrap_active_router_attach(cur); 01020 thread_bootstrap_child_id_request(cur); 01021 if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) { 01022 // publish our services to allow leader to remove old ones 01023 thread_border_router_publish(cur->id); 01024 } 01025 thread_router_bootstrap_address_change_notify_send(cur); 01026 // Validate network data after a short period 01027 thread_border_router_resubmit_timer_set(cur->id, 5); 01028 break; 01029 case THREAD_ATTACH_ROUTER_ID_GET_FAIL: 01030 tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_GET_FAIL"); 01031 tr_debug("Thread Router Id request Fail"); 01032 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01033 cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 01034 thread_router_bootstrap_child_information_clear(cur); 01035 thread_router_bootstrap_reed_advertisements_start(cur); 01036 thread_router_bootstrap_child_id_reject(cur); 01037 break; 01038 01039 case THREAD_ATTACH_ROUTER_ID_RELEASED: 01040 tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_RELEASED"); 01041 if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) { 01042 // publish our services to allow leader to remove old ones 01043 thread_border_router_publish(cur->id); 01044 } 01045 break; 01046 01047 case THREAD_CHILD_ID_REQUEST: 01048 tr_debug_extra("Thread SM THREAD_CHILD_ID_REQUEST"); 01049 thread_router_bootstrap_child_id_handler(cur); 01050 break; 01051 01052 case THREAD_CHILD_UPDATE: 01053 tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); 01054 if (thread_info(cur)->thread_endnode_parent) { 01055 thread_host_bootstrap_child_update(cur->id, cur->thread_info->thread_endnode_parent->mac64); 01056 } 01057 break; 01058 case THREAD_ANNOUNCE_ACTIVE: { 01059 tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); 01060 01061 if (cur->thread_info->announcement_info->count > 0) { 01062 cur->thread_info->announcement_info->count--; 01063 01064 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 01065 if (!linkConfiguration) { 01066 tr_error("No link configuration!"); 01067 break; 01068 } 01069 01070 // New timeout needed 01071 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_ntf_cb,cur->thread_info->announcement_info->period, cur); 01072 01073 // Send announce_ntf 01074 thread_bootstrap_announce_send(cur,linkConfiguration->channel_page,linkConfiguration->rfChannel,linkConfiguration->panId,linkConfiguration->timestamp, cur->thread_info->announcement_info->channel); 01075 } else { 01076 // Last call, delete announcement info 01077 ns_dyn_mem_free(cur->thread_info->announcement_info); 01078 cur->thread_info->announcement_info = NULL; 01079 } 01080 01081 break; 01082 } 01083 01084 default: 01085 break; 01086 } 01087 } 01088 01089 01090 int thread_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur) 01091 { 01092 if (cur->bootStrapId < 0) { 01093 cur->bootStrapId = eventOS_event_handler_create(&thread_tasklet, THREAD_INIT_EVENT); 01094 tr_debug("Allocate Thread Tasklet"); 01095 } 01096 if (cur->bootStrapId >= 0) { 01097 return 0; 01098 } 01099 return -1; 01100 } 01101 01102 int thread_proxy_validate(int8_t interface_id, uint8_t *addrerss) 01103 { 01104 ipv6_route_t *route; 01105 route = ipv6_route_choose_next_hop(addrerss, interface_id, NULL); 01106 if (!route) { 01107 return -1; 01108 } 01109 01110 if (route->prefix_len < 128 || !route->on_link) { 01111 return -1; 01112 } 01113 01114 return 0; 01115 } 01116 01117 void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) 01118 { 01119 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01120 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; 01121 01122 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 01123 cur->ip_multicast_as_mac_unicast_to_parent = false; 01124 cur->ip_forwarding = true; 01125 } else { 01126 cur->ip_multicast_as_mac_unicast_to_parent = true; 01127 cur->ip_forwarding = false; 01128 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01129 /* REED should be able to IP forward */ 01130 cur->ip_forwarding = true; 01131 } else { 01132 cur->ip_forwarding = false; 01133 } 01134 } 01135 01136 tr_info("Set forwarding: ip=%d, multicast=%d", cur->ip_forwarding, thread_i_am_router(cur)); 01137 01138 if (cur->ip_forwarding) { 01139 addr_add_router_groups(cur); 01140 } 01141 // Bizarrely, Thread needs Realm-All-Routers active in FEDs for address resolution 01142 if (cur->ip_forwarding || cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 01143 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS); 01144 } 01145 01146 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01147 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) { 01148 thread_router_bootstrap_reed_advertisements_start(cur); 01149 } 01150 01151 thread_bootstrap_mac_activate(cur, cur->mac_parameters->mac_channel, cur->mac_parameters->pan_id, true); 01152 01153 if (nd_proxy_downstream_interface_register(cur->id,thread_proxy_validate , thread_bbr_proxy_state_update) != 0) { 01154 tr_debug("mesh proxy register fail"); 01155 } 01156 } 01157 01158 if (cur->thread_info->leader_private_data) { 01159 // Generate network data from network data structures 01160 thread_leader_service_generate_network_data(cur); 01161 } 01162 01163 cur->bootsrap_state_machine_cnt = 0; 01164 mac_data_poll_protocol_poll_mode_decrement(cur); 01165 } 01166 01167 void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur) 01168 { 01169 mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id); 01170 01171 ns_list_foreach_safe(mle_neigh_table_entry_t, cur_entry, neig_list) { 01172 if (!thread_addr_is_equal_or_child(cur->thread_info->routerShortAddress, cur_entry->short_adr)) { 01173 tr_debug("Free ID %x", cur_entry->short_adr); 01174 mle_class_remove_entry(cur->id, cur_entry); 01175 } 01176 } 01177 } 01178 01179 void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur) 01180 { 01181 uint8_t static_address[16]; 01182 //Delete old ULA16 01183 memcpy(static_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01184 memcpy(&static_address[8], ADDR_SHORT_ADR_SUFFIC, 6); 01185 common_write_16_bit(mac_helper_mac16_address_get(cur), &static_address[14]); 01186 addr_delete(cur, static_address); 01187 mac_helper_mac16_address_set(cur, 0xffff); 01188 01189 } 01190 01191 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state) 01192 { 01193 01194 protocol_interface_info_entry_t *cur; 01195 01196 cur = protocol_stack_interface_info_get_by_id(interface_id); 01197 if (!cur || !cur->thread_info) { 01198 return -1; 01199 } 01200 //Trigger the bootstrap 01201 01202 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01203 01204 switch (state) { 01205 case THREAD_NORMAL_ATTACH: 01206 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01207 mac_helper_default_security_level_set(cur, cur->mac_parameters->mac_configured_sec_level); 01208 mac_helper_default_security_key_id_mode_set(cur,MAC_KEY_ID_MODE_IDX); 01209 break; 01210 01211 case THREAD_REATTACH: 01212 tr_debug("Thread ReAttach"); 01213 //save the current partition id and sequence number before trying reattach 01214 cur->thread_info->previous_partition_info.partitionId = cur->thread_info->thread_leader_data->partitionId; 01215 cur->thread_info->previous_partition_info.weighting = cur->thread_info->thread_leader_data->weighting; 01216 cur->thread_info->previous_partition_info.idSequence = cur->thread_info->routing.router_id_sequence; 01217 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01218 if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY){ 01219 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH; 01220 } 01221 break; 01222 case THREAD_PARTITION_MERGE: 01223 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01224 break; 01225 case THREAD_ANY_ATTACH: 01226 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01227 cur->thread_info->thread_attached_state = THREAD_STATE_ATTACH_ANY; 01228 break; 01229 01230 case THREAD_REATTACH_REED: 01231 cur->thread_info->releaseRouterId = true; 01232 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01233 01234 if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY){ 01235 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH; 01236 } 01237 break; 01238 } 01239 01240 // Set RX on idle 01241 thread_end_device_mode_set(cur, false); 01242 cur->nwk_nd_re_scan_count = 0; 01243 cur->nwk_bootstrap_state = ER_SCAN; 01244 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 10); 01245 return 0; 01246 } 01247 01248 static void thread_bootsrap_network_discovery_failure(int8_t interface_id) 01249 { 01250 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01251 if (!cur || !cur->thread_info) { 01252 return; 01253 } 01254 //TODO we should send 3 in burst of 0.1 - 0.6 seconds and then do the exponential backup of 5s -- 80s 01255 uint32_t backof_delay = cur->nwk_nd_re_scan_count*2; 01256 if (backof_delay > 600) backof_delay = 600; //TODO test this and check guess this is 100ms ticks 01257 01258 tr_debug("Continue network scan"); 01259 cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01260 cur->bootsrap_state_machine_cnt = backof_delay + randLIB_get_random_in_range(1, 6); 01261 } 01262 01263 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur) 01264 { 01265 if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH) { 01266 tr_debug("ReAttach Fail - retry"); 01267 thread_bootstrap_attach_start(cur->id, THREAD_REATTACH); 01268 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH_RETRY; 01269 } 01270 else if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY) { 01271 tr_warn("ReAttach Fail"); 01272 thread_bootstrap_attach_start(cur->id, THREAD_ANY_ATTACH); 01273 } else { 01274 if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) { 01275 bootsrap_next_state_kick(ER_BOOTSTRAP_LEADER_UP, cur); 01276 } else { 01277 bootsrap_next_state_kick(ER_BOOTSTRAP_NEW_FRAGMENT_START, cur); 01278 } 01279 } 01280 } 01281 static int8_t thread_bootstrap_attempt_attach_with_pending_set(protocol_interface_info_entry_t *cur) 01282 { 01283 tr_debug("Attempting to attach with pending set"); 01284 uint32_t pending_delay_timer = thread_joiner_application_pending_config_timeout_get(cur->id); 01285 if (pending_delay_timer > 0 && thread_joiner_application_pending_delay_timer_in_sync(cur->id)) { 01286 tr_debug("We have a pending delay timer running"); 01287 //we already have a pending set that can be activated so return 01288 return -1; 01289 } 01290 01291 if (!thread_joiner_application_pending_config_exists(cur->id)) { 01292 tr_debug("no pending configuration found after reset"); 01293 return -1; 01294 } 01295 01296 if (thread_joiner_application_old_config_exists(cur->id)){ 01297 //there is an existing old configuration so attempt to attach with it and set the pending timer to expire 01298 thread_joiner_application_old_config_activate(cur->id); 01299 thread_joiner_application_old_config_delete(cur->id); 01300 thread_joiner_application_pending_config_enable(cur->id,20000); 01301 } 01302 else { 01303 thread_joiner_pending_config_activate(cur->id); 01304 } 01305 01306 return 0; 01307 } 01308 01309 static void thread_bootstrap_orphan_scan_ready_cb(struct protocol_interface_info_entry *cur_interface, announce_discovery_response_t *discover_response) { 01310 01311 if (!discover_response) { 01312 thread_bootstrap_orphan_scan_start(cur_interface); 01313 return; 01314 } 01315 01316 link_configuration_s *link_configuration = thread_joiner_application_get_config(cur_interface->id); 01317 01318 if (!link_configuration) { 01319 tr_debug("no link configuration found after reset"); 01320 return; 01321 } 01322 01323 tr_debug("New configuration received channel %u, %x", discover_response->channel, discover_response->pan_id); 01324 link_configuration->panId = discover_response->pan_id; 01325 link_configuration->rfChannel = discover_response->channel; 01326 link_configuration->channel_page = 0; 01327 cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01328 cur_interface->bootsrap_state_machine_cnt = 1; 01329 ns_dyn_mem_free(discover_response); 01330 } 01331 01332 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur) 01333 { 01334 thread_announce_discover_reques_t scan_req; 01335 //default channel mask for channels 11 to 26 01336 scan_req.channel_mask = 0x001fffe0; 01337 #ifdef THREAD_THCI_SUPPORT 01338 //use active operational dataset's channel mask if available 01339 link_configuration_s *link_configuration = thread_joiner_application_get_config(cur->id); 01340 if (!link_configuration) { 01341 return; 01342 } 01343 scan_req.channel_mask = common_read_32_bit(link_configuration->channel_mask); 01344 //the current channel is added to the mask. 01345 scan_req.channel_mask |= (0x80000000 >> link_configuration->rfChannel); 01346 #endif 01347 scan_req.pan_id = cur->mac_parameters->pan_id; 01348 scan_req.active_timestamp = 0; 01349 scan_req.active_timestamp |= MESHCOP_TLV_ACTIVE_TIME_STAMP_U_BIT; 01350 01351 if (thread_discovery_announce_network_scan(cur->id, &scan_req, thread_bootstrap_orphan_scan_ready_cb) != 0) { 01352 01353 tr_debug("announce discover start fail"); 01354 thread_bootstrap_attach_start(cur->id, THREAD_NORMAL_ATTACH); 01355 } else { 01356 tr_debug("Orphan Host start announce scan"); 01357 } 01358 return; 01359 } 01360 01361 void thread_bootstrap_connection_error(int8_t interface_id, nwk_connect_error_types errorType, uint8_t *LinkId) 01362 { 01363 (void)LinkId; 01364 protocol_interface_info_entry_t *cur; 01365 01366 switch (errorType) { 01367 case CON_ERROR_POLL: 01368 case CON_PARENT_CONNECT_DOWN: 01369 thread_bootstrap_reset_restart(interface_id); 01370 break; 01371 01372 case CON_ERROR_LINK_TX_FAIL: 01373 //thread_mle_challenge_trig(interface_id,LinkId); 01374 break; 01375 01376 case CON_ERROR_NETWORK_ATTACH_FAIL: 01377 cur = protocol_stack_interface_info_get_by_id(interface_id); 01378 if (!cur || !cur->thread_info) { 01379 break; 01380 } 01381 if (thread_bootstrap_attempt_attach_with_pending_set(cur) == 0) { 01382 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH); 01383 break; 01384 } 01385 01386 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timer && 01387 cur->thread_info->announcement_info->announce_success) { 01388 // Attachment to announce failed we return to previous channel 01389 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 01390 01391 if (linkConfiguration) { 01392 linkConfiguration->rfChannel = cur->thread_info->announcement_info->channel; 01393 linkConfiguration->channel_page = cur->thread_info->announcement_info->channel_page; 01394 linkConfiguration->panId = cur->thread_info->announcement_info->panid; 01395 thread_joiner_application_link_configuration_store(cur->id, linkConfiguration); 01396 } else { 01397 tr_error("No link configuration!"); 01398 } 01399 //set announce success flag to false because attach to new channel failed 01400 cur->thread_info->announcement_info->announce_success = false; 01401 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH); 01402 01403 break; 01404 } 01405 01406 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER){ 01407 if (!thread_router_bootstrap_routing_allowed(cur)) { 01408 thread_discovery_responser_enable(cur->id, false); 01409 thread_bootstrap_orphan_scan_start(cur); 01410 } else { 01411 thread_bootstrap_generate_leader_and_link(cur); 01412 } 01413 } 01414 else { 01415 thread_bootstrap_orphan_scan_start(cur); 01416 } 01417 break; 01418 01419 case CON_ERROR_NO_THREAD_NETWORK_AVAILABLE: 01420 thread_bootsrap_network_discovery_failure(interface_id); 01421 break; 01422 case CON_ERROR_PARTITION_MERGE: 01423 thread_bootstrap_attach_start(interface_id, THREAD_PARTITION_MERGE); 01424 break; 01425 case CON_ERROR_NETWORK_REATTACH: 01426 thread_bootstrap_attach_start(interface_id, THREAD_REATTACH); 01427 break; 01428 case CON_ERROR_NEIGHBOR_UNREACHABLE: 01429 01430 break; 01431 case CON_ERROR_NETWORK_KICK: 01432 thread_bootstrap_reset_restart(interface_id); 01433 break; 01434 } 01435 } 01436 01437 void thread_interface_up(protocol_interface_info_entry_t *cur) 01438 { 01439 thread_interface_init(cur); 01440 thread_interface_bootsrap_mode_init(cur); 01441 cur->nwk_nd_re_scan_count = 0; 01442 } 01443 01444 int thread_bootstrap_reset(protocol_interface_info_entry_t *cur) 01445 { 01446 if (!cur || !cur->thread_info || (cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) { 01447 return -1; 01448 } 01449 01450 if (cur->thread_info->thread_endnode_parent) { 01451 ns_dyn_mem_free(cur->thread_info->thread_endnode_parent); 01452 cur->thread_info->thread_endnode_parent = NULL; 01453 } 01454 01455 neighbor_cache_flush(&cur->neigh_cache); 01456 thread_bootstrap_stop(cur); 01457 #ifndef NO_MLE 01458 mle_class_list_clean(cur->id); 01459 #endif 01460 cur->bootsrap_state_machine_cnt = 0; 01461 mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params); 01462 //tr_debug( "--> idle"); 01463 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 01464 rpl_control_remove_domain_from_interface(cur); 01465 protocol_core_interface_info_reset(cur); 01466 mac_data_poll_disable(cur); 01467 01468 //Prepare start Again 01469 01470 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; //Set Active Bootsrap 01471 cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; //Clear Bind 01472 protocol_6lowpan_interface_common_init(cur); 01473 addr_interface_set_ll64(cur, NULL); 01474 thread_interface_up(cur); 01475 01476 cur->nwk_mode = ARM_NWK_GP_IP_MODE; 01477 cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01478 cur->nwk_nd_re_scan_count = 0; 01479 if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY) { 01480 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01481 } 01482 cur->ipv6_neighbour_cache.send_nud_probes = false; //Disable NUD probing 01483 cur->ip_multicast_as_mac_unicast_to_parent = true; 01484 //Define Default Contexts 01485 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 01486 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01487 } 01488 thread_anycast_address_policy_update(cur->thread_info, true); 01489 thread_bootstrap_state_machine(cur); 01490 return 0; 01491 } 01492 01493 void thread_generate_ml64_address(protocol_interface_info_entry_t *cur) 01494 { 01495 if_address_entry_t *def_address = NULL; 01496 uint8_t ula[16]; 01497 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01498 //GENERATE ML-EID64 01499 memcpy(&ula[8], cur->iid_slaac , 8); 01500 def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true); 01501 if (def_address) { 01502 tr_debug("Generated UL64: %s", trace_ipv6(ula)); 01503 } 01504 } 01505 01506 void thread_delete_ml64_address(protocol_interface_info_entry_t *cur) 01507 { 01508 uint8_t ula[16]; 01509 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01510 memcpy(&ula[8], cur->iid_slaac, 8); 01511 addr_delete(cur, ula); 01512 01513 } 01514 01515 void thread_generate_ml16_address(protocol_interface_info_entry_t *cur) 01516 { 01517 if_address_entry_t *def_address = NULL; 01518 uint8_t ula[16]; 01519 uint16_t euid16 = mac_helper_mac16_address_get(cur); 01520 if (euid16 == 0xffff) { // Safe guard 01521 tr_debug("Do NOT generate ML16, mac16=%u", euid16); 01522 return; 01523 } 01524 //GENERATE ML-16 01525 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01526 memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6); 01527 common_write_16_bit(euid16, &ula[14]); 01528 01529 def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true); 01530 if (def_address) { 01531 tr_debug("Generated ML16: %s", trace_ipv6(ula)); 01532 cur->global_address_available = true; 01533 } 01534 } 01535 01536 void thread_delete_ml16_addresses(protocol_interface_info_entry_t *cur) 01537 { 01538 uint8_t ula[16] = {0}; 01539 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01540 memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6); 01541 addr_delete_matching(cur, ula, 112, ADDR_SOURCE_UNKNOWN); 01542 } 01543 01544 void thread_bootstrap_update_ml16_address(protocol_interface_info_entry_t *cur, uint16_t mac16) 01545 { 01546 thread_delete_ml16_addresses(cur); 01547 mac_helper_mac16_address_set(cur, mac16); 01548 thread_generate_ml16_address(cur); 01549 thread_router_bootstrap_anycast_address_register(cur); 01550 } 01551 static void thread_meshlocal_route_set(protocol_interface_info_entry_t *cur) 01552 { 01553 cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE; 01554 if (ipv6_route_add(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64, cur->id, NULL, ROUTE_THREAD, 0xffffffff, 0) == NULL) { 01555 tr_error("fail to add route"); 01556 } 01557 } 01558 01559 void thread_bootstrap_attached_ready(protocol_interface_info_entry_t *cur) 01560 { 01561 thread_bootsrap_event_trig(THREAD_ATTACH_READY, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01562 } 01563 01564 void thread_bootstrap_attached_downgrade_router(protocol_interface_info_entry_t *cur) 01565 { 01566 thread_bootsrap_event_trig(THREAD_ATTACH_DOWNGRADE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01567 } 01568 01569 void thread_bootstrap_attched_upgrade_reed(protocol_interface_info_entry_t *cur) 01570 { 01571 thread_bootsrap_event_trig(THREAD_ATTACH_UPGRADE_REED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01572 } 01573 01574 void thread_bootstrap_attached_active_router(protocol_interface_info_entry_t *cur) 01575 { 01576 thread_bootsrap_event_trig(THREAD_ATTACH_ACTIVE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01577 } 01578 01579 void thread_bootstrap_router_id_release_ready(protocol_interface_info_entry_t *cur) 01580 { 01581 thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_RELEASED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01582 } 01583 01584 void thread_bootstrap_router_id_get_fail(protocol_interface_info_entry_t *cur) 01585 { 01586 thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_GET_FAIL, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01587 } 01588 01589 int8_t thread_bootstrap_child_id_request(protocol_interface_info_entry_t *cur) 01590 { 01591 return thread_bootsrap_event_trig(THREAD_CHILD_ID_REQUEST, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01592 } 01593 01594 void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur) 01595 { 01596 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE || 01597 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01598 thread_meshlocal_route_set(cur); 01599 thread_extension_route_set(cur); 01600 // FEDs and routers (REEDs) perform their own address resolution 01601 thread_nd_service_activate(cur->id); 01602 } else { 01603 thread_child_set_default_route(cur); 01604 } 01605 } 01606 01607 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) 01608 { 01609 cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 01610 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; 01611 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 01612 cur->bootsrap_state_machine_cnt = 10; 01613 cur->thread_info->routerIdReqCoapID = 0; 01614 cur->thread_info->networkDataRequested = false; 01615 clear_power_state(ICMP_ACTIVE); 01616 01617 //Free scanned Result 01618 if (cur->thread_info->thread_attach_scanned_parent) { 01619 mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id); 01620 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 01621 cur->thread_info->thread_attach_scanned_parent = NULL; 01622 } 01623 01624 // Make local/nwk data check after 5s 01625 thread_border_router_resubmit_timer_set(cur->id, 5); 01626 //Generate UL16 01627 thread_generate_ml16_address(cur); 01628 //GENERATE ML-EID64 01629 thread_generate_ml64_address(cur); 01630 // Generate new domain address 01631 thread_extension_address_generate(cur); 01632 thread_bootstrap_routing_activate(cur); 01633 thread_bootstrap_network_data_update(cur); 01634 // After successful attach if there is announcement info present, send announcement back to previous channel 01635 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->announce_success == false) { 01636 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb,20000, cur); 01637 } 01638 thread_configuration_mle_activate(cur); 01639 01640 if (cur->thread_info->releaseRouterId) { 01641 thread_router_bootstrap_router_id_release(cur); 01642 } 01643 uint8_t *parent_mac_addr = NULL; 01644 if (cur->thread_info->thread_endnode_parent) { 01645 parent_mac_addr = cur->thread_info->thread_endnode_parent->mac64; 01646 } 01647 thread_nvm_store_link_info_write(parent_mac_addr, mac_helper_mac16_address_get(cur)); 01648 thread_bootstrap_ready(cur); 01649 01650 if(thread_is_router_addr(mac_helper_mac16_address_get(cur))) { 01651 // Attached as router Trigger routter attach 01652 tr_info("Attaching directly to router"); 01653 thread_bootstrap_attached_active_router(cur); 01654 } 01655 } 01656 01657 //This function is for Thread Parent scan callback 01658 bool thread_network_data_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 01659 { 01660 protocol_interface_info_entry_t *cur; 01661 (void)msgId; 01662 01663 cur = protocol_stack_interface_info_get_by_id(interface_id); 01664 if (!cur || !cur->thread_info) { 01665 return false; 01666 } 01667 01668 /* If network data is not received, send again */ 01669 if(thread_info(cur)->networkDataRequested && !usedAllRetries){ 01670 return true; 01671 } 01672 01673 if(cur->thread_info->leader_synced) { 01674 if(usedAllRetries) { 01675 // could not learn network data from neighbour, everyone must reregister 01676 cur->thread_info->leader_synced = false; 01677 thread_leader_service_network_data_changed(cur,true,true); 01678 return false; 01679 } else { 01680 tr_debug("retrying as leader data not yet synced"); 01681 return true; 01682 } 01683 } 01684 01685 // if REED fails to get updated network data, it reattaches 01686 if (thread_info(cur)->networkDataRequested && !thread_attach_active_router(cur) && usedAllRetries) { 01687 thread_bootstrap_reset_restart(interface_id); 01688 } 01689 01690 thread_info(cur)->networkDataRequested = false; 01691 mac_data_poll_protocol_poll_mode_decrement(cur); 01692 return false; 01693 } 01694 01695 01696 bool thread_tlv_request(int8_t interface_id, uint8_t *address, bool delayed_message, uint8_t *req_tlv, uint8_t req_len) 01697 { 01698 mle_message_timeout_params_t timeout; 01699 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01700 uint16_t buf_id; 01701 01702 buf_id = mle_service_msg_allocate(interface_id, 32 + 20 + thread_leader_data_tlv_size(cur), false,MLE_COMMAND_DATA_REQUEST); 01703 01704 if (!cur || buf_id == 0) { 01705 return false; 01706 } 01707 01708 uint8_t *ptr = mle_service_get_data_pointer(buf_id); 01709 ptr = mle_tlv_req_tlv(ptr, req_tlv, req_len); 01710 01711 //SET Leader Data 01712 ptr = thread_leader_data_tlv_write(ptr, cur); 01713 01714 ptr = thread_active_timestamp_write(cur, ptr); 01715 01716 ptr = thread_pending_timestamp_write(cur, ptr); 01717 01718 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 01719 tr_debug("Buffer overflow at message write"); 01720 } 01721 timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; 01722 timeout.timeout_init = 1; 01723 timeout.timeout_max = 3; 01724 if (delayed_message) { 01725 timeout.delay = MLE_STANDARD_RESPONSE_DELAY; 01726 } else { 01727 timeout.delay = MLE_NO_DELAY; 01728 } 01729 mac_data_poll_init_protocol_poll(cur); 01730 mle_service_set_packet_callback(buf_id, thread_network_data_timeout); 01731 mle_service_set_msg_destination_address(buf_id, address); 01732 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 01733 //Set Security 01734 uint32_t keySequence; 01735 thread_management_get_current_keysequence(cur->id, &keySequence); 01736 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 01737 mle_service_send_message(buf_id); 01738 return true; 01739 } 01740 01741 void thread_bootstrap_parent_network_data_request(protocol_interface_info_entry_t *cur, bool delay_request) 01742 { 01743 uint8_t dst_address[16]; 01744 memcpy(dst_address, ADDR_LINK_LOCAL_PREFIX, 8); 01745 memcpy(&dst_address[8], thread_info(cur)->thread_endnode_parent->mac64, 8); 01746 dst_address[8] ^= 2; 01747 thread_network_data_request_send(cur, dst_address, delay_request); 01748 } 01749 01750 void thread_parent_scan(protocol_interface_info_entry_t *cur) 01751 { 01752 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01753 cur->nwk_nd_re_scan_count = 0; 01754 cur->nwk_bootstrap_state = ER_SCAN; 01755 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(5, 15); 01756 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01757 } 01758 01759 void thread_bootstrap_joiner_application_commission_done_cb(int8_t interface_id) 01760 { 01761 protocol_interface_info_entry_t *interface; 01762 interface = protocol_stack_interface_info_get_by_id(interface_id); 01763 if (!interface) { 01764 return; 01765 } 01766 tr_debug("Commission Ready trig bootsrap to starting from init again"); 01767 interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01768 interface->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 4); 01769 } 01770 01771 static int compare_steering_and_joiner_bloom(uint8_t *steering_bloom, uint8_t *joiner_bloom, uint8_t steering_tlv_length) 01772 { 01773 //make sure s bit is not checked 01774 int loop_iterator; 01775 tr_debug("joiner bloom : %s", trace_array(joiner_bloom, steering_tlv_length)); 01776 tr_debug("steering bloom : %s", trace_array(steering_bloom, steering_tlv_length)); 01777 for (loop_iterator = 0; loop_iterator < steering_tlv_length; loop_iterator++) 01778 { 01779 if ((joiner_bloom[loop_iterator] != (joiner_bloom[loop_iterator] & steering_bloom[loop_iterator]))) 01780 { 01781 thci_trace("joinerDiscoveryFailedFiltered"); 01782 return 0; 01783 } 01784 } 01785 return 1; 01786 } 01787 01788 static bool thread_route_possible_add(thread_attach_device_mode_e threadMode) 01789 { 01790 bool addRoute; 01791 if (threadMode == THREAD_DEVICE_MODE_ROUTER || 01792 threadMode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 01793 addRoute = true; 01794 } else { 01795 addRoute = false; 01796 } 01797 01798 return addRoute; 01799 } 01800 01801 static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) 01802 { 01803 if (register_status) { 01804 tr_debug("Get Address %s From %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); 01805 } else { 01806 tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); 01807 if (prefix && dhcp_addr) { 01808 tr_debug("Delete Current Server data"); 01809 thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix); 01810 //TODO shuold we try again or select new Server 01811 } 01812 } 01813 } 01814 01815 bool thread_dhcpv6_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list) 01816 { 01817 bool addressReady = false; 01818 ns_list_foreach(if_address_entry_t, entry, list) { 01819 if (memcmp(entry->address, prefixPtr, 8) == 0) { 01820 addressReady = true; 01821 break; 01822 } 01823 } 01824 return addressReady; 01825 } 01826 01827 static int thread_bloom_and_compare(uint8_t *steering_data_ptr,uint8_t steering_data_length,uint8_t *eui64, uint8_t eui64_length) 01828 { 01829 if (steering_data_length == 0 || steering_data_length > 16) { 01830 return 0; 01831 } 01832 01833 uint8_t joiner_bloom_calculated[16] = {0}; 01834 uint8_t mac_extended_address[8]; 01835 01836 ns_sha256_nbits(eui64, eui64_length, mac_extended_address, 64); 01837 mac_extended_address[0] |= 2; //local administered bit is set 01838 01839 thread_beacon_calculate_bloom_filter(joiner_bloom_calculated,steering_data_length,mac_extended_address,8); 01840 01841 return compare_steering_and_joiner_bloom(steering_data_ptr, joiner_bloom_calculated,steering_data_length); 01842 } 01843 01844 static void thread_network_select_by_steering_data(device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response) 01845 { 01846 ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) { 01847 01848 if (!thread_bloom_and_compare(cur_class->steering_data, cur_class->steering_data_valid, device_configuration_ptr->eui64,8) ) { 01849 ns_list_remove(discover_response, cur_class); 01850 ns_dyn_mem_free(cur_class); 01851 } 01852 01853 } 01854 } 01855 01856 static void thread_network_select(struct protocol_interface_info_entry *interface_ptr, device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response) 01857 { 01858 (void) interface_ptr; 01859 01860 discovery_response_list_t *discovered_network_ptr = thread_extension_bootstrap_network_select(interface_ptr, discover_response); 01861 01862 /* If network found */ 01863 if (discovered_network_ptr) { 01864 /* Clear other networks from list */ 01865 ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) { 01866 if (cur_class != discovered_network_ptr) { 01867 ns_list_remove(discover_response, cur_class); 01868 ns_dyn_mem_free(cur_class); 01869 } 01870 } 01871 } else { 01872 thread_network_select_by_steering_data(device_configuration_ptr, discover_response); 01873 } 01874 } 01875 01876 void thread_bootsrap_discovery_ready_cb(struct protocol_interface_info_entry *cur_interface, thread_nwk_discovery_response_list_t *discover_response) 01877 { 01878 device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id); 01879 if (!device_configuration_ptr) { 01880 tr_error("Mac scan confirm:Unknow Interface"); 01881 thci_trace("joinerDiscoveryFailedNoBeacon"); 01882 return; 01883 } 01884 01885 thread_network_select(cur_interface, device_configuration_ptr, discover_response); 01886 01887 if (!ns_list_count(discover_response)) { 01888 tr_debug("NO network available for scan"); 01889 thci_trace("joinerDiscoveryFailedNoBeacon"); 01890 goto exit_failure; 01891 } 01892 01893 cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01894 cur_interface->bootsrap_state_machine_cnt = 1; 01895 return; 01896 01897 01898 01899 exit_failure: 01900 01901 thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 01902 } 01903 01904 static void thread_bootstrap_create_unsecure_link_to_parent(protocol_interface_info_entry_t *interface, discovery_response_list_t *nwk_info) 01905 { 01906 mlme_start_t start_req; 01907 memset(&start_req, 0, sizeof(mlme_start_t)); 01908 01909 mac_helper_coordinator_address_set(interface, ADDR_802_15_4_LONG , nwk_info->extented_mac); 01910 01911 interface->mac_parameters->pan_id = nwk_info->pan_id; 01912 interface->mac_parameters->mac_channel = nwk_info->channel; 01913 01914 start_req.PANId = nwk_info->pan_id; 01915 start_req.LogicalChannel = nwk_info->channel; 01916 start_req.ChannelPage = 0; 01917 start_req.BeaconOrder = 0x0f; 01918 start_req.SuperframeOrder = 0x0f; 01919 //SET Beacon Payload 01920 mac_helper_beacon_payload_reallocate(interface, 0); 01921 interface->mac_api->mlme_req(interface->mac_api, MLME_START, (void*)&start_req); 01922 mac_data_poll_init(interface); 01923 mac_helper_mac16_address_set(interface, 0xffff); 01924 tr_debug("Mac Ready"); 01925 } 01926 01927 void thread_discover_native_commissioner_response(protocol_interface_info_entry_t *interface, thread_nwk_discovery_response_list_t *nwk_info) 01928 { 01929 thread_commissioning_link_configuration_s *config_ptr; 01930 int n = 0; 01931 if (ns_list_count(nwk_info) == 0) { 01932 tr_debug("Thread discover:No nwk"); 01933 goto exit_failure; 01934 } 01935 01936 // create list of available networks for native commissioner interface 01937 config_ptr = ns_dyn_mem_alloc(sizeof(thread_commissioning_link_configuration_s) * ns_list_count(nwk_info)); 01938 if(!config_ptr) { 01939 tr_debug("Mac scan confirm:out of resources"); 01940 goto exit_failure; 01941 } 01942 01943 ns_list_foreach(discovery_response_list_t, cur_class, nwk_info) { 01944 config_ptr[n].panId = cur_class->pan_id; 01945 config_ptr[n].Protocol_id = THREAD_PROTOCOL_ID; 01946 config_ptr[n].version = THREAD_PROTOCOL_VERSION; 01947 config_ptr[n].rfChannel = cur_class->channel; 01948 memcpy(config_ptr[n].name, cur_class->network_name, 16); 01949 memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8); 01950 n++; 01951 } 01952 01953 if(interface->thread_info->native_commissioner_cb) { 01954 interface->thread_info->native_commissioner_cb(interface->id,n,config_ptr); 01955 } 01956 ns_dyn_mem_free(config_ptr); 01957 01958 if(!interface->thread_info->native_commissioner_link) { 01959 tr_debug("Mac scan confirm:continue scanning"); 01960 goto exit_failure; 01961 } 01962 //Free if not matching network found 01963 ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) { 01964 if(cur_class->version != THREAD_PROTOCOL_VERSION || 01965 cur_class->pan_id != interface->thread_info->native_commissioner_link->panId || 01966 memcmp(interface->thread_info->native_commissioner_link->name,cur_class->network_name,16) != 0 || 01967 memcmp(interface->thread_info->native_commissioner_link->extented_pan_id,cur_class->extented_pan_id,8) != 0 ) { 01968 01969 ns_list_remove(nwk_info, cur_class); 01970 ns_dyn_mem_free(cur_class); 01971 01972 } 01973 } 01974 01975 if(ns_list_is_empty(nwk_info)) { 01976 tr_debug("Mac scan confirm:no networks available"); 01977 goto exit_failure; 01978 } 01979 //select best parent link 01980 discovery_response_list_t *best = NULL; 01981 01982 ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) { 01983 ns_list_remove(nwk_info, cur_class); 01984 if (!best || (best && best->dbm < cur_class->dbm)) { 01985 if (best) { 01986 ns_dyn_mem_free(cur_class); 01987 } 01988 best = cur_class; 01989 } else { 01990 ns_dyn_mem_free(cur_class); 01991 } 01992 } 01993 01994 // best is always not null, because the not empty check above 01995 /* coverity[FORWARD_NULL] */ 01996 interface->thread_info->native_commissioner_port = best->commissioner_port; 01997 thread_bootstrap_create_unsecure_link_to_parent(interface, best); 01998 ns_dyn_mem_free(best); 01999 02000 /** 02001 * we should stop scanning and saying that the interface is up 02002 */ 02003 tr_debug("Native commissioning interface ready"); 02004 interface->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 02005 interface->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 02006 interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; 02007 interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 02008 02009 interface->thread_info->routerIdReqCoapID = 0; 02010 interface->thread_info->networkDataRequested = false; 02011 02012 interface->bootsrap_state_machine_cnt = 10; 02013 02014 clear_power_state(ICMP_ACTIVE); 02015 thread_bootstrap_ready(interface); 02016 return; 02017 02018 02019 02020 exit_failure: 02021 02022 thread_bootstrap_connection_error(interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 02023 } 02024 02025 02026 02027 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info) 02028 { 02029 device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id); 02030 02031 uint8_t parent_ll_addr[16]; 02032 memcpy(parent_ll_addr, ADDR_LINK_LOCAL_PREFIX, 8); 02033 memcpy(parent_ll_addr + 8, nwk_info->extented_mac, 8); 02034 parent_ll_addr[8] ^= 2; 02035 02036 if (!device_configuration_ptr || blacklist_reject(parent_ll_addr)) { 02037 ns_dyn_mem_free(nwk_info); 02038 thci_trace("joinerDiscoveryFailedNoBeacon"); 02039 thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 02040 return; 02041 } 02042 02043 uint8_t private_mac[8]; 02044 ns_sha256_nbits(device_configuration_ptr->eui64, 8, private_mac, 64); 02045 private_mac[0] |= 2; //local administered bit is set 02046 02047 tr_debug("joiner mac id : %s", trace_array(private_mac, 8)); 02048 mac_helper_mac64_set(cur_interface, private_mac); 02049 02050 thread_set_link_local_address(cur_interface); // only to generate IID 02051 02052 thread_bootstrap_create_unsecure_link_to_parent(cur_interface, nwk_info); 02053 02054 thci_trace("joinerDiscoverySuccess"); 02055 uint8_t parentLLAddress[16]; 02056 protocol_6lowpan_interface_get_link_local_cordinator_address(cur_interface, parentLLAddress); 02057 tr_debug("Start commission with %s", trace_ipv6(parentLLAddress)); 02058 cur_interface->bootsrap_state_machine_cnt = 0; 02059 02060 if (0 > thread_extension_bootstrap_commission_start(cur_interface, parentLLAddress, nwk_info, thread_bootstrap_joiner_application_commission_done_cb)) { 02061 thread_joiner_application_pskd_commission_start(cur_interface->id, parentLLAddress, nwk_info->joiner_port, nwk_info->pan_id, nwk_info->extented_pan_id, nwk_info->channel, thread_bootstrap_joiner_application_commission_done_cb); 02062 } 02063 ns_dyn_mem_free(nwk_info); 02064 02065 } 02066 02067 void thread_bootsrap_device_synch_fail(protocol_interface_info_entry_t *cur) 02068 { 02069 tr_debug("Link Synch Fail -->Parent Scan Start"); 02070 thread_bootstrap_clear_neighbor_entries(cur); 02071 thread_network_synch_data_free(cur->id); 02072 thread_delete_ml64_address(cur); 02073 thread_parent_scan(cur); 02074 } 02075 02076 bool thread_device_synch_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 02077 { 02078 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id); 02079 (void)msgId; 02080 if (!interface) { 02081 return false; 02082 } 02083 02084 if (usedAllRetries) { 02085 thread_bootsrap_device_synch_fail(interface); 02086 return false; 02087 } 02088 02089 return true; 02090 } 02091 02092 bool thread_link_request_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 02093 { 02094 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id); 02095 02096 if (!interface) { 02097 return false; 02098 } 02099 02100 if (usedAllRetries) { 02101 uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId); 02102 tr_debug("Link Request timed out, address: %s", trace_ipv6(addr)); 02103 blacklist_update(addr, false); 02104 return false; 02105 } 02106 02107 return true; 02108 } 02109 static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entry_t *cur) 02110 { 02111 uint16_t my_short_address; 02112 uint8_t parent_mac64[8]; 02113 02114 int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address); 02115 if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { 02116 tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err); 02117 return false; 02118 } 02119 link_info_err = thread_nvm_store_link_info_clear(); 02120 if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { 02121 tr_warning("thread_nvm_store_link_info_clear returned %d", link_info_err); 02122 } 02123 if (thread_is_router_addr(my_short_address)) { 02124 thread_info(cur)->routerShortAddress = my_short_address; 02125 thread_dynamic_storage_build_mle_table(cur->id); 02126 thread_router_bootstrap_link_synch_start(cur); 02127 return true; 02128 } 02129 if (!thread_parent_data_allocate(cur->thread_info)) { 02130 tr_info("parent alloc failed"); 02131 return false; 02132 } 02133 02134 cur->thread_info->thread_endnode_parent->shortAddress = 0xfffe; 02135 memcpy(cur->thread_info->thread_endnode_parent->mac64,parent_mac64,8); 02136 thread_endevice_synch_start(cur); 02137 return true; 02138 } 02139 void thread_bootstrap_start_network_discovery(protocol_interface_info_entry_t *cur) 02140 { 02141 thread_discover_reques_t scan_request; 02142 thread_discovery_ready_cb *discover_ready; 02143 cur->nwk_nd_re_scan_count++; 02144 cur->mac_parameters->nwk_scan_params.stack_chan_list = cur->mac_parameters->mac_channel_list; 02145 02146 02147 if(cur->thread_info->native_commissioner_cb) { 02148 tr_debug("native commissioner network scan start"); 02149 02150 discover_ready = thread_discover_native_commissioner_response; 02151 scan_request.joiner_flag = false; 02152 scan_request.native_commisioner = true; 02153 } else { 02154 discovery_response_list_t *thread_network = thread_discovery_network_description_get(cur->id); 02155 if (thread_network) { 02156 thread_bootsrap_network_join_start(cur, thread_network); 02157 return; 02158 } 02159 02160 tr_debug("scan networks for joining application"); 02161 thci_trace("joinerDiscoveryStarted"); 02162 02163 blacklist_params_set( 02164 THREAD_COMM_BLACKLIST_ENTRY_LIFETIME, 02165 THREAD_COMM_BLACKLIST_TIMER_MAX_TIMEOUT, 02166 THREAD_COMM_BLACKLIST_TIMER_TIMEOUT, 02167 THREAD_BLACKLIST_ENTRY_MAX_NBR, 02168 THREAD_BLACKLIST_PURGE_NBR, 02169 THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT); 02170 02171 scan_request.native_commisioner = false; 02172 scan_request.joiner_flag = true; 02173 02174 discover_ready = thread_bootsrap_discovery_ready_cb; 02175 } 02176 02177 scan_request.channel_mask = cur->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0]; 02178 scan_request.filter_tlv_data = NULL; 02179 scan_request.filter_tlv_length = 0; 02180 if (thread_discovery_network_scan(cur->id, &scan_request, discover_ready) != 0 ) { 02181 tr_error("Discovery scan start fail"); 02182 } 02183 } 02184 void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur) 02185 { 02186 link_configuration_s *linkConfiguration; 02187 02188 switch (cur->nwk_bootstrap_state) { 02189 case ER_ACTIVE_SCAN: 02190 tr_debug("Thread SM:Active Scan"); 02191 02192 thread_joiner_application_nvm_link_configuration_load(cur->id); 02193 linkConfiguration = thread_joiner_application_get_config(cur->id); 02194 if (!linkConfiguration) { 02195 thread_bootstrap_start_network_discovery(cur); 02196 return; 02197 } 02198 02199 //SET Link by Static configuration 02200 tr_info("thread network attach start"); 02201 if (thread_mle_service_register(cur->id,thread_joiner_application_random_mac_get(cur->id)) != 0 || 02202 thread_link_configuration_activate(cur, linkConfiguration) != 0) { 02203 tr_error("Network Bootsrap Start Fail"); 02204 bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, cur); 02205 return; 02206 } 02207 if (thread_bootstrap_sync_after_reset_start(cur)) { 02208 // Link syncronisation started 02209 tr_debug("link synchronisation start"); 02210 return; 02211 } 02212 tr_debug("Parent Scan Start"); 02213 thread_parent_scan(cur); 02214 break; 02215 02216 case ER_SCAN: 02217 tr_debug("Thread SM:Start ER Scan"); 02218 cur->nwk_nd_re_scan_count = 0; 02219 thread_network_attach_start(cur); 02220 break; 02221 02222 case ER_MLE_ATTACH_READY: 02223 case ER_MLE_SYNCH: 02224 case ER_MLE_SCAN: 02225 case ER_CHILD_ID_REQ: 02226 tr_debug("Thread SM:Attach Ready"); 02227 break; 02228 02229 case ER_BOOTSRAP_DONE: 02230 tr_debug("Thread SM:Bootstrap Done"); 02231 cur->nwk_nd_re_scan_count = 0; 02232 break; 02233 case ER_BOOTSTRAP_SCAN_FAIL: 02234 tr_debug("Thread SM:Scan Failed"); 02235 nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, cur); 02236 break; 02237 02238 case ER_BOOTSTRAP_LEADER_UP: 02239 tr_debug("Thread SM:Leader Start"); 02240 thread_leader_service_thread_partitition_generate(cur->id, false); 02241 break; 02242 02243 case ER_BOOTSTRAP_NEW_FRAGMENT_START: 02244 tr_debug("Thread SM:Create New fragment"); 02245 thread_leader_service_thread_partitition_generate(cur->id, true); 02246 break; 02247 02248 default: 02249 tr_warn("Thread SM:Invalid state"); 02250 02251 } 02252 } 02253 void thread_bootstrap_stop(protocol_interface_info_entry_t *cur) 02254 { 02255 thread_address_registration_deinit(); 02256 thread_anycast_address_policy_update(cur->thread_info, false); 02257 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL); 02258 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); 02259 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); 02260 thread_leader_service_leader_data_free(cur->thread_info); 02261 thread_bootstrap_all_nodes_multicast_unregister(cur); 02262 thread_data_base_init(cur->thread_info, cur->id); 02263 thread_dhcp_client_delete(cur->id); 02264 thread_nd_service_delete(cur->id); 02265 thread_child_id_request_entry_clean(cur); 02266 thread_registered_mcast_addr_entry_clean(cur); 02267 cur->mesh_callbacks = NULL; 02268 } 02269 02270 void thread_bootstrap_child_update_trig(protocol_interface_info_entry_t *cur) 02271 { 02272 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && cur->thread_info->thread_endnode_parent) { 02273 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 02274 } 02275 } 02276 static void thread_border_router_locator_copy(protocol_interface_info_entry_t *cur,thread_commissioner_t *registered_commissioner , uint8_t *data) 02277 { 02278 memcpy(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 02279 memcpy(®istered_commissioner->border_router_address[8], ADDR_SHORT_ADR_SUFFIC, 6); 02280 memcpy(®istered_commissioner->border_router_address[14], data, 2); 02281 } 02282 /* \return -1 Failed 02283 * 0 OK, data not changed 02284 * 1 OK, data changed */ 02285 static int thread_commission_data_tlv_parse(protocol_interface_info_entry_t *cur, uint8_t type, uint8_t length, uint8_t *data) 02286 { 02287 thread_commissioner_t *registered_commissioner = &cur->thread_info->registered_commissioner; 02288 02289 switch (type) { 02290 // This is set by leader 02291 case THREAD_TLV_COMMISSIONER_SESSION_ID: 02292 if (length != 2) { 02293 return -1; 02294 } 02295 if(registered_commissioner->session_id != common_read_16_bit(data)){ 02296 registered_commissioner->session_id = common_read_16_bit(data); 02297 return 1; 02298 } 02299 break; 02300 02301 case THREAD_TLV_STEERING_DATA: 02302 if (length > 16) { 02303 return -1; 02304 } 02305 if(registered_commissioner->steering_data_len != length || memcmp(registered_commissioner->steering_data, data, length)){ 02306 memcpy(registered_commissioner->steering_data, data, length); 02307 registered_commissioner->steering_data_len = length; 02308 return 1; 02309 } 02310 break; 02311 02312 case THREAD_TLV_BORDER_ROUTER_LOCATOR: 02313 if (length != 2) { 02314 return -1; 02315 } 02316 02317 registered_commissioner->commissioner_valid = true; 02318 if (!registered_commissioner->commissioner_valid || 02319 memcmp(®istered_commissioner->border_router_address[14], data, 2) || 02320 memcmp(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8)) { 02321 thread_border_router_locator_copy(cur,registered_commissioner, data ); 02322 return 1; 02323 } 02324 break; 02325 02326 default: 02327 break; 02328 02329 } 02330 return 0; 02331 } 02332 static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cur, thread_prefix_tlv_t *prefixTlv, bool stableData) 02333 { 02334 thread_network_local_data_context_entry_t context; 02335 uint8_t cid; 02336 //check possible context id or current allocated 02337 cid = thread_nd_context_id_allocate(&cur->thread_info->networkDataStorage, &cur->thread_info->localServerDataBase, prefixTlv->Prefix, prefixTlv->PrefixLen); 02338 if (cid == 16) { 02339 return -1; 02340 } 02341 context.cid = cid; 02342 context.compression = true; 02343 context.stableData = stableData; 02344 context.contextPrefixLength = prefixTlv->PrefixLen; 02345 if (lowpan_context_update(&cur->lowpan_contexts, cid, 0xffff, prefixTlv->Prefix, prefixTlv->PrefixLen, stableData) != 0) { 02346 return -1; 02347 } 02348 02349 if (thread_nd_local_list_add_contexts(&cur->thread_info->networkDataStorage, prefixTlv, &context) != 0) { 02350 //Free context if allocation fail 02351 lowpan_context_update(&cur->lowpan_contexts, cid, 0, prefixTlv->Prefix, prefixTlv->PrefixLen, stableData); 02352 return -1; 02353 } 02354 02355 return 0; 02356 } 02357 02358 int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, uint8_t *network_data_ptr, uint16_t network_data_length) 02359 { 02360 int ret_val = 0; 02361 uint8_t addr[16]; 02362 uint8_t *dptr; 02363 uint16_t length, data_length, flags; 02364 uint8_t prefix_bytes_len, subLength, preference; 02365 uint8_t type; 02366 bool stableData; 02367 bool update_data = false; 02368 thread_prefix_tlv_t prefixTlv; 02369 thread_network_local_data_context_entry_t context; 02370 thread_border_router_tlv_entry_t genericService; 02371 thread_network_data_cache_entry_t *networkDataStorage = &cur->thread_info->networkDataStorage; 02372 02373 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 02374 if (!linkConfiguration) { 02375 return -1; 02376 } 02377 02378 data_length = network_data_length; 02379 dptr = network_data_ptr; 02380 tr_debug("Start Parsing TLV one by One"); 02381 while (data_length) { 02382 tr_debug("Main TLV: %s", trace_array(dptr, data_length)); 02383 02384 prefixTlv.Prefix = NULL; 02385 prefixTlv.PrefixLen = 0; 02386 02387 type = *dptr++; 02388 if (type & THREAD_NWK_STABLE_DATA) { 02389 stableData = true; 02390 } else { 02391 stableData = false; 02392 } 02393 02394 type &= THREAD_NWK_DATA_TYPE_MASK; 02395 length = *dptr++; 02396 if ((length + 2) > data_length) { 02397 return -1; 02398 } 02399 02400 //SET Pointer & Length ready for next check 02401 data_length -= (length + 2); 02402 if (!stableData && !cur->thread_info->requestFullNetworkData) { 02403 //Skip unstable data when it not requsted 02404 dptr += length; 02405 } else if (type == THREAD_NWK_DATA_TYPE_PREFIX) { 02406 prefixTlv.domainId = *dptr++; 02407 prefixTlv.PrefixLen = *dptr++; 02408 //Decrement length by prefix length 02409 length -= 2; 02410 prefixTlv.Prefix = dptr; 02411 prefix_bytes_len = prefixBits_to_bytes(prefixTlv.PrefixLen); 02412 02413 if (prefix_bytes_len > length) { 02414 return -1; 02415 } 02416 length -= prefix_bytes_len; 02417 dptr += prefix_bytes_len; 02418 tr_debug("Prefix: %s", trace_ipv6_prefix(prefixTlv.Prefix, prefixTlv.PrefixLen)); 02419 02420 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02421 02422 while (length > 2) { 02423 type = *dptr++; 02424 subLength = *dptr++; 02425 length -= 2; 02426 if (type & THREAD_NWK_STABLE_DATA) { 02427 stableData = true; 02428 } else { 02429 stableData = false; 02430 } 02431 type &= THREAD_NWK_DATA_TYPE_MASK; 02432 02433 tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength)); 02434 02435 if (subLength <= length) { 02436 length -= subLength; 02437 if (type == THREAD_NWK_DATA_TYPE_6LOWPAN_ID) { 02438 while (subLength) { 02439 if (*dptr & THREAD_NWK_CONTEXT_COMPRESS_ENABLED) { 02440 context.compression = true; 02441 } else { 02442 context.compression = false; 02443 } 02444 02445 context.cid = (*dptr++ & 0x0f); 02446 context.contextPrefixLength = *dptr++; 02447 context.stableData = stableData; 02448 subLength -= 2; 02449 02450 if (thread_nd_verify_contex_id_is_free(networkDataStorage, prefixTlv.Prefix, &context) == 0) { 02451 thread_nd_local_list_add_contexts(networkDataStorage, &prefixTlv, &context); 02452 02453 } else { 02454 tr_debug("CID reserved already"); 02455 } 02456 } 02457 } else { 02458 02459 while (subLength) { 02460 genericService.routerID = common_read_16_bit(dptr); 02461 dptr += 2; 02462 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 02463 flags = common_read_16_bit(dptr); 02464 dptr += 2; 02465 subLength -= THREAD_BORDER_ROUTER_TLV_LENGTH; 02466 genericService.Prf = ((flags >> THREAD_PRF_BIT_MOVE) & 3); 02467 } else { 02468 /* HAS_ROUTE */ 02469 preference = *dptr++; 02470 subLength -= THREAD_HAS_ROUTE_TLV_LENGTH; 02471 genericService.Prf = ((preference >> THREAD_HAS_ROUTE_PRF_BIT_MOVE) & 3); 02472 } 02473 02474 genericService.stableData = stableData; 02475 02476 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 02477 genericService.P_configure = ((flags >> THREAD_P_CONFIGURE_BIT_MOVE) & 1); 02478 genericService.P_default_route = ((flags >> THREAD_P_DEF_ROUTE_BIT_MOVE) & 1); 02479 genericService.P_dhcp = ((flags >> THREAD_P_DHCP_BIT_MOVE) & 1); 02480 genericService.P_preferred = ((flags >> THREAD_P_PREFERRED_BIT_MOVE) & 1); 02481 genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1); 02482 genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1); 02483 genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1); 02484 if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) { 02485 if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) { 02486 if (!genericService.P_slaac) { 02487 //Delete Address by this Entry 02488 tr_debug("Delete SLAAC address because not valid."); 02489 addr_delete_matching(cur, prefixTlv.Prefix, 64, ADDR_SOURCE_SLAAC); 02490 } else { 02491 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 02492 if (e->source == ADDR_SOURCE_SLAAC && 02493 bitsequal(e->address, prefixTlv.Prefix, 64)) { 02494 if (genericService.P_preferred) { 02495 tr_debug("SLAAC address set as preferred."); 02496 } else { 02497 tr_debug("SLAAC address set as NOT preferred."); 02498 } 02499 addr_set_preferred_lifetime(cur, e, genericService.P_preferred ? 0xfffffffff: 0); 02500 } 02501 } 02502 } 02503 02504 if (!genericService.P_dhcp) { 02505 //Delete DHCPv6 client 02506 memcpy(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 02507 memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); 02508 common_write_16_bit(genericService.routerID, &addr[14]); 02509 tr_debug("Delete DHCPv6 given address"); 02510 thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); 02511 } 02512 } 02513 02514 02515 //Allocate Context 02516 if (cur->thread_info->leader_private_data) { 02517 if (thread_nd_prefix_context_allocate(cur, &prefixTlv, stableData) != 0) { 02518 //Mark Delete for this setup if context allocate fail 02519 thread_nd_local_list_del_on_mesh_server(networkDataStorage, &prefixTlv, &genericService); 02520 } 02521 } 02522 } 02523 } else if (type == THREAD_NWK_DATA_TYPE_ROUTE) { 02524 if (genericService.routerID < 0xfffe) { 02525 thread_nd_local_list_add_route(networkDataStorage, &prefixTlv, &genericService); 02526 tr_debug("added route"); 02527 } 02528 } 02529 } 02530 } 02531 } else { 02532 tr_debug("SERVER Parse fail"); 02533 break; 02534 } 02535 } 02536 } else { 02537 tr_debug("Malform Prefix sub TLV"); 02538 dptr += length; 02539 } 02540 02541 } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && stableData) { 02542 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02543 tr_debug("Stable Commisssion TLV: %i", length); 02544 // Stable commissioning data has the Timestamps and is not processed here 02545 } else { 02546 tr_debug("Malformed stable Commisssion TLV: %i", length); 02547 } 02548 dptr += length; 02549 02550 } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && !stableData) { 02551 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02552 int data_changed; 02553 tr_debug("Unstable Commisssion TLV: %i", length); 02554 // in thread 1.1 unstable has only commissioner information 02555 cur->thread_info->registered_commissioner.commissioner_valid = false; 02556 while (length > 2) { 02557 type = *dptr++; 02558 subLength = *dptr++; 02559 length -= 2; 02560 tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength)); 02561 02562 if (subLength <= length) { 02563 length -= subLength; 02564 02565 data_changed = thread_commission_data_tlv_parse(cur, type, subLength, dptr); 02566 if (data_changed < 0) 02567 tr_debug("Fail"); 02568 else { 02569 if (data_changed == 1) { 02570 update_data = true; 02571 tr_debug("Changed"); 02572 } else { 02573 tr_debug("OK"); 02574 } 02575 } 02576 dptr += subLength; 02577 } else { 02578 tr_debug("SERVER Parse fail"); 02579 break; 02580 } 02581 } 02582 } else { 02583 tr_debug("Malformed unstable Commisssion TLV: %i", length); 02584 dptr += length; 02585 } 02586 } else if (type == THREAD_NWK_DATA_TYPE_SERVICE_DATA) { 02587 thread_network_data_service_entry_t service_entry; 02588 02589 service_entry.T = (*dptr) >> 7; 02590 service_entry.S_id = (*dptr++) & 0x0f; 02591 service_entry.S_stable = stableData; 02592 02593 if (!service_entry.T) { 02594 service_entry.S_enterprise_number = common_read_32_bit(dptr); 02595 dptr += 4; 02596 length -= 4; 02597 } else { 02598 service_entry.S_enterprise_number = THREAD_ENTERPRISE_NUMBER; 02599 } 02600 02601 service_entry.S_service_data_length = *dptr++; 02602 service_entry.S_service_data = dptr; 02603 dptr += service_entry.S_service_data_length; 02604 02605 tr_debug("Service data: %s, enterprise number: %"PRIu32, trace_array(service_entry.S_service_data, 02606 service_entry.S_service_data_length), service_entry.S_enterprise_number); 02607 02608 length -= 2 + service_entry.S_service_data_length; 02609 02610 while (length > 2) { 02611 type = *dptr++; 02612 subLength = *dptr++; 02613 length -= 2; 02614 02615 if (subLength <= length) { 02616 tr_debug("SubType: %02x, length: %d, data: %s", type, length, trace_array(dptr, subLength)); 02617 02618 length -= subLength; 02619 02620 thread_network_data_service_server_entry_t server = {0}; 02621 02622 if (type & THREAD_NWK_STABLE_DATA) { 02623 server.stable = true; 02624 } 02625 02626 server.router_id = common_read_16_bit(dptr); 02627 subLength -= 2; 02628 dptr += 2; 02629 02630 server.server_data = dptr; 02631 server.server_data_length = subLength; 02632 tr_debug("Router ID: %04x, Server data: %s", server.router_id, trace_array(server.server_data, server.server_data_length)); 02633 02634 thread_nd_local_list_add_service(networkDataStorage, &service_entry, &server); 02635 dptr += subLength; 02636 } else { 02637 tr_debug("Server sub-TLV parse fail!"); 02638 return -1; 02639 } 02640 } 02641 } else { 02642 return -1; 02643 } 02644 } 02645 02646 if (update_data) { 02647 ret_val = 1; 02648 } 02649 return ret_val; 02650 } 02651 02652 int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) 02653 { 02654 //Mark old data to be be freed 02655 thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false); 02656 02657 int retVal = thread_bootstrap_network_data_process(cur, cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len); 02658 02659 if (retVal < 0) { 02660 tr_warn("network data update failed: %s", trace_array(cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len)); 02661 return retVal; 02662 } 02663 02664 // delete marked data 02665 if (thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur) ) { 02666 thread_bootstrap_child_update_trig(cur); 02667 } 02668 02669 // Learn the routes and dhcp addresses from prefixes 02670 thread_bootstrap_network_prefixes_process(cur); 02671 //Add new anycast addressess learned from network data. 02672 thread_router_bootstrap_anycast_address_register(cur); 02673 // Update joiner router status 02674 thread_management_server_joiner_router_init(cur->id); 02675 thread_extension_joiner_router_init(cur->id); 02676 02677 // Update border router relay 02678 thread_bbr_commissioner_proxy_service_update(cur->id); 02679 // update beacons 02680 thread_beacon_create_payload(cur); 02681 02682 // Indicate network data change to other modules 02683 thread_extension_network_data_process(cur); 02684 thread_border_router_network_data_update_notify(cur); 02685 thread_bbr_network_data_update_notify(cur); 02686 02687 return 0; 02688 } 02689 02690 int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint8_t* network_data_ptr, uint16_t network_data_len) 02691 { 02692 if (!cur || !cur->thread_info || !leader_data || network_data_len > THREAD_MAX_NETWORK_DATA_SIZE) { 02693 tr_warn("Network data saving failed"); 02694 return -1; 02695 } 02696 02697 if (thread_attach_ready(cur) != 0) { 02698 return -2; 02699 } 02700 02701 if (thread_network_data_malformed_check(network_data_ptr, network_data_len) != 0) { 02702 tr_warn("Malformed nw data: %s", trace_array(network_data_ptr, network_data_len)); 02703 return -3; 02704 } 02705 02706 // Do not process the network data until we are synchronized 02707 tr_debug("learn new network data"); 02708 02709 if (thread_info(cur)->thread_leader_data->stableDataVersion != leader_data->stableDataVersion) { 02710 thread_info(cur)->thread_leader_data->stableDataVersion = leader_data->stableDataVersion; 02711 cur->thread_info->networkDataStorage.stableUpdatePushed = true; 02712 } 02713 if (thread_info(cur)->thread_leader_data->dataVersion != leader_data->dataVersion) { 02714 thread_info(cur)->thread_leader_data->dataVersion = leader_data->dataVersion; 02715 cur->thread_info->networkDataStorage.temporaryUpdatePushed = true; 02716 } 02717 if ((network_data_len!=cur->thread_info->networkDataStorage.network_data_len || 02718 memcmp(cur->thread_info->networkDataStorage.network_data,network_data_ptr,network_data_len) != 0)){ 02719 // Network data was changed so at least it will be unstable change 02720 cur->thread_info->networkDataStorage.temporaryUpdatePushed = true; 02721 tr_debug("Network data changed; size %d stable:%d, unstable:%d", network_data_len, cur->thread_info->networkDataStorage.stableUpdatePushed,cur->thread_info->networkDataStorage.temporaryUpdatePushed); 02722 memcpy(cur->thread_info->networkDataStorage.network_data, network_data_ptr,network_data_len); 02723 cur->thread_info->networkDataStorage.network_data_len = network_data_len; 02724 } 02725 02726 return 0; 02727 } 02728 02729 02730 void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur) 02731 { 02732 // Route prefix is variable-length, so need to zero pad for ip6tos 02733 uint8_t addr[16]; 02734 bool validToLearnRoutes, validToLearOnMeshRoute; 02735 thread_network_server_data_entry_t *weHostService = NULL; 02736 uint16_t routerId; 02737 tr_debug("Network Data process:"); 02738 routerId = cur->mac_parameters->mac_short_address; 02739 thread_network_data_cache_entry_t *networkData; 02740 networkData = &cur->thread_info->networkDataStorage; 02741 validToLearnRoutes = thread_route_possible_add(cur->thread_info->thread_device_mode); 02742 validToLearOnMeshRoute = thread_on_mesh_route_possible_add(cur->thread_info->thread_device_mode); 02743 02744 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); 02745 02746 ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &networkData->localPrefixList ) { 02747 weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->routeList); 02748 tr_debug("Local ServicePrefix: %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02749 02750 if (!weHostService && validToLearnRoutes) { 02751 ns_list_foreach(thread_network_server_data_entry_t, curRouteItem, &curPrefix->routeList) { 02752 thread_addr_write_mesh_local_16(addr, curRouteItem->routerID, cur->thread_info); 02753 tr_debug("Add new route via: %s", trace_ipv6(addr)); 02754 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curRouteItem->Prf); 02755 } 02756 } 02757 02758 weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->borderRouterList); 02759 if(weHostService) { 02760 tr_debug( "I'm Hosting BR"); 02761 } 02762 02763 ns_list_foreach(thread_network_server_data_entry_t, curBorderRouter, &curPrefix->borderRouterList) { 02764 //Set Default route ::/0 02765 if (curBorderRouter->P_default_route) { 02766 if (!(weHostService && weHostService->P_default_route) && validToLearnRoutes) { 02767 thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); 02768 tr_debug("Add default route via: %s", trace_ipv6(addr)); 02769 ipv6_route_add(NULL, 0, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf); 02770 } 02771 } 02772 ipv6_stack_route_advert_update(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, RA_PRF_LOW); 02773 02774 if (thread_nd_on_mesh_address_valid(curBorderRouter)) { 02775 if (validToLearOnMeshRoute) { 02776 if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) { 02777 // don't add 02778 tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02779 } else { 02780 //add 02781 tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02782 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf); 02783 } 02784 } 02785 } 02786 02787 if (curBorderRouter->P_dhcp) { 02788 /* All end device types perform BR RLOC16 -> ALOC16 02789 replacement if stable network data was requested. */ 02790 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST || 02791 cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) && 02792 cur->thread_info->requestFullNetworkData == false) { 02793 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) { 02794 curBorderRouter->routerID = 0xfc00; 02795 curBorderRouter->routerID |= curRoute->cid; 02796 tr_debug("Replaced router ID with ALOC16: %04x", curBorderRouter->routerID); 02797 } 02798 } 02799 02800 if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { 02801 thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); 02802 /* Do not allow multiple DHCP solicits from one prefix => delete previous */ 02803 thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); 02804 if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { 02805 tr_debug("GP Address Requested"); 02806 } 02807 } 02808 } else { 02809 /* All end device types perform RLOC16 -> 0xfffe 02810 replacement if stable network data was requested. */ 02811 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST || 02812 cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) && 02813 cur->thread_info->requestFullNetworkData == false) { 02814 curBorderRouter->routerID = 0xfffe; 02815 tr_debug("Invalidated router ID: %04x", curBorderRouter->routerID); 02816 } 02817 } 02818 02819 if (curBorderRouter->P_preferred) { 02820 if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { 02821 icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); 02822 } 02823 } 02824 02825 } // for each borderRouterList 02826 02827 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) { 02828 uint8_t flags; 02829 flags = curRoute->cid; 02830 if (curRoute->compression) { 02831 flags |= 0x10; 02832 } 02833 02834 lowpan_context_update(&cur->lowpan_contexts, flags , 0xFFFF, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, curRoute->stableData); 02835 } 02836 } // for each localPrefixList 02837 } 02838 02839 void thread_bootstrap_network_data_update(protocol_interface_info_entry_t *cur) 02840 { 02841 if (!cur || !cur->thread_info) { 02842 return; 02843 } 02844 02845 if (cur->thread_info->networkDataStorage.stableUpdatePushed) { 02846 tr_debug("Stable Network Data Update"); 02847 } else if (cur->thread_info->networkDataStorage.temporaryUpdatePushed) { 02848 tr_debug("Temporary Network Data Update"); 02849 } else { 02850 // No changes in network data detected so no processing done 02851 return; 02852 } 02853 tr_info("Network data updated"); 02854 thread_bootstrap_network_data_activate(cur); 02855 thread_router_bootstrap_network_data_distribute(cur); 02856 02857 cur->thread_info->networkDataStorage.stableUpdatePushed = false; 02858 cur->thread_info->networkDataStorage.temporaryUpdatePushed = false; 02859 } 02860 02861 void thread_bootstrap_clear_neighbor_entries(protocol_interface_info_entry_t *cur) 02862 { 02863 if (cur == NULL || cur->thread_info == NULL) { 02864 return; 02865 } 02866 02867 // Remove registered entries in the IP neighbor cache 02868 ns_list_foreach_safe(ipv6_neighbour_t, neighbour, &cur->ipv6_neighbour_cache.list) { 02869 if (neighbour->type == IP_NEIGHBOUR_REGISTERED) { 02870 ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour); 02871 } 02872 } 02873 02874 mle_class_list_clean(cur->id); 02875 } 02876 02877 void thread_bootstrap_dynamic_configuration_save(protocol_interface_info_entry_t *cur) 02878 { 02879 uint32_t mac_frame_counter; 02880 if (!cur->thread_info) { 02881 return; 02882 } 02883 02884 if (thread_i_am_router(cur)) { 02885 /* Store information of our children to the dynamic storage */ 02886 mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id); 02887 ns_list_foreach_safe(mle_neigh_table_entry_t, entry, neig_list) { 02888 if (thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->short_adr)) { 02889 thread_dynamic_storage_child_info_store(cur->id, entry); 02890 } 02891 } 02892 } 02893 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 02894 mac_helper_link_frame_counter_read(cur->id, &mac_frame_counter); 02895 // in error situation this returns 0 !!!! 02896 uint32_t mle_frame_counter = mle_service_security_get_frame_counter(cur->id); 02897 if (linkConfiguration) { 02898 thread_nvm_store_fast_data_check_and_write(mac_frame_counter, mle_frame_counter, linkConfiguration->key_sequence); 02899 } 02900 else { 02901 thread_nvm_store_frame_counters_check_and_write(mac_frame_counter, mle_frame_counter); 02902 } 02903 } 02904 02905 bool thread_bootstrap_link_create_check(protocol_interface_info_entry_t *interface, uint16_t short_address) 02906 { 02907 if (interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE || 02908 interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE) { 02909 // MED's never make any links so return false 02910 return false; 02911 } 02912 02913 if(mle_class_free_entry_count_get(interface->id) < 1) { 02914 // We dont have room for any new links 02915 tr_warn("Link ignore no room for addr:%x", short_address); 02916 return false; 02917 } 02918 // TODO should check that we have enough room left for children 02919 // TODO Need to drop links for bad routers if no room 02920 02921 if (interface->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 02922 //routers always make links 02923 return true; 02924 } 02925 02926 if (thread_is_router_addr(short_address) == false) { 02927 //incoming advertisement is not from router so return false 02928 return false; 02929 } 02930 02931 if (mle_class_active_neigh_counter(interface->id) < THREAD_REED_AND_END_DEVICE_NEIGHBOR_LINKS + 1) { 02932 return true; 02933 } 02934 02935 return false; 02936 } 02937 02938 bool thread_bootstrap_link_create_allowed(protocol_interface_info_entry_t *interface, uint16_t short_address, const uint8_t *src_addr) 02939 { 02940 #ifndef HAVE_DEBUG 02941 (void) short_address; 02942 #endif 02943 // Add blacklist of routers that newer answer to us 02944 if(mle_service_interface_tx_queue_size(interface->id) > THREAD_MAX_PARALLEL_MLE_LINK_REQUEST) { 02945 // Maximum parallel link requests 02946 tr_warn("Link ignore too many req addr:%x", short_address); 02947 return false; 02948 } 02949 02950 if (blacklist_reject(src_addr)) { 02951 return false; 02952 } 02953 02954 return true; 02955 } 02956 02957 bool thread_bootstrap_should_register_address(protocol_interface_info_entry_t *cur) 02958 { 02959 // If we are a MTD, send requests to register addresses 02960 // Neither REEDs nor FEDs need to register their addresses 02961 uint8_t mode = thread_mode_get_by_interface_ptr(cur); 02962 return (mode & MLE_DEV_MASK) == MLE_RFD_DEV; 02963 } 02964 02965 #endif
Generated on Tue Jul 12 2022 12:45:56 by
