Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ws_bootstrap.c
00001 /* 00002 * Copyright (c) 2018-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include <string.h> 00019 #include "nsconfig.h" 00020 #include "ns_types.h" 00021 #include "ns_trace.h" 00022 #include "net_interface.h" 00023 #include "eventOS_event.h" 00024 #include "randLIB.h" 00025 #include "common_functions.h" 00026 #include "mac_common_defines.h" 00027 #include "sw_mac.h" 00028 #include "ccmLIB.h" 00029 #include "NWK_INTERFACE/Include/protocol.h" 00030 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00031 #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" 00032 #include "ipv6_stack/protocol_ipv6.h" 00033 #include "6LoWPAN/MAC/mac_helper.h" 00034 #include "6LoWPAN/MAC/mac_data_poll.h" 00035 #include "6LoWPAN/MAC/mpx_api.h" 00036 #include "6LoWPAN/MAC/mac_ie_lib.h" 00037 #include "MPL/mpl.h" 00038 #include "RPL/rpl_protocol.h" 00039 #include "RPL/rpl_control.h" 00040 #include "RPL/rpl_data.h" 00041 #include "Common_Protocols/icmpv6.h" 00042 #include "Common_Protocols/icmpv6_radv.h" 00043 #include "Common_Protocols/ipv6_constants.h" 00044 #include "Service_Libs/Trickle/trickle.h" 00045 #include "Service_Libs/fhss/channel_list.h" 00046 #include "6LoWPAN/ws/ws_common_defines.h" 00047 #include "6LoWPAN/ws/ws_common_defines.h" 00048 #include "6LoWPAN/ws/ws_config.h" 00049 #include "6LoWPAN/ws/ws_common.h" 00050 #include "6LoWPAN/ws/ws_bootstrap.h" 00051 #include "6LoWPAN/ws/ws_bbr_api_internal.h" 00052 #include "6LoWPAN/ws/ws_common_defines.h" 00053 #include "6LoWPAN/ws/ws_llc.h" 00054 #include "6LoWPAN/ws/ws_neighbor_class.h" 00055 #include "6LoWPAN/ws/ws_ie_lib.h" 00056 #include "6LoWPAN/ws/ws_stats.h" 00057 #include "6LoWPAN/lowpan_adaptation_interface.h" 00058 #include "Service_Libs/etx/etx.h" 00059 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00060 #include "Service_Libs/nd_proxy/nd_proxy.h" 00061 #include "Service_Libs/blacklist/blacklist.h" 00062 #include "platform/topo_trace.h" 00063 #include "libDHCPv6/libDHCPv6.h" 00064 #include "DHCPv6_client/dhcpv6_client_api.h" 00065 #include "ws_management_api.h" 00066 #include "net_rpl.h" 00067 #include "mac_api.h" 00068 #include "6LoWPAN/ws/ws_pae_controller.h" 00069 #include "6LoWPAN/ws/ws_eapol_pdu.h" 00070 #include "6LoWPAN/ws/ws_eapol_auth_relay.h" 00071 #include "6LoWPAN/ws/ws_eapol_relay.h" 00072 00073 #define TRACE_GROUP "wsbs" 00074 00075 #ifdef HAVE_WS 00076 00077 static void ws_bootstrap_event_handler(arm_event_s *event); 00078 static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state); 00079 static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur); 00080 static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur); 00081 static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur); 00082 static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data); 00083 00084 static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new); 00085 static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur); 00086 static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur); 00087 static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur); 00088 00089 static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cur); 00090 static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t operation, uint8_t index, uint8_t *key); 00091 static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot); 00092 static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index); 00093 static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot); 00094 static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot); 00095 static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64); 00096 static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur); 00097 static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor); 00098 static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr); 00099 static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data); 00100 static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface); 00101 00102 00103 static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); 00104 static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); 00105 00106 typedef enum { 00107 WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ 00108 WS_PARENT_HARD_SYNCH, /**< Synch FHSS with latest synch information*/ 00109 WS_EAPOL_PARENT_SYNCH, /**< Broadcast synch with EAPOL parent*/ 00110 } ws_parent_synch_e; 00111 00112 00113 static void ws_bootsrap_create_ll_address(uint8_t *ll_address, const uint8_t *mac64) 00114 { 00115 memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8); 00116 memcpy(ll_address + 8, mac64, 8); 00117 ll_address[8] ^= 2; 00118 } 00119 00120 mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interface_info_entry *interface, const uint8_t *src64) 00121 00122 { 00123 mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT); 00124 if (neighbor) { 00125 return neighbor; 00126 } 00127 00128 neighbor = mac_neighbor_table_entry_allocate(mac_neighbor_info(interface), src64); 00129 if (!neighbor) { 00130 return NULL; 00131 } 00132 // TODO only call these for new neighbour 00133 mlme_device_descriptor_t device_desc; 00134 neighbor->lifetime = WS_NEIGHBOR_LINK_TIMEOUT; 00135 neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; 00136 tr_debug("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index ); 00137 mac_helper_device_description_write(interface, &device_desc, neighbor->mac64 , neighbor->mac16 , 0, false); 00138 mac_helper_devicetable_set(&device_desc, interface, neighbor->index , interface->mac_parameters->mac_default_key_index, true); 00139 return neighbor; 00140 } 00141 00142 static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr) 00143 { 00144 mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index , entry_ptr->mac64 ); 00145 etx_neighbor_remove(interface->id, entry_ptr->index ); 00146 ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, entry_ptr->index ); 00147 } 00148 00149 static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface) 00150 { 00151 00152 mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(interface)); 00153 } 00154 00155 static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason) 00156 { 00157 /* No need for LL address registration */ 00158 if (addr->source == ADDR_SOURCE_UNKNOWN) { 00159 return; 00160 } 00161 if (reason == ADDR_CALLBACK_DAD_COMPLETE) { 00162 //Trig Address Registartion only when Bootstrap is ready 00163 if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE && addr->source != ADDR_SOURCE_DHCP) { 00164 tr_debug("Address registration %s", trace_ipv6(addr->address)); 00165 rpl_control_register_address(interface, addr->address); 00166 } 00167 if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_LINK_LOCAL) { 00168 // at least ula address available inside mesh. 00169 interface->global_address_available = true; 00170 } 00171 00172 } else if (reason == ADDR_CALLBACK_DELETED) { 00173 // What to do? 00174 // Go through address list and check if there is global address still available 00175 if (addr->source == ADDR_SOURCE_DHCP) { 00176 //Deprecate dhcpv address 00177 uint8_t address[16]; 00178 memcpy(address, addr->address, 16); 00179 dhcp_client_global_address_delete(interface->id, NULL, address); 00180 } 00181 //Discover prefix policy 00182 addr_policy_remove_by_label(WS_NON_PREFFRED_LABEL); 00183 00184 interface->global_address_available = false; 00185 ns_list_foreach(if_address_entry_t, addr_str, &interface->ip_addresses) { 00186 if (addr_ipv6_scope(addr_str->address, interface) > IPV6_SCOPE_LINK_LOCAL) { 00187 // at least ula address available inside mesh. 00188 interface->global_address_available = true; 00189 break; 00190 } 00191 } 00192 } else if (reason == ADDR_CALLBACK_TIMER) { 00193 if (addr->source != ADDR_SOURCE_DHCP) { 00194 tr_debug("Address Re registration %s", trace_ipv6(addr->address)); 00195 //Register 00196 rpl_control_register_address(interface, addr->address); 00197 } 00198 } 00199 } 00200 00201 static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur) 00202 { 00203 if (cur->bootStrapId < 0) { 00204 cur->bootStrapId = eventOS_event_handler_create(&ws_bootstrap_event_handler, WS_INIT_EVENT); 00205 tr_debug("WS tasklet init"); 00206 } 00207 00208 if (cur->bootStrapId < 0) { 00209 tr_error("tasklet init failed"); 00210 return -1; 00211 } 00212 00213 00214 return 0; 00215 } 00216 static void ws_nwk_event_post(protocol_interface_info_entry_t *cur, arm_nwk_interface_status_type_e posted_event) 00217 { 00218 arm_event_s event = { 00219 .receiver = cur->net_start_tasklet, 00220 .sender = protocol_read_tasklet_id(), /**< Event sender Tasklet ID */ 00221 .event_type = ARM_LIB_NWK_INTERFACE_EVENT, 00222 .event_data = posted_event, 00223 .event_id = (int8_t) cur->id, 00224 .data_ptr = NULL, 00225 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00226 }; 00227 if (eventOS_event_send(&event) != 0) { 00228 tr_error("nwk_net_event_post(): event send failed"); 00229 } 00230 } 00231 00232 static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data) 00233 { 00234 arm_event_s event = { 00235 .receiver = interface_id, 00236 .sender = 0, 00237 .event_type = event_type, 00238 .priority = priority, 00239 .data_ptr = event_data, 00240 }; 00241 return eventOS_event_send(&event); 00242 } 00243 00244 static void ws_nud_table_reset(protocol_interface_info_entry_t *cur) 00245 { 00246 //Empty active list 00247 ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { 00248 ns_list_remove(&cur->ws_info->active_nud_process, entry); 00249 } 00250 00251 //Empty free list 00252 ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->free_nud_entries) { 00253 ns_list_remove(&cur->ws_info->free_nud_entries, entry); 00254 } 00255 //Add to free list to full 00256 for (int i = 0; i < ACTIVE_NUD_PROCESS_MAX; i++) { 00257 ns_list_add_to_end(&cur->ws_info->free_nud_entries, &cur->ws_info->nud_table_entrys[i]); 00258 } 00259 } 00260 00261 static ws_nud_table_entry_t *ws_nud_entry_get_free(protocol_interface_info_entry_t *cur) 00262 { 00263 ws_nud_table_entry_t *entry = ns_list_get_first(&cur->ws_info->free_nud_entries); 00264 if (entry) { 00265 entry->wait_response = false; 00266 entry->retry_count = 0; 00267 entry->nud_process = false; 00268 entry->timer = randLIB_get_random_in_range(1, 900); 00269 entry->neighbor_info = NULL; 00270 ns_list_remove(&cur->ws_info->free_nud_entries, entry); 00271 ns_list_add_to_end(&cur->ws_info->active_nud_process, entry); 00272 } 00273 return entry; 00274 } 00275 00276 00277 void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor) 00278 { 00279 ws_nud_table_entry_t *entry = ws_nud_entry_discover(cur, neighbor); 00280 00281 if (entry) { 00282 mac_neighbor_table_entry_t *mac_neighbor = neighbor; 00283 ns_list_remove(&cur->ws_info->active_nud_process, entry); 00284 ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry); 00285 if (mac_neighbor->nud_active ) { 00286 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_neighbor, mac_neighbor->link_lifetime ); 00287 } 00288 00289 mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor); 00290 } 00291 } 00292 00293 00294 static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor) 00295 { 00296 ns_list_foreach(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { 00297 if (entry->neighbor_info == neighbor) { 00298 return entry; 00299 } 00300 } 00301 return NULL; 00302 } 00303 00304 00305 static void ws_nud_state_clean(protocol_interface_info_entry_t *cur, ws_nud_table_entry_t *entry) 00306 { 00307 mac_neighbor_table_entry_t *neighbor = entry->neighbor_info; 00308 ns_list_remove(&cur->ws_info->active_nud_process, entry); 00309 ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry); 00310 if (neighbor->nud_active ) { 00311 neighbor->nud_active = false; 00312 mac_neighbor_info(cur)->active_nud_process--; 00313 } 00314 } 00315 00316 static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr) 00317 { 00318 ws_nud_table_entry_t *nud_entry = ws_nud_entry_discover(cur, entry_ptr); 00319 if (nud_entry) { 00320 ws_nud_state_clean(cur, nud_entry); 00321 } 00322 } 00323 00324 static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor) 00325 { 00326 //Send NS 00327 uint8_t ll_target[16]; 00328 ws_bootsrap_create_ll_address(ll_target, neighbor->mac64 ); 00329 tr_info("NUD generate NS %u", neighbor->index ); 00330 buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); 00331 if (buffer) { 00332 protocol_push(buffer); 00333 return true; 00334 } 00335 return false; 00336 } 00337 00338 void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks) 00339 { 00340 //Convert TICKS to real milliseconds 00341 if (ticks > 0xffff / 100) { 00342 ticks = 0xffff; 00343 } else if (ticks == 0) { 00344 ticks = 1; 00345 } else { 00346 ticks *= 100; 00347 } 00348 00349 ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { 00350 if (entry->timer <= ticks) { 00351 //TX Process or timeout 00352 if (entry->wait_response) { 00353 //Timeout for NUD or Probe 00354 if (entry->nud_process) { 00355 tr_debug("NUD NA timeout"); 00356 if (entry->retry_count < 2) { 00357 entry->timer = randLIB_get_random_in_range(1, 900); 00358 entry->wait_response = false; 00359 } else { 00360 //Clear entry from active list 00361 ws_nud_state_clean(cur, entry); 00362 //Remove whole entry 00363 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry->neighbor_info); 00364 } 00365 } else { 00366 ws_nud_state_clean(cur, entry); 00367 } 00368 00369 } else { 00370 //Random TX wait period is over 00371 entry->wait_response = ws_nud_message_build(cur, entry->neighbor_info); 00372 if (!entry->wait_response) { 00373 if (entry->nud_process && entry->retry_count < 2) { 00374 entry->timer = randLIB_get_random_in_range(1, 900); 00375 } else { 00376 //Clear entry from active list 00377 //Remove and try again later on 00378 ws_nud_state_clean(cur, entry); 00379 } 00380 } else { 00381 entry->retry_count++; 00382 entry->timer = 5001; 00383 } 00384 } 00385 } else { 00386 entry->timer -= ticks; 00387 } 00388 } 00389 } 00390 00391 static fhss_ws_neighbor_timing_info_t *ws_get_neighbor_info(const fhss_api_t *api, uint8_t eui64[8]) 00392 { 00393 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_fhss_api(api); 00394 if (!cur || !cur->mac_parameters || !mac_neighbor_info(cur)) { 00395 return NULL; 00396 } 00397 mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), eui64, MAC_ADDR_MODE_64_BIT); 00398 if (!mac_neighbor) { 00399 return NULL; 00400 } 00401 ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, mac_neighbor->index ); 00402 if (!ws_neighbor) { 00403 return NULL; 00404 } 00405 return &ws_neighbor->fhss_data; 00406 } 00407 static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry *cur, const fhss_ws_configuration_t *fhss_configuration) 00408 { 00409 memcpy(cur->ws_info->hopping_schdule.channel_mask, fhss_configuration->channel_mask, sizeof(uint32_t) * 8); 00410 cur->ws_info->hopping_schdule.uc_fixed_channel = fhss_configuration->unicast_fixed_channel; 00411 cur->ws_info->hopping_schdule.bc_fixed_channel = fhss_configuration->broadcast_fixed_channel; 00412 cur->ws_info->hopping_schdule.uc_channel_function = fhss_configuration->ws_uc_channel_function; 00413 cur->ws_info->hopping_schdule.bc_channel_function = fhss_configuration->ws_bc_channel_function; 00414 cur->ws_info->hopping_schdule.fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval; 00415 cur->ws_info->hopping_schdule.fhss_broadcast_interval = fhss_configuration->fhss_broadcast_interval; 00416 cur->ws_info->hopping_schdule.fhss_uc_dwell_interval = fhss_configuration->fhss_uc_dwell_interval; 00417 cur->ws_info->hopping_schdule.fhss_bsi = fhss_configuration->bsi; 00418 } 00419 00420 static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur) 00421 { 00422 fhss_api_t *fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); 00423 00424 if (!fhss_api || (fhss_api && cur->ws_info->fhss_owner)) { 00425 // When FHSS doesn't exist yet, create one 00426 fhss_ws_configuration_t fhss_configuration; 00427 memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); 00428 ws_generate_channel_list(fhss_configuration.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); 00429 00430 // using bitwise AND operation for user set channel mask to remove channels not allowed in this device 00431 for (uint8_t n = 0; n < 8; n++) { 00432 fhss_configuration.channel_mask[n] &= cur->ws_info->fhss_channel_mask[n]; 00433 } 00434 00435 fhss_configuration.fhss_uc_dwell_interval = cur->ws_info->fhss_uc_dwell_interval; 00436 fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; 00437 fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_bc_channel_function; 00438 fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval; 00439 fhss_configuration.fhss_broadcast_interval = cur->ws_info->fhss_bc_interval; 00440 00441 if (!fhss_api) { 00442 fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); 00443 if (!fhss_api) { 00444 tr_error("fhss create failed"); 00445 return -1; 00446 } 00447 ns_sw_mac_fhss_register(cur->mac_api, fhss_api); 00448 cur->ws_info->fhss_owner = true; 00449 } else { 00450 //Configuration set 00451 ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); 00452 00453 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 00454 ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0); 00455 } else { 00456 //Clear OWN HOP 00457 ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff); 00458 } 00459 } 00460 } else { 00461 // Read defaults from the configuration to help FHSS testing 00462 const fhss_ws_configuration_t *fhss_configuration = ns_fhss_ws_configuration_get(fhss_api); 00463 if (!fhss_configuration) { 00464 // no configuration set yet 00465 return 0; 00466 } 00467 memcpy(cur->ws_info->fhss_channel_mask, fhss_configuration->channel_mask, sizeof(uint32_t) * 8); 00468 cur->ws_info->fhss_uc_channel_function = fhss_configuration->ws_uc_channel_function; 00469 cur->ws_info->fhss_bc_channel_function = fhss_configuration->ws_bc_channel_function; 00470 cur->ws_info->fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval; 00471 cur->ws_info->fhss_bc_interval = fhss_configuration->fhss_broadcast_interval; 00472 cur->ws_info->fhss_uc_dwell_interval = fhss_configuration->fhss_uc_dwell_interval; 00473 cur->ws_info->fhss_bc_fixed_channel = fhss_configuration->broadcast_fixed_channel; 00474 cur->ws_info->fhss_uc_fixed_channel = fhss_configuration->unicast_fixed_channel; 00475 } 00476 return 0; 00477 } 00478 static int8_t ws_fhss_set_defaults(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) 00479 { 00480 fhss_configuration->fhss_uc_dwell_interval = cur->ws_info->fhss_uc_dwell_interval; 00481 fhss_configuration->ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; 00482 fhss_configuration->ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_bc_channel_function; 00483 fhss_configuration->fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval; 00484 fhss_configuration->fhss_broadcast_interval = cur->ws_info->fhss_bc_interval; 00485 if (cur->ws_info->fhss_uc_fixed_channel != 0xffff) { 00486 fhss_configuration->unicast_fixed_channel = cur->ws_info->fhss_uc_fixed_channel; 00487 } 00488 fhss_configuration->broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel; 00489 ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); 00490 00491 // using bitwise AND operation for user set channel mask to remove channels not allowed in this device 00492 for (uint8_t n = 0; n < 8; n++) { 00493 fhss_configuration->channel_mask[n] &= cur->ws_info->fhss_channel_mask[n]; 00494 } 00495 return 0; 00496 } 00497 static int8_t ws_fhss_border_router_configure(protocol_interface_info_entry_t *cur) 00498 { 00499 // Read configuration of existing FHSS and start using the default values for any network 00500 fhss_ws_configuration_t fhss_configuration; 00501 memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); 00502 00503 if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) { 00504 memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); 00505 } 00506 ws_fhss_set_defaults(cur, &fhss_configuration); 00507 ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); 00508 ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); 00509 00510 return 0; 00511 } 00512 00513 static uint16_t ws_randomize_fixed_channel(uint16_t configured_fixed_channel, uint8_t number_of_channels) 00514 { 00515 if (configured_fixed_channel == 0xFFFF) { 00516 return randLIB_get_random_in_range(0, number_of_channels - 1); 00517 } else { 00518 return configured_fixed_channel; 00519 } 00520 } 00521 00522 static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur) 00523 { 00524 // Read configuration of existing FHSS and start using the default values for any network 00525 fhss_ws_configuration_t fhss_configuration; 00526 memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); 00527 00528 if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) { 00529 memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); 00530 } 00531 00532 fhss_configuration.ws_uc_channel_function = WS_FIXED_CHANNEL; 00533 fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL; 00534 fhss_configuration.fhss_broadcast_interval = 0; 00535 uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); 00536 uint8_t tmp_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); 00537 fhss_configuration.unicast_fixed_channel = tmp_uc_fixed_channel; 00538 fhss_configuration.broadcast_fixed_channel = tmp_bc_fixed_channel; 00539 ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); 00540 ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff); 00541 ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); 00542 00543 return 0; 00544 } 00545 00546 static int8_t ws_fhss_enable(protocol_interface_info_entry_t *cur) 00547 { 00548 const fhss_ws_configuration_t *fhss_configuration = ns_fhss_ws_configuration_get(cur->ws_info->fhss_api); 00549 00550 if (!cur->ws_info->fhss_api || !fhss_configuration) { 00551 return -1; 00552 } 00553 // Set the LLC information to follow the actual fhss settings 00554 ws_bootstrap_llc_hopping_update(cur, fhss_configuration); 00555 00556 // Set neighbor info callback 00557 if (ns_fhss_set_neighbor_info_fp(cur->ws_info->fhss_api, &ws_get_neighbor_info)) { 00558 return -1; 00559 } 00560 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 00561 ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0); 00562 } 00563 return 0; 00564 } 00565 00566 /* Sets the parent and broadcast schedule we are following 00567 * 00568 */ 00569 static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info, ws_parent_synch_e synch_req) 00570 { 00571 00572 fhss_ws_configuration_t fhss_configuration; 00573 if (!neighbor_info->ws_neighbor->broadcast_timing_info_stored) { 00574 tr_error("No BC timing info for set new parent"); 00575 return; 00576 } 00577 00578 memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); 00579 00580 // Learning broadcast network configuration 00581 if (neighbor_info->ws_neighbor->broadcast_shedule_info_stored) { 00582 if (synch_req != WS_EAPOL_PARENT_SYNCH) { 00583 ws_fhss_set_defaults(cur, &fhss_configuration); 00584 } 00585 fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function; 00586 if (fhss_configuration.ws_bc_channel_function == WS_FIXED_CHANNEL) { 00587 cur->ws_info->hopping_schdule.bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel; 00588 cur->ws_info->fhss_bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel; 00589 } 00590 fhss_configuration.bsi = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id; 00591 fhss_configuration.fhss_bc_dwell_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval; 00592 fhss_configuration.fhss_broadcast_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_interval; 00593 fhss_configuration.broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel; 00594 neighbor_info->ws_neighbor->synch_done = true; 00595 } 00596 00597 ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); 00598 00599 // We have broadcast schedule set up set the broadcast parent schedule 00600 ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64 , &neighbor_info->ws_neighbor->fhss_data.bc_timing_info, synch_req != WS_PARENT_SOFT_SYNCH); 00601 00602 // Update LLC to follow updated fhss settings 00603 ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); 00604 } 00605 00606 void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info) 00607 { 00608 if (cur->ws_info->configuration_learned || !neighbor_info->ws_neighbor->broadcast_shedule_info_stored || !neighbor_info->ws_neighbor->broadcast_timing_info_stored) { 00609 return; 00610 } 00611 00612 if (ws_bootstrap_candidate_parent_get(cur, neighbor_info->neighbor->mac64 , false) == NULL) { 00613 return; 00614 } 00615 00616 //Store Brodacst Shedule 00617 if (!neighbor_info->ws_neighbor->synch_done) { 00618 ws_bootstrap_primary_parent_set(cur, neighbor_info, WS_EAPOL_PARENT_SYNCH); 00619 } else { 00620 ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64 , &neighbor_info->ws_neighbor->fhss_data.bc_timing_info, false); 00621 } 00622 } 00623 00624 static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entry *cur) 00625 { 00626 // Configure EUI64 for MAC if missing 00627 uint8_t mac64[8]; 00628 if (!cur->mac_api) { 00629 return; 00630 } 00631 00632 cur->mac_api->mac64_get(cur->mac_api, MAC_EXTENDED_DYNAMIC, mac64); 00633 00634 if (memcmp(mac64, ADDR_UNSPECIFIED, 8) == 0) { 00635 cur->mac_api->mac64_get(cur->mac_api, MAC_EXTENDED_READ_ONLY, mac64); 00636 } 00637 00638 if (memcmp(mac64, ADDR_UNSPECIFIED, 8) == 0) { 00639 // Generate random mac because it was not available 00640 randLIB_get_n_bytes_random(mac64, 8); 00641 mac64[0] |= 2; //Set Local Bit 00642 mac64[0] &= ~1; //Clear multicast bit 00643 00644 tr_info("Generated random MAC %s", trace_array(mac64, 8)); 00645 } 00646 mac_helper_mac64_set(cur, mac64); 00647 00648 memcpy(cur->iid_eui64, mac64, 8); 00649 /* Invert U/L Bit */ 00650 cur->iid_eui64[0] ^= 2; 00651 memcpy(cur->iid_slaac, cur->iid_eui64, 8); 00652 00653 } 00654 00655 /* \return 0x0100 to 0xFFFF ETX value (8 bit fraction) 00656 * \return 0xFFFF address not associated 00657 * \return 0x0000 address unknown or other error 00658 * \return 0x0001 no ETX statistics on this interface 00659 */ 00660 uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr_type, const uint8_t *addr_ptr) 00661 { 00662 00663 uint16_t etx; 00664 if (!addr_ptr || !interface) { 00665 return 0; 00666 } 00667 00668 uint8_t attribute_index; 00669 00670 mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), addr_ptr + PAN_ID_LEN, addr_type); 00671 if (!mac_neighbor) { 00672 return 0xffff; 00673 } 00674 attribute_index = mac_neighbor->index ; 00675 ws_neighbor_class_entry_t *ws_neighbour = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, attribute_index); 00676 etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, attribute_index); 00677 00678 if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 00679 if (!ws_neighbour || !etx_entry) { 00680 return 0xffff; 00681 } 00682 } else { 00683 00684 if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 /*|| 00685 !ws_neighbour->candidate_parent*/) { 00686 // if RSL value is not good enough candidate parent flag is removed and device not accepted as parent 00687 //tr_debug("ws_etx_read not valid params"); 00688 return 0xffff; 00689 } 00690 00691 //If we are not following gbobal Broadcast synch 00692 if (!interface->ws_info->pan_information.use_parent_bs) { 00693 //We must know both information's here 00694 if (!ws_neighbour->broadcast_shedule_info_stored || 00695 !ws_neighbour->broadcast_timing_info_stored) { 00696 return 0xffff; 00697 } 00698 } else { 00699 if (!ws_neighbour->broadcast_timing_info_stored) { 00700 //Global shedule is stored already 00701 tr_debug("ws_etx_read not valid NO BTI"); 00702 return 0xffff; 00703 } 00704 } 00705 } 00706 00707 etx = etx_local_etx_read(interface->id, attribute_index); 00708 if (etx == 0) { 00709 return 0xffff; 00710 } 00711 00712 //tr_debug("ws_etx_read etx:%d", etx); 00713 return etx; 00714 } 00715 bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq) 00716 { 00717 (void)cur; 00718 (void)seq; 00719 00720 if (unicast) { 00721 // Unicast NS is OK 00722 return false; 00723 } 00724 // Fail the resolution 00725 tr_warn("Link address lost for %s", trace_ipv6(entry->ip_address)); 00726 ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, entry); 00727 // True means we skip the message sending 00728 return true; 00729 } 00730 00731 static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) 00732 { 00733 int8_t ret_val = -1; 00734 00735 if (!cur) { 00736 return -1; 00737 } 00738 00739 if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) { 00740 tr_error("Interface not yet fully configured"); 00741 return -2; 00742 } 00743 if (ws_fhss_initialize(cur) != 0) { 00744 tr_error("fhss initialization failed"); 00745 return -3; 00746 } 00747 00748 // Save FHSS api 00749 cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); 00750 00751 ws_bootstrap_ll_address_validate(cur); 00752 00753 addr_interface_set_ll64(cur, NULL); 00754 cur->nwk_nd_re_scan_count = 0; 00755 //WS_interface_up(cur); 00756 // Trigger discovery for bootstrap 00757 ret_val = nwk_6lowpan_up(cur); 00758 if (ret_val) { 00759 goto cleanup; 00760 } 00761 00762 /* Disable SLLAO send/mandatory receive with the ARO */ 00763 cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true; 00764 /* Omit sending of NA if ARO SUCCESS */ 00765 cur->ipv6_neighbour_cache.omit_na_aro_success = true; 00766 /* Omit sending of NA and consider ACK to be success */ 00767 cur->ipv6_neighbour_cache.omit_na = true; 00768 // do not process AROs from NA. This is overriden by Wi-SUN specific failure handling 00769 cur->ipv6_neighbour_cache.recv_na_aro = false; 00770 /* Disable NUD Probes */ 00771 cur->ipv6_neighbour_cache.send_nud_probes = false; 00772 cur->ipv6_neighbour_cache.probe_avoided_routers = true; 00773 /*Replace NS handler to disable multicast address queries */ 00774 cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit; 00775 00776 dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE); 00777 dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used. 00778 dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC); 00779 00780 00781 ws_nud_table_reset(cur); 00782 00783 ws_bootstrap_candidate_table_reset(cur); 00784 00785 blacklist_params_set( 00786 WS_BLACKLIST_ENTRY_LIFETIME, 00787 WS_BLACKLIST_TIMER_MAX_TIMEOUT, 00788 WS_BLACKLIST_TIMER_TIMEOUT, 00789 WS_BLACKLIST_ENTRY_MAX_NBR, 00790 WS_BLACKLIST_PURGE_NBR, 00791 WS_BLACKLIST_PURGE_TIMER_TIMEOUT); 00792 00793 ws_bootstrap_event_discovery_start(cur); 00794 00795 return 0; 00796 cleanup: 00797 return ret_val; 00798 } 00799 00800 static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) 00801 { 00802 if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { 00803 return -1; 00804 } 00805 00806 tr_debug("Wi-SUN ifdown"); 00807 00808 // Reset WS information 00809 // ws_common_reset(cur) 00810 ws_llc_reset(cur); 00811 if (nd_proxy_downstream_interface_unregister(cur->id) != 0) { 00812 tr_warn("nd proxy unregister failed"); 00813 } 00814 ws_nud_table_reset(cur); 00815 dhcp_client_delete(cur->id); 00816 ws_eapol_relay_delete(cur); 00817 ws_eapol_auth_relay_delete(cur); 00818 ws_pae_controller_stop(cur); 00819 ws_bootstrap_candidate_table_reset(cur); 00820 blacklist_clear(); 00821 00822 return nwk_6lowpan_down(cur); 00823 } 00824 00825 void ws_bootstrap_configuration_reset(protocol_interface_info_entry_t *cur) 00826 { 00827 // Configure IP stack to operate as Wi-SUN node 00828 00829 // Do not process beacons 00830 cur->mac_parameters->beacon_ind = NULL; 00831 cur->mac_parameters->mac_security_level = 0; 00832 00833 // Set default parameters to interface 00834 cur->configure_flags = INTERFACE_BOOTSTRAP_DEFINED; 00835 cur->configure_flags |= INTERFACE_SECURITY_DEFINED; 00836 cur->lowpan_info = 0; 00837 00838 switch (cur->bootsrap_mode) { 00839 // case NET_6LOWPAN_SLEEPY_HOST: 00840 case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST: 00841 break; 00842 00843 case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER: 00844 case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER: 00845 cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE; 00846 break; 00847 00848 default: 00849 tr_err("Invalid bootstrap_mode"); 00850 } 00851 00852 cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; 00853 cur->ws_info->network_pan_id = 0xffff; 00854 cur->ws_info->trickle_pas_running = false; 00855 cur->ws_info->trickle_pa_running = false; 00856 cur->ws_info->trickle_pcs_running = false; 00857 cur->ws_info->trickle_pc_running = false; 00858 00859 //cur->mac_security_key_usage_update_cb = ws_management_mac_security_key_update_cb; 00860 return; 00861 } 00862 00863 static bool ws_bootstrap_network_name_matches(const struct mcps_data_ie_list *ie_ext, const char *network_name_ptr) 00864 { 00865 if (!network_name_ptr || !ie_ext) { 00866 return false; 00867 } 00868 00869 ws_wp_network_name_t network_name; 00870 if (!ws_wp_nested_network_name_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &network_name)) { 00871 tr_warn("No network name IE"); 00872 return false; 00873 } 00874 00875 if (network_name_ptr == NULL || strncmp(network_name_ptr, (char *)network_name.network_name, network_name.network_name_length) != 0) { 00876 return false; 00877 } 00878 return true; 00879 } 00880 00881 static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interface_info_entry *cur, ws_pan_information_t *pan_information) 00882 { 00883 /* In Active state 00884 * 00885 * A consistent transmission is defined as a PAN Advertisement received by a node with PAN ID and 00886 * NETNAME-IE / Network Name matching that of the receiving node, and with a PAN-IE / Routing Cost 00887 * the same or worse than (bigger than or equal to) that of the receiving node. 00888 * 00889 * Inconsistent: 00890 * 00891 * Received Routing Cost is smaller than stored one 00892 * 00893 * A PAN Advertisement received by a node with PAN ID and NETNAME-IE / Network name matching 00894 * that of the receiving node, and PAN-IE / Routing Cost better than (smaller than) that of the receiving node. 00895 * 00896 */ 00897 00898 #ifdef WISUN_1_0_ERRATA_FIX 00899 // All messages are considered as consistent only Solicit will cause inconsistent 00900 trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); 00901 #else 00902 // Wi-SUN 1.0 specified functionality, causes extra inconsistencies when we hear higher rank advertisements 00903 if (pan_information->routing_cost >= ws_bootstrap_routing_cost_calculate(cur)) { 00904 trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); 00905 } else { 00906 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); 00907 } 00908 #endif 00909 } 00910 00911 static parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_info_entry_t *cur) 00912 { 00913 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 00914 tr_info("candidate list a:%s panid:%x cost:%d size:%d rssi:%d age:%"PRIu32, trace_array(entry->addr, 8), entry->pan_id, entry->pan_information.routing_cost, entry->pan_information.pan_size, entry->signal_dbm, protocol_core_monotonic_time - entry->age); 00915 } 00916 00917 return ns_list_get_first(&cur->ws_info->parent_list_reserved); 00918 } 00919 00920 static void ws_bootstrap_candidate_parent_store(parent_info_t *parent, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us, ws_pan_information_t *pan_information) 00921 { 00922 parent->ws_utt = *ws_utt; 00923 // Saved from unicast IE 00924 parent->ws_us = *ws_us; 00925 00926 // Saved from Pan information, do not overwrite pan_version as it is not valid here 00927 parent->pan_information.pan_size = pan_information->pan_size; 00928 parent->pan_information.routing_cost = pan_information->routing_cost; 00929 parent->pan_information.use_parent_bs = pan_information->use_parent_bs; 00930 parent->pan_information.rpl_routing_method = pan_information->rpl_routing_method; 00931 parent->pan_information.version = pan_information->version; 00932 00933 // Saved from message 00934 parent->timestamp = data->timestamp; 00935 parent->pan_id = data->SrcPANId; 00936 parent->link_quality = data->mpduLinkQuality; 00937 parent->signal_dbm = data->signal_dbm; 00938 memcpy(parent->addr, data->SrcAddr, 8); 00939 00940 parent->age = protocol_core_monotonic_time; 00941 } 00942 00943 static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur) 00944 { 00945 //Empty active list 00946 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_free) { 00947 ns_list_remove(&cur->ws_info->parent_list_free, entry); 00948 } 00949 00950 //Empty free list 00951 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 00952 ns_list_remove(&cur->ws_info->parent_list_reserved, entry); 00953 } 00954 //Add to free list to full 00955 for (int i = 0; i < WS_PARENT_LIST_SIZE; i++) { 00956 ns_list_add_to_end(&cur->ws_info->parent_list_free, &cur->ws_info->parent_info[i]); 00957 } 00958 } 00959 00960 static parent_info_t *ws_bootstrap_candidate_parent_allocate(protocol_interface_info_entry_t *cur, const uint8_t *addr) 00961 { 00962 parent_info_t *entry = ns_list_get_first(&cur->ws_info->parent_list_free); 00963 if (entry) { 00964 memcpy(entry->addr, addr, 8); 00965 ns_list_remove(&cur->ws_info->parent_list_free, entry); 00966 ns_list_add_to_end(&cur->ws_info->parent_list_reserved, entry); 00967 } else { 00968 // If there is no free entries always allocate the last one of reserved as it is the worst 00969 entry = ns_list_get_last(&cur->ws_info->parent_list_reserved); 00970 } 00971 return entry; 00972 } 00973 00974 static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, uint8_t *addr) 00975 { 00976 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 00977 if (memcmp(entry->addr, addr, 8) == 0) { 00978 ns_list_remove(&cur->ws_info->parent_list_reserved, entry); 00979 ns_list_add_to_end(&cur->ws_info->parent_list_free, entry); 00980 return; 00981 } 00982 } 00983 } 00984 00985 static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create) 00986 { 00987 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 00988 if (memcmp(entry->addr, addr, 8) == 0) { 00989 return entry; 00990 } 00991 } 00992 if (create) { 00993 return ws_bootstrap_candidate_parent_allocate(cur, addr); 00994 } 00995 return NULL; 00996 } 00997 00998 static bool ws_bootstrap_candidate_parent_compare(parent_info_t *p1, parent_info_t *p2) 00999 { 01000 // Return true if P2 is better 01001 // signal lower than threshold for both 01002 // pan_cost 01003 // signal quality 01004 01005 if (ws_neighbor_class_rsl_from_dbm_calculate(p1->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) && 01006 ws_neighbor_class_rsl_from_dbm_calculate(p2->signal_dbm) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) { 01007 // above threshold is always better than not. 01008 return true; 01009 } 01010 if (ws_neighbor_class_rsl_from_dbm_calculate(p2->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) && 01011 ws_neighbor_class_rsl_from_dbm_calculate(p1->signal_dbm) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) { 01012 // P2 is less than threshold and P1 is larger so P1 is always better. 01013 return false; 01014 } 01015 01016 // Select the lowest PAN cost 01017 uint16_t p1_pan_cost = (p1->pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (p1->pan_information.pan_size / PS_WEIGHT_FACTOR); 01018 uint16_t p2_pan_cost = (p2->pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (p2->pan_information.pan_size / PS_WEIGHT_FACTOR); 01019 if (p1_pan_cost > p2_pan_cost) { 01020 return true; 01021 } else if (p1_pan_cost < p2_pan_cost) { 01022 return false; 01023 } 01024 01025 // If pan cost is the same then we select the one we hear highest 01026 if (p1->signal_dbm < p2->signal_dbm) { 01027 return true; 01028 } 01029 return false; 01030 } 01031 01032 static void ws_bootstrap_candidate_list_clean(struct protocol_interface_info_entry *cur, uint8_t pan_max, uint32_t current_time, uint16_t pan_id) 01033 { 01034 int pan_count = 0; 01035 01036 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 01037 if ((current_time - entry->age) > WS_PARENT_LIST_MAX_AGE) { 01038 ns_list_remove(&cur->ws_info->parent_list_reserved, entry); 01039 ns_list_add_to_end(&cur->ws_info->parent_list_free, entry); 01040 continue; 01041 } 01042 if (entry->pan_id == pan_id) { 01043 // Same panid if there is more than limited amount free those 01044 pan_count++; 01045 if (pan_count > pan_max) { 01046 ns_list_remove(&cur->ws_info->parent_list_reserved, entry); 01047 ns_list_add_to_end(&cur->ws_info->parent_list_free, entry); 01048 continue; 01049 } 01050 } 01051 } 01052 } 01053 01054 static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry) 01055 { 01056 ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { 01057 if (entry == new_entry) { 01058 // own entry skip it 01059 continue; 01060 } 01061 if (ws_bootstrap_candidate_parent_compare(entry, new_entry)) { 01062 // New entry is better 01063 //tr_debug("candidate list new is better"); 01064 ns_list_remove(&cur->ws_info->parent_list_reserved, new_entry); 01065 ns_list_add_before(&cur->ws_info->parent_list_reserved, entry, new_entry); 01066 return; 01067 } 01068 } 01069 } 01070 01071 static void ws_bootstrap_pan_information_store(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us, ws_pan_information_t *pan_information) 01072 { 01073 01074 parent_info_t *new_entry; 01075 /* Have List of 20 heard neighbours 01076 * Order those as best based on pan cost 01077 * In single pan order based on signal quality 01078 * in single PAN limit the amount of devices to 5 01079 * If there is no advertisement heard for last hour Clear the neigbour. 01080 */ 01081 01082 // Discovery state processing 01083 //tr_info("neighbour: addr:%s panid:%x signal:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); 01084 01085 // Clean old entries 01086 ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY, protocol_core_monotonic_time, data->SrcPANId); 01087 01088 new_entry = ws_bootstrap_candidate_parent_get(cur, data->SrcAddr, true); 01089 if (!new_entry) { 01090 tr_warn("neighbour creation fail"); 01091 return; 01092 } 01093 // Safe the information 01094 ws_bootstrap_candidate_parent_store(new_entry, data, ws_utt, ws_us, pan_information); 01095 // set to the correct place in list 01096 ws_bootstrap_candidate_parent_sort(cur, new_entry); 01097 01098 return; 01099 } 01100 01101 static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) 01102 { 01103 01104 //Validate Pan Conrfirmation is at packet 01105 ws_pan_information_t pan_information; 01106 if (!ws_wp_nested_pan_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_information)) { 01107 // Corrupted 01108 tr_error("No pan information"); 01109 return; 01110 } 01111 01112 // Check pan flags so that it is valid 01113 if (!pan_information.rpl_routing_method) { 01114 // NOT RPL routing 01115 //tr_warn("Not supported routing"); 01116 return; 01117 } 01118 01119 // Store heard pans and possible candidate parents 01120 ws_bootstrap_pan_information_store(cur, data, ws_utt, ws_us, &pan_information); 01121 01122 if (!(ws_bootstrap_state_active(cur) || 01123 ws_bootstrap_state_wait_rpl(cur))) { 01124 // During discovery/eapol/config learn we dont do further processing for advertisements 01125 return; 01126 } 01127 // Active state processing 01128 //tr_debug("Advertisement active"); 01129 01130 // In active operation less neighbours per pan is allowed 01131 ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_ACTIVE, protocol_core_monotonic_time, data->SrcPANId); 01132 01133 // Check if valid PAN 01134 if (data->SrcPANId != cur->ws_info->network_pan_id) { 01135 return; 01136 } 01137 01138 // Save route cost for all known neighbors 01139 llc_neighbour_req_t neighbor_info; 01140 neighbor_info.neighbor = NULL; 01141 if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { 01142 neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost; 01143 } 01144 01145 ws_bootstrap_pan_advertisement_analyse_active(cur, &pan_information); 01146 01147 // Learn latest network information 01148 if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && neighbor_info.neighbor) { 01149 uint8_t ll_address[16]; 01150 ws_bootsrap_create_ll_address(ll_address, neighbor_info.neighbor->mac64 ); 01151 01152 if (rpl_control_is_dodag_parent(cur, ll_address)) { 01153 // automatic network size adjustment learned 01154 if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC && 01155 cur->ws_info->pan_information.pan_size != pan_information.pan_size) { 01156 ws_common_network_size_configure(cur, pan_information.pan_size); 01157 } 01158 01159 cur->ws_info->pan_information.pan_size = pan_information.pan_size; 01160 cur->ws_info->pan_information.routing_cost = pan_information.routing_cost; 01161 cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method; 01162 cur->ws_info->pan_information.use_parent_bs = pan_information.use_parent_bs; 01163 cur->ws_info->pan_information.version = pan_information.version; 01164 } 01165 } 01166 } 01167 01168 static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) 01169 { 01170 01171 (void)data; 01172 (void)ws_utt; 01173 (void)ws_us; 01174 /* 01175 * An inconsistent transmission is defined as: 01176 * A PAN Advertisement Solicit with NETNAME-IE matching that of the receiving node. 01177 */ 01178 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); 01179 /* 01180 * A consistent transmission is defined as 01181 * a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node. 01182 */ 01183 trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit); 01184 01185 /* 01186 * Optimized PAN discovery to select faster the parent if we hear solicit from someone else 01187 */ 01188 01189 if (ws_bootstrap_state_discovery(cur) && 01190 cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin + 50) { 01191 cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; 01192 tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); 01193 } 01194 } 01195 01196 01197 static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) 01198 { 01199 01200 uint16_t pan_version; 01201 ws_bs_ie_t ws_bs_ie; 01202 uint8_t *gtkhash_ptr; 01203 01204 if (data->SrcPANId != cur->ws_info->network_pan_id) { 01205 return; 01206 } 01207 ws_bt_ie_t ws_bt_ie; 01208 if (!ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt_ie)) { 01209 tr_warn("BT-IE"); 01210 return; 01211 } 01212 01213 /* 01214 * A consistent transmission is defined as a PAN Configuration with a PAN-ID matching that of the receiving node and 01215 * a PANVER-IE / PAN Version greater than or equal to the receiving node’s current PAN version. 01216 * 01217 * A inconsistent transmission is defined as: 01218 * 01219 * A PAN Configuration with PAN-ID matching that of the receiving node and a 01220 * PANVER-IE / PAN Version that is less than the receiving node’s current PAN version. 01221 */ 01222 01223 // TODO Add this to neighbor table 01224 // TODO save all information from config message if version number has changed 01225 01226 if (!ws_wp_nested_pan_version_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_version)) { 01227 // Corrupted 01228 tr_warn("no version"); 01229 return; 01230 } 01231 01232 gtkhash_ptr = ws_wp_nested_gtkhash_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength); 01233 01234 if (!gtkhash_ptr) { 01235 // Corrupted 01236 tr_error("No gtk hash"); 01237 return; 01238 } 01239 01240 if (!ws_wp_nested_bs_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_bs_ie)) { 01241 // Corrupted 01242 tr_error("No broadcast schedule"); 01243 return; 01244 } 01245 llc_neighbour_req_t neighbor_info; 01246 bool neighbour_pointer_valid; 01247 01248 if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 01249 //If we are border router or learned configuration we only update already learned neighbours. 01250 neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false); 01251 01252 } else { 01253 neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true); 01254 if (!neighbour_pointer_valid) { 01255 return; 01256 } 01257 } 01258 01259 if (neighbour_pointer_valid) { 01260 etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index ); 01261 //Update Neighbor Broadcast and Unicast Parameters 01262 ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); 01263 ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us); 01264 ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp); 01265 ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); 01266 } 01267 01268 if (cur->ws_info->configuration_learned) { 01269 tr_info("PAN Config analyse own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); 01270 if (cur->ws_info->pan_information.pan_version == pan_version) { 01271 // Same version heard so it is consistent 01272 trickle_consistent_heard(&cur->ws_info->trickle_pan_config); 01273 if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { 01274 ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_SOFT_SYNCH); 01275 } 01276 // no need to process more 01277 return; 01278 } else { 01279 // received version is different so we need to reset the trickle 01280 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); 01281 if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { 01282 ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); 01283 } 01284 if (common_serial_number_greater_16(cur->ws_info->pan_information.pan_version, pan_version)) { 01285 // older version heard ignoring the message 01286 return; 01287 } 01288 } 01289 } 01290 01291 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 01292 //Border router does not learn network information 01293 return; 01294 } 01295 01296 /* 01297 * Learn new information from neighbor 01298 */ 01299 tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); 01300 01301 // restart PAN version timer 01302 cur->ws_info->pan_version_timeout_timer = ws_common_version_timeout_get(cur->ws_info->network_size_config); 01303 cur->ws_info->pan_information.pan_version = pan_version; 01304 01305 ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr); 01306 01307 ws_pae_controller_nw_key_index_update(cur, data->Key.KeyIndex - 1); 01308 01309 if (!cur->ws_info->configuration_learned) { 01310 // Generate own hopping schedules Follow first parent broadcast and plans and also use same unicast dwell 01311 tr_info("learn network configuration"); 01312 cur->ws_info->configuration_learned = true; 01313 // return to state machine after 1-2 s 01314 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, 20); 01315 // enable frequency hopping for unicast channel and start listening first neighbour 01316 ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); 01317 // set neighbor as priority parent clear if there is others 01318 protocol_6lowpan_neighbor_priority_clear_all(cur->id, PRIORITY_1ST); 01319 neighbor_info.neighbor->link_role = PRIORITY_PARENT_NEIGHBOUR; 01320 } 01321 } 01322 01323 static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) 01324 { 01325 if (data->SrcPANId != cur->ws_info->network_pan_id) { 01326 return; 01327 } 01328 01329 /* TODO smart neighbour process 01330 * 01331 * Unsecure packet we cant trust the device? 01332 * 01333 * Question mark in specification also present, now we create neighbour. 01334 * this is moved in future to NS/ND processing triggered by RPL 01335 * 01336 */ 01337 01338 llc_neighbour_req_t neighbor_info; 01339 if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { 01340 etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index ); 01341 ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); 01342 ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us); 01343 } 01344 01345 01346 01347 /* 01348 * A consistent transmission is defined as a PAN Configuration Solicit with 01349 * a PAN-ID matching that of the receiving node and a NETNAME-IE / Network Name 01350 * matching that configured on the receiving node. 01351 */ 01352 trickle_consistent_heard(&cur->ws_info->trickle_pan_config_solicit); 01353 /* 01354 * inconsistent transmission is defined as either: 01355 * A PAN Configuration Solicit with a PAN-ID matching that of the receiving node and 01356 * a NETNAME-IE / Network Name matching the network name configured on the receiving 01357 */ 01358 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); 01359 } 01360 static bool ws_channel_plan_zero_compare(ws_channel_plan_zero_t *rx_plan, ws_hopping_schedule_t *hopping_schdule) 01361 { 01362 if (rx_plan->operation_class != hopping_schdule->operating_class) { 01363 return false; 01364 } else if (rx_plan->regulator_domain != hopping_schdule->regulatory_domain) { 01365 return false; 01366 } 01367 return true; 01368 } 01369 01370 static bool ws_channel_plan_one_compare(ws_channel_plan_one_t *rx_plan, ws_hopping_schedule_t *hopping_schdule) 01371 { 01372 uint16_t num_of_channel = hopping_schdule->number_of_channels; 01373 if (rx_plan->ch0 != hopping_schdule->ch0_freq) { 01374 return false; 01375 } else if (rx_plan->channel_spacing != hopping_schdule->channel_spacing) { 01376 return false; 01377 } else if (rx_plan->number_of_channel != num_of_channel) { 01378 return false; 01379 } 01380 return true; 01381 } 01382 01383 01384 01385 01386 static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type) 01387 { 01388 01389 if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) { 01390 // Not from long address 01391 return; 01392 } 01393 //Validate network name 01394 switch (message_type) { 01395 case WS_FT_PAN_ADVERT: 01396 case WS_FT_PAN_ADVERT_SOL: 01397 case WS_FT_PAN_CONF_SOL: 01398 //Check Network Name 01399 if (!ws_bootstrap_network_name_matches(ie_ext, cur->ws_info->network_name)) { 01400 // Not in our network 01401 return; 01402 } 01403 break; 01404 case WS_FT_PAN_CONF: 01405 break; 01406 default: 01407 return; 01408 } 01409 ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1); 01410 //UTT-IE and US-IE are mandatory for all Asynch Messages 01411 ws_utt_ie_t ws_utt; 01412 if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) { 01413 // Corrupted 01414 return; 01415 } 01416 01417 ws_us_ie_t ws_us; 01418 if (!ws_wp_nested_us_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_us)) { 01419 // Corrupted 01420 return; 01421 } 01422 01423 //Compare Unicast channel Plan 01424 if (ws_us.channel_plan != cur->ws_info->hopping_schdule.channel_plan) { 01425 return; 01426 } 01427 01428 if (ws_us.channel_plan == 0) { 01429 if (!ws_channel_plan_zero_compare(&ws_us.plan.zero, &cur->ws_info->hopping_schdule)) { 01430 return; 01431 } 01432 } else if (ws_us.channel_plan == 1) { 01433 if (!ws_channel_plan_one_compare(&ws_us.plan.one, &cur->ws_info->hopping_schdule)) { 01434 return; 01435 } 01436 } 01437 01438 //Handle Message's 01439 switch (message_type) { 01440 case WS_FT_PAN_ADVERT: 01441 // Analyse Advertisement 01442 tr_info("received ADVERT Src:%s panid:%x rssi:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); 01443 ws_bootstrap_pan_advertisement_analyse(cur, data, ie_ext, &ws_utt, &ws_us); 01444 break; 01445 case WS_FT_PAN_ADVERT_SOL: 01446 tr_info("received ADVERT SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); 01447 ws_bootstrap_pan_advertisement_solicit_analyse(cur, data, &ws_utt, &ws_us); 01448 break; 01449 case WS_FT_PAN_CONF: 01450 tr_info("received CONFIG Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); 01451 ws_bootstrap_pan_config_analyse(cur, data, ie_ext, &ws_utt, &ws_us); 01452 break; 01453 default: 01454 tr_info("received CONFIG SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); 01455 ws_bootstrap_pan_config_solicit_analyse(cur, data, &ws_utt, &ws_us); 01456 break; 01457 } 01458 } 01459 01460 static void ws_bootstrap_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) 01461 { 01462 ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1); 01463 (void)interface; 01464 (void)asynch_message; 01465 } 01466 01467 uint32_t ws_time_from_last_unicast_traffic(uint32_t current_time_stamp, ws_neighbor_class_entry_t *ws_neighbor) 01468 { 01469 uint32_t time_from_last_unicast_shedule = current_time_stamp; 01470 01471 //Time from last RX unicast in us 01472 time_from_last_unicast_shedule -= ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp; 01473 time_from_last_unicast_shedule /= 1000000; //Convert to seconds 01474 return time_from_last_unicast_shedule; 01475 } 01476 01477 static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_entry *interface) 01478 { 01479 uint8_t ll_target[16]; 01480 01481 if (mac_neighbor_info(interface)->neighbour_list_size <= mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT) { 01482 // Enough neighbor entries 01483 return; 01484 } 01485 memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8); 01486 01487 uint32_t current_time_stamp = ns_sw_mac_read_current_timestamp(interface->mac_api); 01488 01489 mac_neighbor_table_entry_t *neighbor_entry_ptr = NULL; 01490 ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) { 01491 ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, cur->index); 01492 01493 if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) { 01494 //This is our primary parent we cannot delete 01495 continue; 01496 } 01497 01498 if (cur->nud_active || ws_neighbor->accelerated_etx_probe || ws_neighbor->negative_aro_send) { 01499 //If NUD process is active do not trig 01500 continue; 01501 } 01502 01503 if (neighbor_entry_ptr && neighbor_entry_ptr->lifetime < cur->lifetime) { 01504 // We have already shorter link entry found this cannot replace it 01505 continue; 01506 } 01507 01508 if (cur->trusted_device) { 01509 01510 if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) { 01511 // We have registered entry so we have been selected as parent 01512 continue; 01513 } 01514 01515 memcpy(ll_target + 8, cur->mac64, 8); 01516 ll_target[8] ^= 2; 01517 01518 if (rpl_control_is_dodag_parent(interface, ll_target)) { 01519 // Possible parent is limited to 3 by default? 01520 continue; 01521 } 01522 } 01523 01524 //Read current timestamp 01525 uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor); 01526 uint32_t min_timeout; 01527 if (interface->ws_info->network_size_config == NETWORK_SIZE_LARGE) { 01528 min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE; 01529 } else { 01530 min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; 01531 } 01532 if (time_from_last_unicast_shedule > min_timeout) { 01533 //Accept only Enough Old Device 01534 if (!neighbor_entry_ptr) { 01535 //Accept first compare 01536 neighbor_entry_ptr = cur; 01537 } else { 01538 uint32_t compare_neigh_time = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor_entry_ptr->index )); 01539 if (compare_neigh_time < time_from_last_unicast_shedule) { 01540 //Accept older RX timeout allways 01541 neighbor_entry_ptr = cur; 01542 } 01543 } 01544 } 01545 } 01546 if (neighbor_entry_ptr) { 01547 tr_info("dropped oldest neighbour %s", trace_array(neighbor_entry_ptr->mac64 , 8)); 01548 mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_entry_ptr); 01549 } 01550 01551 } 01552 01553 static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new) 01554 { 01555 neighbor_buffer->ws_neighbor = NULL; 01556 neighbor_buffer->neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), mac_64, ADDR_802_15_4_LONG ); 01557 if (neighbor_buffer->neighbor) { 01558 neighbor_buffer->ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor_buffer->neighbor->index ); 01559 if (!neighbor_buffer->ws_neighbor) { 01560 return false; 01561 } 01562 return true; 01563 } 01564 if (!request_new) { 01565 return false; 01566 } 01567 01568 uint8_t ll_target[16]; 01569 ws_bootsrap_create_ll_address(ll_target, mac_64); 01570 01571 if (blacklist_reject(ll_target)) { 01572 // Rejected by blacklist 01573 return false; 01574 } 01575 01576 ws_bootstrap_neighbor_table_clean(interface); 01577 01578 neighbor_buffer->neighbor = ws_bootstrap_mac_neighbor_add(interface, mac_64); 01579 01580 if (!neighbor_buffer->neighbor) { 01581 return false; 01582 } 01583 01584 neighbor_buffer->ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor_buffer->neighbor->index ); 01585 if (!neighbor_buffer->ws_neighbor) { 01586 mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_buffer->neighbor); 01587 return false; 01588 } 01589 return true; 01590 } 01591 01592 static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface) 01593 { 01594 uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false); 01595 //TODO check bootstarap state for review 01596 //if we have enough candidates at list do not accept new multicast neighbours 01597 if (parent_candidate_size > interface->ws_info->rpl_parent_candidate_max) { 01598 return false; 01599 } 01600 01601 parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true); 01602 //If we have already enough parent selected Candidates count is bigger than configured 01603 if (parent_candidate_size >= interface->ws_info->rpl_selected_parent_max) { 01604 return false; 01605 } 01606 01607 return true; 01608 } 01609 01610 01611 static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) 01612 { 01613 01614 protocol_interface_info_entry_t *cur = user_data; 01615 lowpan_adaptation_remove_free_indirect_table(cur, entry_ptr); 01616 // Sleepy host 01617 if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { 01618 mac_data_poll_protocol_poll_mode_decrement(cur); 01619 } 01620 01621 //TODO State machine check here 01622 01623 if (entry_ptr->ffd_device ) { 01624 protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_ptr->mac16 ); 01625 protocol_6lowpan_release_long_link_address_from_neighcache(cur, entry_ptr->mac64 ); 01626 } 01627 01628 //NUD Process Clear Here 01629 ws_nud_entry_remove(cur, entry_ptr); 01630 01631 ws_bootstrap_neighbor_delete(cur, entry_ptr); 01632 } 01633 01634 static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) 01635 { 01636 uint32_t time_from_start = entry_ptr->link_lifetime - entry_ptr->lifetime ; 01637 bool activate_nud = false; 01638 protocol_interface_info_entry_t *cur = user_data; 01639 01640 ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, entry_ptr->index ); 01641 etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, entry_ptr->index ); 01642 01643 if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send) { 01644 return false; 01645 } 01646 01647 uint8_t ll_address[16]; 01648 01649 if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT) { 01650 01651 ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64 ); 01652 01653 if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) { 01654 if (!ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64 )) { 01655 //NUD Not needed for if neighbour is not child or parent candidate 01656 return false; 01657 } 01658 } 01659 01660 if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT * 1.5) { 01661 activate_nud = true; 01662 } else { 01663 uint16_t switch_prob = randLIB_get_random_in_range(0, WS_NUD_RANDOM_SAMPLE_LENGTH - 1); 01664 //Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5 01665 if (switch_prob < WS_NUD_RANDOM_COMPARE) { 01666 activate_nud = true; 01667 } 01668 } 01669 } else if (etx_entry->etx_samples < WS_NEIGBOR_ETX_SAMPLE_MAX) { 01670 //Take Random number for trig a prope. 01671 //ETX Sample 0: random 1-8 01672 //ETX Sample 1: random 2-16 01673 //ETX Sample 2: random 4-32 01674 if (etx_entry->etx_samples == 0 && ws_neighbor->accelerated_etx_probe) { 01675 //Accept quick Probe for init ETX 01676 activate_nud = true; 01677 } else { 01678 01679 ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64 ); 01680 if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) { 01681 return false; 01682 } 01683 01684 uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples; 01685 uint32_t time_block = 1 << etx_entry->etx_samples; 01686 if (time_from_start >= probe_period) { 01687 //tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples); 01688 activate_nud = true; 01689 } else if (time_from_start > time_block) { 01690 uint16_t switch_prob = randLIB_get_random_in_range(0, probe_period - 1); 01691 //Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5 01692 if (switch_prob < 2) { 01693 //tr_debug("Link Probe test with jitter %"PRIu32", sample %u", time_from_start, etx_entry->etx_samples); 01694 activate_nud = true; 01695 } 01696 } 01697 } 01698 } 01699 01700 if (!activate_nud) { 01701 return false; 01702 } 01703 01704 ws_nud_table_entry_t *entry = ws_nud_entry_get_free(cur); 01705 if (!entry) { 01706 return false; 01707 } 01708 entry->neighbor_info = entry_ptr; 01709 if (ws_neighbor->accelerated_etx_probe) { 01710 ws_neighbor->accelerated_etx_probe = false; 01711 entry->timer = 1; 01712 } 01713 01714 if (etx_entry->etx_samples >= WS_NEIGBOR_ETX_SAMPLE_MAX) { 01715 entry->nud_process = true; 01716 } 01717 return true; 01718 } 01719 01720 int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) 01721 { 01722 int ret_val = 0; 01723 01724 ws_neighbor_class_t neigh_info; 01725 neigh_info.neigh_info_list = NULL; 01726 neigh_info.list_size = 0; 01727 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01728 if (!cur) { 01729 return -1; 01730 } 01731 01732 mac_description_storage_size_t buffer; 01733 if (!cur->mac_api || !cur->mac_api->mac_storage_sizes_get || cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) { 01734 return -2; 01735 } 01736 01737 if (buffer.key_description_table_size < 4) { 01738 tr_err("MAC key_description_table_size too short %d<4", buffer.key_description_table_size); 01739 return -2; 01740 } 01741 01742 if (ns_sw_mac_enable_frame_counter_per_key(cur->mac_api, true)) { 01743 return -1; 01744 } 01745 01746 if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) { 01747 return -1; 01748 } 01749 if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT)) { 01750 etx_storage_list_allocate(cur->id, 0); 01751 return -1; 01752 } 01753 01754 etx_max_update_set(WS_ETX_MAX_UPDATE); 01755 01756 if (blacklist_init() != 0) { 01757 tr_err("MLE blacklist init failed."); 01758 return -1; 01759 } 01760 01761 switch (bootstrap_mode) { 01762 // case NET_6LOWPAN_SLEEPY_HOST: 01763 case NET_6LOWPAN_HOST: 01764 cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST; 01765 break; 01766 case NET_6LOWPAN_ROUTER: 01767 cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER; 01768 break; 01769 case NET_6LOWPAN_BORDER_ROUTER: 01770 cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER; 01771 break; 01772 default: 01773 return -3; 01774 } 01775 01776 if (!ws_neighbor_class_alloc(&neigh_info, buffer.device_decription_table_size)) { 01777 ret_val = -1; 01778 goto init_fail; 01779 } 01780 01781 //Disable allways by default 01782 lowpan_adaptation_interface_mpx_register(interface_id, NULL, 0); 01783 01784 mac_neighbor_table_delete(mac_neighbor_info(cur)); 01785 mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size, ws_neighbor_entry_remove_notify 01786 , ws_neighbor_entry_nud_notify, cur); 01787 if (!mac_neighbor_info(cur)) { 01788 ret_val = -1; 01789 goto init_fail; 01790 } 01791 01792 ws_llc_create(cur, &ws_bootstrap_asynch_ind, &ws_bootstrap_asynch_confirm, &ws_bootstrap_neighbor_info_request); 01793 01794 mpx_api_t *mpx_api = ws_llc_mpx_api_get(cur); 01795 if (!mpx_api) { 01796 ret_val = -4; 01797 goto init_fail; 01798 } 01799 01800 if (ws_common_allocate_and_init(cur) < 0) { 01801 ret_val = -4; 01802 goto init_fail; 01803 } 01804 01805 if (ws_bootstrap_tasklet_init(cur) != 0) { 01806 ret_val = -4; 01807 goto init_fail; 01808 } 01809 01810 //Register MPXUser to adapatation layer 01811 if (lowpan_adaptation_interface_mpx_register(interface_id, mpx_api, MPX_LOWPAN_ENC_USER_ID) != 0) { 01812 ret_val = -4; 01813 goto init_fail; 01814 } 01815 01816 //Init PAE controller and set callback 01817 if (ws_pae_controller_init(cur) < 0) { 01818 ret_val = -4; 01819 goto init_fail; 01820 } 01821 if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment) < 0) { 01822 ret_val = -4; 01823 goto init_fail; 01824 } 01825 01826 //Init EAPOL PDU handler and register it to MPX 01827 if (ws_eapol_pdu_init(cur) < 0) { 01828 ret_val = -4; 01829 goto init_fail; 01830 } 01831 if (ws_eapol_pdu_mpx_register(cur, mpx_api, MPX_KEY_MANAGEMENT_ENC_USER_ID != 0)) { 01832 ret_val = -4; 01833 // add deallocs 01834 goto init_fail; 01835 } 01836 01837 cur->if_up = ws_bootstrap_up; 01838 cur->if_down = ws_bootstrap_down; 01839 cur->ws_info->neighbor_storage = neigh_info; 01840 cur->etx_read_override = ws_etx_read; 01841 01842 ws_bootstrap_configuration_reset(cur); 01843 addr_notification_register(ws_bootstrap_address_notification_cb); 01844 //Enable MAC Security by pass 01845 mlme_set_t set_req; 01846 bool state = true; 01847 set_req.attr = macAcceptByPassUnknowDevice; 01848 set_req.attr_index = 0; 01849 set_req.value_pointer = &state; 01850 set_req.value_size = sizeof(bool); 01851 cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req); 01852 01853 // Set the default parameters for MPL 01854 cur->mpl_proactive_forwarding = true; 01855 01856 cur->mpl_data_trickle_params.Imin = MPL_MS_TO_TICKS(DATA_MESSAGE_IMIN); 01857 cur->mpl_data_trickle_params.Imax = MPL_MS_TO_TICKS(DATA_MESSAGE_IMAX); 01858 cur->mpl_data_trickle_params.TimerExpirations = DATA_MESSAGE_TIMER_EXPIRATIONS; 01859 cur->mpl_data_trickle_params.k = 8; 01860 01861 // Specification is ruling out the compression mode, but we are now doing it. 01862 cur->mpl_seed = true; 01863 cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_IPV6_SRC_FOR_DOMAIN; 01864 cur->mpl_seed_set_entry_lifetime = MPL_SEED_SET_ENTRY_TIMEOUT; 01865 01866 cur->mpl_control_trickle_params.TimerExpirations = 0; 01867 01868 mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL); 01869 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_NODES); 01870 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS); 01871 01872 return 0; 01873 01874 //Error handling and free memory 01875 init_fail: 01876 lowpan_adaptation_interface_mpx_register(interface_id, NULL, 0); 01877 ws_eapol_pdu_mpx_register(cur, NULL, 0); 01878 mac_neighbor_table_delete(mac_neighbor_info(cur)); 01879 etx_storage_list_allocate(cur->id, 0); 01880 ws_neighbor_class_dealloc(&neigh_info); 01881 ws_llc_delete(cur); 01882 ws_eapol_pdu_delete(cur); 01883 ws_pae_controller_delete(cur); 01884 return ret_val; 01885 } 01886 01887 int ws_bootstrap_restart(int8_t interface_id) 01888 { 01889 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01890 if (!cur || !cur->ws_info) { 01891 return -1; 01892 } 01893 ws_bootstrap_event_discovery_start(cur); 01894 return 0; 01895 } 01896 01897 int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_channel_configuration_s rf_configs) 01898 { 01899 mlme_set_t set_request; 01900 // Set RF configuration 01901 set_request.attr = macRfConfiguration; 01902 set_request.value_pointer = &rf_configs; 01903 set_request.value_size = sizeof(phy_rf_channel_configuration_s); 01904 cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); 01905 // Set Ack wait duration 01906 uint16_t ack_wait_symbols = WS_ACK_WAIT_SYMBOLS + (WS_TACK_MAX_MS * (rf_configs.datarate / 1000)); 01907 set_request.attr = macAckWaitDuration; 01908 set_request.value_pointer = &ack_wait_symbols; 01909 set_request.value_size = sizeof(ack_wait_symbols); 01910 cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); 01911 // Set multi CSMA-CA configuration 01912 mlme_multi_csma_ca_param_t multi_csma_params = {WS_NUMBER_OF_CSMA_PERIODS, WS_CSMA_MULTI_CCA_INTERVAL}; 01913 set_request.attr = macMultiCSMAParameters; 01914 set_request.value_pointer = &multi_csma_params; 01915 set_request.value_size = sizeof(mlme_multi_csma_ca_param_t); 01916 cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); 01917 return 0; 01918 } 01919 01920 int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) 01921 { 01922 mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL); 01923 01924 if (mac_neighbor) { 01925 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), mac_neighbor); 01926 } 01927 return 0; 01928 } 01929 01930 int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) 01931 { 01932 rpl_control_neighbor_delete(cur, ll_address); 01933 ws_bootstrap_neighbor_remove(cur, ll_address); 01934 return 0; 01935 } 01936 01937 static void ws_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator) 01938 { 01939 mlme_start_t start_req; 01940 memset(&start_req, 0, sizeof(mlme_start_t)); 01941 01942 cur->mac_parameters->pan_id = panid; 01943 cur->mac_parameters->mac_channel = channel; 01944 01945 start_req.PANId = panid; 01946 start_req.LogicalChannel = channel; 01947 start_req.BeaconOrder = 0x0f; 01948 start_req.SuperframeOrder = 0x0f; 01949 start_req.PANCoordinator = coordinator; 01950 01951 if (cur->mac_api) { 01952 cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void *)&start_req); 01953 } 01954 } 01955 01956 static void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur) 01957 { 01958 tr_debug("FHSS activate"); 01959 ws_fhss_enable(cur); 01960 ws_llc_hopping_schedule_config(cur, &cur->ws_info->hopping_schdule); 01961 // Only supporting fixed channel 01962 01963 tr_debug("MAC init"); 01964 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); 01965 cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; 01966 ws_bootstrap_mac_security_enable(cur); 01967 ws_bootstrap_mac_activate(cur, cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->network_pan_id, true); 01968 return; 01969 } 01970 01971 static void ws_bootstrap_network_configuration_learn(protocol_interface_info_entry_t *cur) 01972 { 01973 tr_debug("Start using PAN configuration"); 01974 01975 // Timing information can be modified here 01976 ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information); 01977 uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur); 01978 ws_llc_set_gtkhash(cur, gtkhash); 01979 // TODO update own fhss schedules we are starting to follow first parent 01980 01981 return; 01982 } 01983 01984 static void ws_bootstrap_ip_stack_addr_clear(protocol_interface_info_entry_t *cur) 01985 { 01986 tr_debug("ip stack address clear"); 01987 ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { 01988 if (addr->source != ADDR_SOURCE_STATIC && 01989 addr_ipv6_scope(addr->address, cur) > IPV6_SCOPE_LINK_LOCAL) { 01990 // Remove all exept User set address 01991 addr_delete_entry(cur, addr); 01992 } 01993 } 01994 } 01995 01996 static void ws_bootstrap_ip_stack_reset(protocol_interface_info_entry_t *cur) 01997 { 01998 tr_debug("ip stack reset"); 01999 // Delete all temporary cached information 02000 ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); 02001 lowpan_context_list_free(&cur->lowpan_contexts); 02002 } 02003 02004 static void ws_bootstrap_ip_stack_activate(protocol_interface_info_entry_t *cur) 02005 { 02006 tr_debug("ip stack init"); 02007 clear_power_state(ICMP_ACTIVE); 02008 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; 02009 ws_bootstrap_ip_stack_reset(cur); 02010 } 02011 02012 static void ws_set_fhss_hop(protocol_interface_info_entry_t *cur) 02013 { 02014 uint16_t own_rank = ws_bootstrap_rank_get(cur); 02015 uint16_t rank_inc = ws_bootstrap_min_rank_inc_get(cur); 02016 if (own_rank == 0xffff || rank_inc == 0xffff) { 02017 return; 02018 } 02019 // Calculate own hop count. This method gets inaccurate when hop count increases. 02020 uint8_t own_hop = (own_rank - rank_inc) / rank_inc; 02021 ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, own_hop); 02022 tr_debug("own hop: %u, own rank: %u, rank inc: %u", own_hop, own_rank, rank_inc); 02023 } 02024 02025 static void ws_address_registration_update(protocol_interface_info_entry_t *interface) 02026 { 02027 rpl_control_register_address(interface, NULL); 02028 tr_info("RPL parent update ... register ARO"); 02029 } 02030 02031 static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) 02032 { 02033 02034 protocol_interface_info_entry_t *cur = handle; 02035 if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { 02036 return; 02037 } 02038 // if waiting for RPL and 02039 if (event == RPL_EVENT_DAO_DONE) { 02040 // Trigger statemachine check 02041 cur->bootsrap_state_machine_cnt = 1; 02042 rpl_dodag_info_t dodag_info; 02043 struct rpl_instance *instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); 02044 02045 if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) { 02046 tr_debug("Enable DHCPv6 relay"); 02047 dhcp_relay_agent_enable(cur->id, dodag_info.dodag_id); 02048 02049 tr_debug("Start EAPOL relay"); 02050 // Set both own port and border router port to 10253 02051 ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT); 02052 // Set network information to PAE 02053 ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); 02054 // Network key is valid 02055 ws_pae_controller_nw_key_valid(cur); 02056 } 02057 02058 ws_set_fhss_hop(cur); 02059 02060 } else if (event == RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS) { 02061 /* 02062 * RPL goes to passive mode, but does not require any extra changed 02063 * 02064 * We could remove our current addresses learned from RPL 02065 * We could send solicit for configuration and then select new parent when those arrive 02066 * 02067 */ 02068 02069 } else if (event == RPL_EVENT_DAO_PARENT_ADD) { 02070 ws_address_registration_update(cur); 02071 } 02072 cur->ws_info->rpl_state = event; 02073 tr_info("RPL event %d", event); 02074 } 02075 02076 static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) 02077 { 02078 (void)prefix; 02079 (void)interface; 02080 //TODO add handler for negative status 02081 tr_debug("DHCPv6 %s status %u with link %s", trace_ipv6(prefix), register_status, trace_ipv6(dhcp_addr)); 02082 if (register_status) { 02083 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); 02084 if (cur) { 02085 rpl_control_register_address(cur, prefix); 02086 } 02087 } else { 02088 //Delete dhcpv6 client 02089 dhcp_client_global_address_delete(interface, dhcp_addr, prefix); 02090 } 02091 } 02092 02093 02094 void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local) 02095 { 02096 if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, ws_dhcp_client_global_adress_cb) != 0) { 02097 tr_error("DHCPp client request fail"); 02098 } 02099 } 02100 02101 void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix) 02102 { 02103 dhcp_client_global_address_delete(cur->id, NULL, prefix); 02104 } 02105 02106 bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur) 02107 { 02108 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { 02109 return true; 02110 } 02111 02112 return false; 02113 } 02114 02115 static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local) 02116 { 02117 protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t *) handle; 02118 /* Check if A-Flag. 02119 * A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC) 02120 * from a prefix advertised by a parent. 02121 */ 02122 if (prefix->options & PIO_A) { 02123 02124 if (parent_link_local) { 02125 if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) { 02126 ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime); 02127 /* 02128 * Give SLAAC addresses a different label and low precedence to indicate that 02129 * they probably shouldn't be used for external traffic. SLAAC use in Wi-SUN is non-standard, 02130 * and we use it for mesh-local traffic we should prefer any DHCP-assigned addresses 02131 * for talking to the outside world 02132 * 02133 */ 02134 addr_policy_table_add_entry(prefix->prefix, prefix->prefix_len, 2, WS_NON_PREFFRED_LABEL); 02135 } 02136 } else { 02137 icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, 0, 0); 02138 } 02139 } else if (prefix->prefix_len) { 02140 // Create new address using DHCP 02141 if (parent_link_local) { 02142 ws_dhcp_client_address_request(cur, prefix->prefix, parent_link_local); 02143 } else { 02144 /* Deprecate address and remove client */ 02145 tr_debug("Prefix invalidation %s", trace_ipv6(prefix->prefix)); 02146 dhcp_client_global_address_delete(cur->id, NULL, prefix->prefix); 02147 } 02148 } 02149 } 02150 02151 static bool ws_rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle) 02152 { 02153 02154 protocol_interface_info_entry_t *cur = handle; 02155 if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { 02156 return false; 02157 } 02158 02159 uint8_t mac64[8]; 02160 memcpy(mac64, ll_parent_address + 8, 8); 02161 mac64[0] ^= 2; 02162 llc_neighbour_req_t neigh_buffer; 02163 if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { 02164 return true; 02165 } 02166 02167 if (!ws_rpl_dio_new_parent_accept(cur)) { 02168 return false; 02169 } 02170 02171 //Discover Multicast temporary entry 02172 02173 ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); 02174 if (!entry) { 02175 return false; 02176 } 02177 //Create entry 02178 bool create_ok = ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, true); 02179 if (create_ok) { 02180 ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; 02181 //Copy fhss temporary data 02182 *ws_neigh = entry->neigh_info_list ; 02183 //ETX Create here 02184 etx_lqi_dbm_update(cur->id, entry->mpduLinkQuality, entry->signal_dbm, neigh_buffer.neighbor->index ); 02185 mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); 02186 } 02187 ws_llc_free_multicast_temp_entry(cur, entry); 02188 02189 02190 return create_ok; 02191 } 02192 02193 static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) 02194 { 02195 tr_debug("RPL Activate"); 02196 bool downstream = true; 02197 bool leaf = false; 02198 02199 addr_add_router_groups(cur); 02200 rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); 02201 rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback_t, cur); 02202 // If i am router I Do this 02203 rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); 02204 rpl_control_request_parent_link_confirmation(true); 02205 rpl_control_set_dio_multicast_min_config_advertisment_count(WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT); 02206 rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES); 02207 rpl_control_set_initial_dao_ack_wait(WS_MAX_DAO_INITIAL_TIMEOUT); 02208 02209 cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event 02210 } 02211 02212 static void ws_bootstrap_network_start(protocol_interface_info_entry_t *cur) 02213 { 02214 //Set Network names, Pan information configure, hopping schedule & GTKHash 02215 ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->network_name, strlen(cur->ws_info->network_name)); 02216 ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information); 02217 } 02218 02219 static void ws_bootstrap_network_discovery_configure(protocol_interface_info_entry_t *cur) 02220 { 02221 // Reset information to defaults 02222 cur->ws_info->network_pan_id = 0xffff; 02223 02224 ws_common_regulatory_domain_config(cur); 02225 ws_fhss_discovery_configure(cur); 02226 02227 //Set Network names, Pan information configure, hopping schedule & GTKHash 02228 ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->network_name, strlen(cur->ws_info->network_name)); 02229 } 02230 02231 02232 static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur) 02233 { 02234 cur->ws_info->trickle_pa_running = true; 02235 trickle_start(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); 02236 cur->ws_info->trickle_pc_running = true; 02237 trickle_start(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); 02238 } 02239 02240 static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur) 02241 { 02242 cur->ws_info->pan_version_timer = 1; 02243 } 02244 02245 // Start network scan 02246 static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) 02247 { 02248 tr_debug("router discovery start"); 02249 // Remove network keys from MAC 02250 ws_pae_controller_nw_keys_remove(cur); 02251 ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); 02252 cur->nwk_nd_re_scan_count = 0; 02253 cur->ws_info->configuration_learned = false; 02254 cur->ws_info->pan_version_timeout_timer = 0; 02255 02256 // Clear learned neighbours 02257 ws_bootstrap_neighbor_list_clean(cur); 02258 02259 // Clear learned candidate parents 02260 ws_bootstrap_candidate_table_reset(cur); 02261 02262 // Clear RPL information 02263 rpl_control_free_domain_instances_from_interface(cur); 02264 // Clear EAPOL relay address 02265 ws_eapol_relay_delete(cur); 02266 02267 // Clear ip stack from old information 02268 ws_bootstrap_ip_stack_reset(cur); 02269 // New network scan started old addresses not assumed valid anymore 02270 ws_bootstrap_ip_stack_addr_clear(cur); 02271 02272 if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) != INTERFACE_NWK_BOOTSRAP_ACTIVE) { 02273 // we have sent bootstrap ready event and now 02274 // restarted discovery so bootstrap down event is sent 02275 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; 02276 ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN); 02277 } 02278 02279 // Start advertisement solicit trickle and calculate when we are checking the status 02280 cur->ws_info->trickle_pas_running = true; 02281 if (cur->ws_info->trickle_pan_advertisement_solicit.I != cur->ws_info->trickle_params_pan_discovery.Imin) { 02282 // Trickle not reseted so starting a new interval 02283 trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); 02284 } 02285 02286 // Discovery statemachine is checkked after we have sent the Solicit 02287 uint16_t time_to_solicit = 0; 02288 if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) { 02289 time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now; 02290 } 02291 02292 tr_debug("Disc params imin %u, imax %u, expirations %u, k %u PAS Trickle I %u t %u, now %u, c %u", 02293 cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k, 02294 cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c); 02295 02296 cur->bootsrap_state_machine_cnt = time_to_solicit + cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; 02297 tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); 02298 } 02299 02300 // Start authentication 02301 static void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur) 02302 { 02303 // Set PAN ID and network name to controller 02304 ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); 02305 02306 ws_pae_controller_authenticate(cur); 02307 } 02308 02309 static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cur) 02310 { 02311 mac_helper_default_security_level_set(cur, AES_SECURITY_LEVEL_ENC_MIC64); 02312 mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX); 02313 } 02314 02315 static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t slot, uint8_t index, uint8_t *key) 02316 { 02317 mac_helper_security_key_to_descriptor_set(cur, key, index + 1, slot); 02318 } 02319 02320 static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot) 02321 { 02322 mac_helper_security_key_descriptor_clear(cur, slot); 02323 } 02324 02325 static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index) 02326 { 02327 // Set send key 02328 mac_helper_security_auto_request_key_index_set(cur, index, index + 1); 02329 } 02330 02331 static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot) 02332 { 02333 // Set frame counter 02334 mac_helper_key_link_frame_counter_set(cur->id, counter, slot); 02335 } 02336 02337 static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot) 02338 { 02339 // Read frame counter 02340 mac_helper_key_link_frame_counter_read(cur->id, counter, slot); 02341 } 02342 02343 static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64) 02344 { 02345 (void) target_eui_64; 02346 02347 if (result == AUTH_RESULT_OK) { 02348 tr_debug("authentication success"); 02349 ws_bootstrap_event_configuration_start(cur); 02350 } else if (result == AUTH_RESULT_ERR_TX_NO_ACK) { 02351 // eapol parent selected is not working 02352 tr_debug("authentication TX failed"); 02353 02354 ws_bootstrap_candidate_parent_free(cur, target_eui_64); 02355 // Go back for network scanning 02356 ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); 02357 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, cur->ws_info->trickle_params_pan_discovery.Imin >> 1); 02358 tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); 02359 } else { 02360 tr_debug("authentication failed"); 02361 // What else to do to start over again... 02362 // Trickle is reseted when entering to discovery from state 2 02363 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); 02364 ws_bootstrap_event_discovery_start(cur); 02365 } 02366 } 02367 02368 // Start configuration learning 02369 static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur) 02370 { 02371 tr_debug("router configuration learn start"); 02372 ws_bootstrap_state_change(cur, ER_SCAN); 02373 02374 cur->ws_info->configuration_learned = false; 02375 02376 // Clear all temporary information 02377 ws_bootstrap_ip_stack_reset(cur); 02378 02379 cur->ws_info->pas_requests = 0; 02380 // Reset advertisement solicit trickle to start discovering network 02381 cur->ws_info->trickle_pcs_running = true; 02382 trickle_start(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); 02383 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); 02384 } 02385 static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) 02386 { 02387 tr_debug("Start RPL learn"); 02388 // routers wait until RPL root is contacted 02389 ws_bootstrap_state_change(cur, ER_RPL_SCAN); 02390 // Set timeout for check to 30 -60 seconds 02391 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT); 02392 } 02393 02394 /* 02395 * Event transitions 02396 * 02397 * */ 02398 void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur) 02399 { 02400 ws_bootsrap_event_trig(WS_DISCOVERY_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL); 02401 } 02402 void ws_bootstrap_event_configuration_start(protocol_interface_info_entry_t *cur) 02403 { 02404 ws_bootsrap_event_trig(WS_CONFIGURATION_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL); 02405 } 02406 void ws_bootstrap_event_authentication_start(protocol_interface_info_entry_t *cur) 02407 { 02408 ws_bootstrap_state_change(cur, ER_PANA_AUTH); 02409 } 02410 void ws_bootstrap_event_operation_start(protocol_interface_info_entry_t *cur) 02411 { 02412 ws_bootsrap_event_trig(WS_OPERATION_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL); 02413 } 02414 void ws_bootstrap_event_routing_ready(protocol_interface_info_entry_t *cur) 02415 { 02416 ws_bootsrap_event_trig(WS_ROUTING_READY, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL); 02417 } 02418 void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *cur) 02419 { 02420 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); 02421 } 02422 02423 static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asynch_request_t *async_req) 02424 { 02425 memset(&async_req->channel_list, 0, sizeof(channel_list_s)); 02426 if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) { 02427 //SET 1 Channel only 02428 uint16_t channel_number = cur->ws_info->fhss_uc_fixed_channel; 02429 async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32)); 02430 } else { 02431 ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); 02432 } 02433 02434 async_req->channel_list.channel_page = CHANNEL_PAGE_10; 02435 } 02436 02437 static void ws_bootstrap_pan_advert_solicit(protocol_interface_info_entry_t *cur) 02438 { 02439 asynch_request_t async_req; 02440 memset(&async_req, 0, sizeof(asynch_request_t)); 02441 async_req.message_type = WS_FT_PAN_ADVERT_SOL; 02442 //Request UTT Header and US and Net name from payload 02443 async_req.wh_requested_ie_list.utt_ie = true; 02444 async_req.wp_requested_nested_ie_list.us_ie = true; 02445 async_req.wp_requested_nested_ie_list.net_name_ie = true; 02446 02447 ws_set_asynch_channel_list(cur, &async_req); 02448 02449 02450 async_req.security.SecurityLevel = 0; 02451 02452 ws_llc_asynch_request(cur, &async_req); 02453 } 02454 02455 static void ws_bootstrap_pan_config_solicit(protocol_interface_info_entry_t *cur) 02456 { 02457 asynch_request_t async_req; 02458 memset(&async_req, 0, sizeof(asynch_request_t)); 02459 async_req.message_type = WS_FT_PAN_CONF_SOL; 02460 //Request UTT Header and US and Net name from payload 02461 async_req.wh_requested_ie_list.utt_ie = true; 02462 async_req.wp_requested_nested_ie_list.us_ie = true; 02463 async_req.wp_requested_nested_ie_list.net_name_ie = true; 02464 02465 ws_set_asynch_channel_list(cur, &async_req); 02466 async_req.security.SecurityLevel = 0; 02467 02468 ws_llc_asynch_request(cur, &async_req); 02469 } 02470 02471 static struct rpl_instance *ws_get_rpl_instance(protocol_interface_info_entry_t *cur) 02472 { 02473 if (!cur || !cur->rpl_domain) { 02474 return NULL; 02475 } 02476 struct rpl_instance *best_instance = NULL; 02477 ns_list_foreach(struct rpl_instance, instance, &cur->rpl_domain->instances) { 02478 best_instance = instance; 02479 // Select best grounded and lowest rank? But there should be only one really 02480 } 02481 return best_instance; 02482 } 02483 02484 static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur) 02485 { 02486 mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_priority(mac_neighbor_info(cur)); 02487 if (!mac_neighbor) { 02488 return 0xffff; 02489 } 02490 ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, mac_neighbor->index ); 02491 if (!ws_neighbor) { 02492 return 0xffff; 02493 } 02494 02495 uint16_t etx = etx_local_etx_read(cur->id, mac_neighbor->index ); 02496 if (etx == 0) { 02497 etx = 0xffff; 02498 } 02499 if (etx > 0x800) { 02500 // Wi-SUN section 6.2.3.1.6.1 says ETX can only be maximum of 1024 (8*128) in RPL units, ie 8.0. 02501 etx = 0x800; 02502 } 02503 etx = etx >> 1; 02504 02505 return ws_neighbor->routing_cost + etx; 02506 } 02507 02508 static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur) 02509 { 02510 struct rpl_instance *rpl_instance = ws_get_rpl_instance(cur); 02511 if (!rpl_instance) { 02512 return 0xffff; 02513 } 02514 return rpl_control_current_rank(rpl_instance); 02515 } 02516 02517 02518 static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur) 02519 { 02520 struct rpl_instance *rpl_instance = ws_get_rpl_instance(cur); 02521 if (!rpl_instance) { 02522 return 0xffff; 02523 } 02524 struct rpl_dodag_info_t dodag_info; 02525 if (!rpl_control_read_dodag_info(rpl_instance, &dodag_info)) { 02526 return 0xffff; 02527 } 02528 return dodag_info.dag_min_hop_rank_inc; 02529 } 02530 02531 static void ws_bootstrap_pan_advert(protocol_interface_info_entry_t *cur) 02532 { 02533 asynch_request_t async_req; 02534 memset(&async_req, 0, sizeof(asynch_request_t)); 02535 async_req.message_type = WS_FT_PAN_ADVERT; 02536 //Request UTT Header, Pan information and US and Net name from payload 02537 async_req.wh_requested_ie_list.utt_ie = true; 02538 async_req.wp_requested_nested_ie_list.us_ie = true; 02539 async_req.wp_requested_nested_ie_list.pan_ie = true; 02540 async_req.wp_requested_nested_ie_list.net_name_ie = true; 02541 02542 ws_set_asynch_channel_list(cur, &async_req); 02543 async_req.security.SecurityLevel = 0; 02544 02545 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 02546 // Border routers write the NW size 02547 cur->ws_info->pan_information.pan_size = ws_bbr_pan_size(cur); 02548 cur->ws_info->pan_information.routing_cost = 0; 02549 } else { 02550 // Nodes need to calculate routing cost 02551 // PAN size is saved from latest PAN advertisement 02552 cur->ws_info->pan_information.routing_cost = ws_bootstrap_routing_cost_calculate(cur); 02553 } 02554 02555 02556 ws_llc_asynch_request(cur, &async_req); 02557 } 02558 02559 static void ws_bootstrap_pan_config(protocol_interface_info_entry_t *cur) 02560 { 02561 asynch_request_t async_req; 02562 memset(&async_req, 0, sizeof(asynch_request_t)); 02563 async_req.message_type = WS_FT_PAN_CONF; 02564 //Request UTT Header, Pan information and US and Net name from payload 02565 async_req.wh_requested_ie_list.utt_ie = true; 02566 async_req.wh_requested_ie_list.bt_ie = true; 02567 async_req.wp_requested_nested_ie_list.us_ie = true; 02568 async_req.wp_requested_nested_ie_list.bs_ie = true; 02569 async_req.wp_requested_nested_ie_list.pan_version_ie = true; 02570 async_req.wp_requested_nested_ie_list.gtkhash_ie = true; 02571 async_req.wp_requested_nested_ie_list.vp_ie = true; 02572 02573 ws_set_asynch_channel_list(cur, &async_req); 02574 02575 async_req.security.SecurityLevel = mac_helper_default_security_level_get(cur); 02576 async_req.security.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur); 02577 async_req.security.KeyIndex = mac_helper_default_key_index_get(cur); 02578 ws_llc_asynch_request(cur, &async_req); 02579 } 02580 02581 static void ws_bootstrap_event_handler(arm_event_s *event) 02582 { 02583 ws_bootsrap_event_type_e event_type; 02584 event_type = (ws_bootsrap_event_type_e)event->event_type; 02585 protocol_interface_info_entry_t *cur; 02586 cur = protocol_stack_interface_info_get_by_bootstrap_id(event->receiver); 02587 if (!cur) { 02588 return; 02589 } 02590 02591 switch (event_type) { 02592 case WS_INIT_EVENT: 02593 tr_debug("tasklet init"); 02594 break; 02595 case WS_DISCOVERY_START: 02596 tr_info("Discovery start"); 02597 // All trickle timers stopped to allow entry from any state 02598 cur->ws_info->trickle_pa_running = false; 02599 cur->ws_info->trickle_pc_running = false; 02600 cur->ws_info->trickle_pas_running = false; 02601 cur->ws_info->trickle_pcs_running = false; 02602 02603 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 02604 tr_debug("Border router start network"); 02605 02606 if (!ws_bbr_ready_to_start(cur)) { 02607 // Wi-SUN not started yet we wait for Border router permission 02608 ws_bootstrap_state_change(cur, ER_WAIT_RESTART); 02609 cur->nwk_nd_re_scan_count = randLIB_get_random_in_range(40, 100); 02610 return; 02611 } 02612 ws_pae_controller_auth_init(cur); 02613 02614 // Randomize fixed channels. Only used if channel plan is fixed. 02615 cur->ws_info->fhss_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); 02616 cur->ws_info->fhss_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); 02617 cur->ws_info->network_pan_id = randLIB_get_random_in_range(0, 0xfffd); 02618 cur->ws_info->pan_information.pan_size = 0; 02619 cur->ws_info->pan_information.pan_version = randLIB_get_random_in_range(0, 0xffff); 02620 cur->ws_info->pan_information.routing_cost = 0; 02621 cur->ws_info->pan_information.rpl_routing_method = true; 02622 cur->ws_info->pan_information.use_parent_bs = true; 02623 cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0; 02624 02625 uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur); 02626 ws_llc_set_gtkhash(cur, gtkhash); 02627 cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config); 02628 02629 // Set default parameters for FHSS when starting a discovery 02630 ws_fhss_border_router_configure(cur); 02631 ws_bootstrap_fhss_activate(cur); 02632 ws_bootstrap_event_operation_start(cur); 02633 02634 uint8_t ll_addr[16]; 02635 addr_interface_get_ll_address(cur, ll_addr, 1); 02636 02637 //SET EAPOL authenticator EUI64 02638 ws_pae_controller_border_router_addr_write(cur, cur->mac); 02639 02640 // Set EAPOL relay to port 10255 and authenticator relay to 10253 (and to own ll address) 02641 ws_eapol_relay_start(cur, BR_EAPOL_RELAY_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT); 02642 02643 // Set authenticator relay to port 10253 and PAE to 10254 (and to own ll address) 02644 ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT); 02645 02646 // Set PAN ID and network name to controller 02647 ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); 02648 02649 // Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address) 02650 ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT); 02651 break; 02652 } 02653 ws_pae_controller_supp_init(cur); 02654 02655 // Configure LLC for network discovery 02656 ws_bootstrap_network_discovery_configure(cur); 02657 ws_bootstrap_fhss_activate(cur); 02658 // Start network scan 02659 ws_bootstrap_start_discovery(cur); 02660 break; 02661 02662 case WS_CONFIGURATION_START: 02663 tr_info("Configuration start"); 02664 // Old configuration is considered invalid stopping all 02665 cur->ws_info->trickle_pa_running = false; 02666 cur->ws_info->trickle_pc_running = false; 02667 cur->ws_info->trickle_pas_running = false; 02668 cur->ws_info->trickle_pcs_running = false; 02669 02670 // Build list of possible neighbours and learn first broadcast schedule 02671 02672 ws_bootstrap_start_configuration_learn(cur); 02673 break; 02674 case WS_OPERATION_START: 02675 tr_info("operation start"); 02676 // Advertisements stopped during the RPL scan 02677 cur->ws_info->trickle_pa_running = false; 02678 cur->ws_info->trickle_pc_running = false; 02679 cur->ws_info->trickle_pas_running = false; 02680 cur->ws_info->trickle_pcs_running = false; 02681 // Activate RPL 02682 // Activate IPv6 stack 02683 ws_bootstrap_ip_stack_activate(cur); 02684 ws_bootstrap_rpl_activate(cur); 02685 ws_bootstrap_network_start(cur); 02686 // Wait for RPL start 02687 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 02688 ws_bootstrap_event_routing_ready(cur); 02689 } else { 02690 ws_bootstrap_rpl_scan_start(cur); 02691 } 02692 break; 02693 case WS_ROUTING_READY: 02694 tr_info("Routing ready"); 02695 // stopped all to make sure we can enter here from any state 02696 cur->ws_info->trickle_pa_running = false; 02697 cur->ws_info->trickle_pc_running = false; 02698 cur->ws_info->trickle_pas_running = false; 02699 cur->ws_info->trickle_pcs_running = false; 02700 02701 // Indicate PAE controller that bootstrap is ready 02702 ws_pae_controller_bootstrap_done(cur); 02703 02704 ws_bootstrap_advertise_start(cur); 02705 ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE); 02706 break; 02707 02708 default: 02709 tr_err("Invalid event received"); 02710 break; 02711 } 02712 } 02713 02714 /* 02715 * State machine 02716 * 02717 * */ 02718 void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) 02719 { 02720 02721 parent_info_t *selected_parent_ptr; 02722 02723 tr_debug("analyze network discovery result"); 02724 02725 selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur); 02726 02727 if (!selected_parent_ptr) { 02728 // Next check will be after one trickle 02729 cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; 02730 tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); 02731 return; 02732 } 02733 tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id); 02734 02735 // Add EAPOL neighbour 02736 cur->ws_info->network_pan_id = selected_parent_ptr->pan_id; 02737 cur->ws_info->pan_information = selected_parent_ptr->pan_information; 02738 cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration 02739 02740 ws_bootstrap_fhss_activate(cur); 02741 llc_neighbour_req_t neighbor_info; 02742 if (!ws_bootstrap_neighbor_info_request(cur, selected_parent_ptr->addr, &neighbor_info, true)) { 02743 return; 02744 } 02745 02746 ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_utt, selected_parent_ptr->timestamp); 02747 ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_us); 02748 02749 ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth 02750 ws_bootstrap_event_authentication_start(cur); 02751 return; 02752 } 02753 02754 void ws_bootstrap_configure_process(protocol_interface_info_entry_t *cur) 02755 { 02756 02757 if (cur->ws_info->configuration_learned) { 02758 ws_bootstrap_network_configuration_learn(cur); 02759 02760 02761 ws_bootstrap_event_operation_start(cur); 02762 02763 02764 return; 02765 } 02766 return; 02767 } 02768 void ws_bootstrap_rpl_wait_process(protocol_interface_info_entry_t *cur) 02769 { 02770 02771 if (cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { 02772 // RPL routing is ready 02773 ws_bootstrap_event_routing_ready(cur); 02774 } else if (!rpl_control_have_dodag(cur->rpl_domain)) { 02775 // RPL not ready send DIS message if possible 02776 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) { 02777 // TODO Multicast DIS should be sent only if no DIO heard for some time 02778 rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, ADDR_LINK_LOCAL_ALL_RPL_NODES); 02779 } 02780 // set timer for next DIS 02781 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_TIMEOUT / 2, WS_RPL_DIS_TIMEOUT); 02782 } 02783 return; 02784 } 02785 02786 /* 02787 02788 static bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *cur) 02789 { 02790 // Think about the state value 02791 if (cur->nwk_bootstrap_state == ER_SCAN) { 02792 return true; 02793 } 02794 return false; 02795 } 02796 02797 */ 02798 static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur) 02799 { 02800 if (cur->nwk_bootstrap_state == ER_ACTIVE_SCAN) { 02801 return true; 02802 } 02803 return false; 02804 } 02805 02806 static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur) 02807 { 02808 if (cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { 02809 return true; 02810 } 02811 return false; 02812 } 02813 static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur) 02814 { 02815 // Think about the state value 02816 if (cur->nwk_bootstrap_state == ER_RPL_SCAN) { 02817 return true; 02818 } 02819 return false; 02820 } 02821 02822 static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state) 02823 { 02824 cur->bootsrap_state_machine_cnt = 1; 02825 cur->nwk_bootstrap_state = nwk_bootstrap_state; 02826 } 02827 02828 void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur) 02829 { 02830 02831 switch (cur->nwk_bootstrap_state) { 02832 case ER_WAIT_RESTART: 02833 tr_debug("WS SM:Wait for startup"); 02834 ws_bootstrap_event_discovery_start(cur); 02835 break; 02836 case ER_ACTIVE_SCAN: 02837 tr_debug("WS SM:Active Scan"); 02838 ws_bootstrap_network_scan_process(cur); 02839 break; 02840 case ER_SCAN: 02841 tr_debug("WS SM:configuration Scan"); 02842 ws_bootstrap_configure_process(cur); 02843 break; 02844 case ER_PANA_AUTH: 02845 tr_info("authentication start"); 02846 // Advertisements stopped during the EAPOL 02847 cur->ws_info->trickle_pa_running = false; 02848 cur->ws_info->trickle_pc_running = false; 02849 cur->ws_info->trickle_pas_running = false; 02850 cur->ws_info->trickle_pcs_running = false; 02851 02852 ws_bootstrap_start_authentication(cur); 02853 break; 02854 case ER_RPL_SCAN: 02855 tr_debug("WS SM:Wait RPL to contact DODAG root"); 02856 ws_bootstrap_rpl_wait_process(cur); 02857 break; 02858 case ER_BOOTSRAP_DONE: 02859 tr_debug("WS SM:Bootstrap Done"); 02860 // Bootstrap_done event to application 02861 nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur); 02862 break; 02863 default: 02864 tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state); 02865 } 02866 } 02867 02868 void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks) 02869 { 02870 if (cur->ws_info->trickle_pas_running && 02871 trickle_timer(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery, ticks)) { 02872 // send PAN advertisement solicit 02873 tr_info("Send PAN advertisement Solicit"); 02874 ws_bootstrap_pan_advert_solicit(cur); 02875 } 02876 if (cur->ws_info->trickle_pcs_running && 02877 trickle_timer(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery, ticks)) { 02878 // send PAN Configuration solicit 02879 if (cur->ws_info->pas_requests >= PCS_MAX) { 02880 // if MAX PCS sent restart discovery 02881 02882 // Trickle is reseted when entering to discovery from state 3 02883 trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); 02884 ws_bootstrap_event_discovery_start(cur); 02885 return; 02886 } 02887 tr_info("Send PAN configuration Solicit"); 02888 cur->ws_info->pas_requests++; 02889 ws_bootstrap_pan_config_solicit(cur); 02890 } 02891 if (cur->ws_info->trickle_pa_running && 02892 trickle_timer(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery, ticks)) { 02893 // send PAN advertisement 02894 tr_info("Send PAN advertisement"); 02895 ws_bootstrap_pan_advert(cur); 02896 } 02897 if (cur->ws_info->trickle_pc_running && 02898 trickle_timer(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery, ticks)) { 02899 // send PAN Configuration 02900 tr_info("Send PAN configuration"); 02901 ws_bootstrap_pan_config(cur); 02902 } 02903 } 02904 02905 02906 void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) 02907 { 02908 if (cur->ws_info->pan_version_timeout_timer) { 02909 // PAN version timer running 02910 if (cur->ws_info->pan_version_timeout_timer > seconds) { 02911 cur->ws_info->pan_version_timeout_timer -= seconds; 02912 } else { 02913 // Border router has timed out 02914 tr_warn("Border router has timed out"); 02915 ws_bootstrap_event_discovery_start(cur); 02916 } 02917 } 02918 } 02919 02920 void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) 02921 { 02922 if (interface->ws_info) { 02923 llc_neighbour_req_t neighbor_info; 02924 neighbor_info.neighbor = neighbor; 02925 neighbor_info.ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index ); 02926 ws_bootstrap_primary_parent_set(interface, &neighbor_info, WS_PARENT_HARD_SYNCH); 02927 uint8_t link_local_address[16]; 02928 ws_bootsrap_create_ll_address(link_local_address, neighbor->mac64 ); 02929 dhcp_client_server_address_update(interface->id, NULL, link_local_address); 02930 02931 ws_secondary_parent_update(interface); 02932 } 02933 } 02934 02935 void ws_secondary_parent_update(protocol_interface_info_entry_t *interface) 02936 { 02937 if (interface->ws_info) { 02938 ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) { 02939 if (!addr_is_ipv6_link_local(address->address)) { 02940 ws_address_registration_update(interface); 02941 } 02942 } 02943 } 02944 } 02945 02946 void ws_bootstrap_etx_accelerate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh) 02947 { 02948 ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neigh->index ); 02949 //Enable Faster ETX probing 02950 ws_neighbor->accelerated_etx_probe = true; 02951 //Move Neighbor to first to for accelerate Process 02952 mac_neighbor_table_t *table_class = mac_neighbor_info(interface); 02953 ns_list_remove(&table_class->neighbour_list , neigh); 02954 ns_list_add_to_start(&table_class->neighbour_list , neigh); 02955 //Try to Generate Active NUD Immediately 02956 if (!ws_neighbor_entry_nud_notify(neigh, interface)) { 02957 return;//Return if NUD active is full 02958 } 02959 table_class->active_nud_process ++; 02960 neigh->nud_active = true; 02961 //Push NS to send 02962 ws_nud_active_timer(interface, 0); 02963 } 02964 02965 #endif //HAVE_WS
Generated on Tue Jul 12 2022 13:55:04 by
