Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_common.c Source File

ws_common.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 "randLIB.h"
00023 #include <ns_list.h>
00024 #include <nsdynmemLIB.h>
00025 #include "6LoWPAN/ws/ws_config.h"
00026 #include "6LoWPAN/ws/ws_common_defines.h"
00027 #include "6LoWPAN/ws/ws_common.h"
00028 #include "6LoWPAN/ws/ws_bootstrap.h"
00029 #include "6LoWPAN/ws/ws_bbr_api_internal.h"
00030 #include "6LoWPAN/ws/ws_pae_controller.h"
00031 #include "Service_Libs/etx/etx.h"
00032 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00033 #include "Service_Libs/blacklist/blacklist.h"
00034 #include "RPL/rpl_protocol.h"
00035 #include "RPL/rpl_control.h"
00036 #include "ws_management_api.h"
00037 #include "mac_api.h"
00038 
00039 #ifdef HAVE_WS
00040 #define TRACE_GROUP "wscm"
00041 
00042 // estimated sensitivity -93 dbm converted to Wi-SUN RSL range
00043 // This provides a range of -174 (0) to +80 (254) dBm
00044 uint8_t DEVICE_MIN_SENS = 174 - 93;
00045 
00046 #define TRICKLE_IMIN_60_SECS (60 * 10)
00047 #define TRICKLE_IMIN_30_SECS (30 * 10)
00048 #define TRICKLE_IMIN_15_SECS (15 * 10)
00049 
00050 static const trickle_params_t trickle_params_pan_discovery_large = {
00051     .Imin = TRICKLE_IMIN_60_SECS,           /* 60 second; ticks are 1s */
00052     .Imax = TRICKLE_IMIN_60_SECS << 4,      /* 960 seconds 16 min*/
00053                                  .k = 1,    /* 1 */
00054                                  .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
00055 };
00056 
00057 static const trickle_params_t trickle_params_pan_discovery_medium = {
00058     .Imin = TRICKLE_IMIN_30_SECS,           /* 30 second; ticks are 1s */
00059     .Imax = TRICKLE_IMIN_30_SECS << 5,      /* 960 seconds 16 min*/
00060                                  .k = 1,    /* 1 */
00061                                  .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
00062 };
00063 
00064 static const trickle_params_t trickle_params_pan_discovery_small = {
00065     .Imin = TRICKLE_IMIN_15_SECS,           /* 15 second; ticks are 1s */
00066     .Imax = TRICKLE_IMIN_15_SECS << 2,      /* 60 seconds 1 min*/
00067                                  .k = 1,    /* 1 */
00068                                  .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
00069 };
00070 
00071 uint16_t test_max_child_count_override = 0xffff;
00072 
00073 
00074 int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain)
00075 {
00076     (void)regulatory_domain;
00077     for (uint8_t i = 0; i < number_of_channels; i++) {
00078         channel_mask[0 + (i / 32)] |= (1 << (i % 32));
00079     }
00080     return 0;
00081 }
00082 
00083 static uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
00084 {
00085     if (CHANNEL_SPACING_100 == channel_spacing) {
00086         return 100000;
00087     } else if (CHANNEL_SPACING_200 == channel_spacing) {
00088         return 200000;
00089     } else if (CHANNEL_SPACING_250 == channel_spacing) {
00090         return 250000;
00091     } else if (CHANNEL_SPACING_400 == channel_spacing) {
00092         return 400000;
00093     } else if (CHANNEL_SPACING_600 == channel_spacing) {
00094         return 600000;
00095     }
00096     return 0;
00097 }
00098 
00099 static uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode)
00100 {
00101     if ((OPERATING_MODE_1a == operating_mode) || (OPERATING_MODE_1b == operating_mode)) {
00102         return 50000;
00103     } else if ((OPERATING_MODE_2a == operating_mode) || (OPERATING_MODE_2b == operating_mode)) {
00104         return 100000;
00105     } else if (OPERATING_MODE_3 == operating_mode) {
00106         return 150000;
00107     } else if ((OPERATING_MODE_4a == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
00108         return 200000;
00109     } else if (OPERATING_MODE_5 == operating_mode) {
00110         return 300000;
00111     }
00112     return 0;
00113 }
00114 
00115 static phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode)
00116 {
00117     if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
00118         return MODULATION_INDEX_1_0;
00119     } else {
00120         return MODULATION_INDEX_0_5;
00121     }
00122 }
00123 
00124 static int ws_set_domain_rf_config(protocol_interface_info_entry_t *cur)
00125 {
00126     phy_rf_channel_configuration_s rf_configs;
00127     rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000;
00128     rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing);
00129     rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
00130     rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
00131     rf_configs.modulation = M_2FSK;
00132     rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels;
00133     ws_bootstrap_set_rf_config(cur, rf_configs);
00134     return 0;
00135 }
00136 
00137 int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur)
00138 {
00139     cur->ws_info->hopping_schdule.channel_plan = 0;
00140 
00141     if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_KR) {
00142         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00143             cur->ws_info->hopping_schdule.ch0_freq = 9171;
00144             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00145         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00146             cur->ws_info->hopping_schdule.ch0_freq = 9173;
00147             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
00148         } else {
00149             return -1;
00150         }
00151     } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_EU) {
00152         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00153             cur->ws_info->hopping_schdule.ch0_freq = 8631;
00154             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
00155         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00156             cur->ws_info->hopping_schdule.ch0_freq = 8631;
00157             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00158         } else if (cur->ws_info->hopping_schdule.operating_class == 3) {
00159             cur->ws_info->hopping_schdule.ch0_freq = 8701;
00160             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
00161         } else if (cur->ws_info->hopping_schdule.operating_class == 4) {
00162             cur->ws_info->hopping_schdule.ch0_freq = 8702;
00163             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00164         } else {
00165             return -1;
00166         }
00167     } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_IN) {
00168         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00169             cur->ws_info->hopping_schdule.ch0_freq = 8651;
00170             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
00171         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00172             cur->ws_info->hopping_schdule.ch0_freq = 8651;
00173             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00174         } else {
00175             return -1;
00176         }
00177     } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_NA) {
00178         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00179             cur->ws_info->hopping_schdule.ch0_freq = 9022;
00180             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00181         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00182             cur->ws_info->hopping_schdule.ch0_freq = 9024;
00183             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
00184         } else if (cur->ws_info->hopping_schdule.operating_class == 3) {
00185             cur->ws_info->hopping_schdule.ch0_freq = 9026;
00186             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600;
00187         } else {
00188             return -1;
00189         }
00190     } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_JP) {
00191         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00192             cur->ws_info->hopping_schdule.ch0_freq = 9206;
00193             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00194         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00195             cur->ws_info->hopping_schdule.ch0_freq = 9209;
00196             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
00197         } else if (cur->ws_info->hopping_schdule.operating_class == 3) {
00198             cur->ws_info->hopping_schdule.ch0_freq = 9208;
00199             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600;
00200         } else {
00201             return -1;
00202         }
00203     } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_WW) {
00204         if (cur->ws_info->hopping_schdule.operating_class == 1) {
00205             cur->ws_info->hopping_schdule.ch0_freq = 24002;
00206             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
00207         } else if (cur->ws_info->hopping_schdule.operating_class == 2) {
00208             cur->ws_info->hopping_schdule.ch0_freq = 24004;
00209             cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
00210         } else {
00211             return -1;
00212         }
00213     } else {
00214         return -1;
00215     }
00216     cur->ws_info->hopping_schdule.number_of_channels = (uint8_t)ws_common_channel_number_calc(cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
00217     if (!cur->ws_info->hopping_schdule.number_of_channels) {
00218         return -1;
00219     }
00220     // Note: doesn't work for Brazil region
00221     ws_generate_channel_list(cur->ws_info->hopping_schdule.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
00222     ws_set_domain_rf_config(cur);
00223     return 0;
00224 }
00225 
00226 uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class)
00227 {
00228     if (regulatory_domain == REG_DOMAIN_KR) {
00229         if (operating_class == 1) {
00230             return 32;
00231         } else if (operating_class == 2) {
00232             return 16;
00233         }
00234     } else if (regulatory_domain == REG_DOMAIN_EU) {
00235         if (operating_class == 1) {
00236             return 69;
00237         } else if (operating_class == 2) {
00238             return 35;
00239         } else if (operating_class == 3) {
00240             return 55;
00241         } else if (operating_class == 4) {
00242             return 27;
00243         }
00244     } else if (regulatory_domain == REG_DOMAIN_IN) {
00245         if (operating_class == 1) {
00246             return 19;
00247         } else if (operating_class == 2) {
00248             return 10;
00249         }
00250     } else if (regulatory_domain == REG_DOMAIN_NA) {
00251         if (operating_class == 1) {
00252             return 129;
00253         } else if (operating_class == 2) {
00254             return 64;
00255         } else if (operating_class == 3) {
00256             return 42;
00257         }
00258     } else if (regulatory_domain == REG_DOMAIN_JP) {
00259         if (operating_class == 1) {
00260             return 38;
00261         } else if (operating_class == 2) {
00262             return 18;
00263         } else if (operating_class == 3) {
00264             return 12;
00265         }
00266     } else if (regulatory_domain == REG_DOMAIN_WW) {
00267         if (operating_class == 1) {
00268             // TODO we dont support this yet, but it is used as test value
00269             return 416;
00270         } else if (operating_class == 2) {
00271             return 207;
00272         }
00273     }
00274     return 0;
00275 }
00276 
00277 int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
00278 {
00279 
00280     if (!cur->ws_info) {
00281         cur->ws_info = ns_dyn_mem_alloc(sizeof(ws_info_t));
00282     }
00283     if (!cur->ws_info) {
00284         return -1;
00285     }
00286 
00287     memset(cur->ws_info, 0, sizeof(ws_info_t));
00288     ns_list_init(&cur->ws_info->active_nud_process);
00289     ns_list_init(&cur->ws_info->free_nud_entries);
00290 
00291     ns_list_init(&cur->ws_info->parent_list_free);
00292     ns_list_init(&cur->ws_info->parent_list_reserved);
00293 
00294     cur->ws_info->pan_information.use_parent_bs = true;
00295     cur->ws_info->pan_information.rpl_routing_method = true;
00296     cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
00297 
00298     cur->ws_info->hopping_schdule.regulatory_domain = REG_DOMAIN_EU;
00299     cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
00300     cur->ws_info->hopping_schdule.operating_class = 2;
00301     // Clock drift value 255 indicates that information is not provided
00302     cur->ws_info->hopping_schdule.clock_drift = 255;
00303     // Timing accuracy is given from 0 to 2.55msec with 10usec resolution
00304     cur->ws_info->hopping_schdule.timing_accurancy = 100;
00305     ws_common_regulatory_domain_config(cur);
00306     cur->ws_info->network_size_config = NETWORK_SIZE_MEDIUM;
00307     cur->ws_info->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
00308     cur->ws_info->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
00309     ws_common_network_size_configure(cur, 200); // defaults to medium network size
00310 
00311     // Set defaults for the device. user can modify these.
00312     cur->ws_info->fhss_uc_fixed_channel = 0xffff;
00313     cur->ws_info->fhss_bc_fixed_channel = 0xffff;
00314     cur->ws_info->fhss_uc_dwell_interval = WS_FHSS_UC_DWELL_INTERVAL;
00315     cur->ws_info->fhss_bc_interval = WS_FHSS_BC_INTERVAL;
00316     cur->ws_info->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL;
00317     cur->ws_info->fhss_uc_channel_function = WS_DH1CF;
00318     cur->ws_info->fhss_bc_channel_function = WS_DH1CF;
00319     for (uint8_t n = 0; n < 8; n++) {
00320         cur->ws_info->fhss_channel_mask[n] = 0xffffffff;
00321     }
00322 
00323     return 0;
00324 }
00325 void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size)
00326 {
00327     // TODO Modify NUD timings based on network size
00328     // TODO Modify EAPOLL timings
00329 
00330     if (network_size < 100) {
00331         // Configure the Wi-SUN discovery trickle parameters
00332         cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_small;
00333         // default values are for Wi-SUN small network parameters
00334         // imin: 14 (16s)
00335         // doublings:3 (128s)
00336         // redundancy; 0 Disabled
00337         if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
00338             ws_bbr_rpl_config(14, 3, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
00339         } else if (cur->ws_info->network_size_config == NETWORK_SIZE_CERTIFICATE) {
00340             ws_bbr_rpl_config(0, 0, 0, WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE, WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE);
00341         } else {
00342             ws_bbr_rpl_config(0, 0, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
00343         }
00344         ws_pae_controller_timing_adjust(1); // Fast and reactive network
00345     } else if (network_size < 300) {
00346         // Configure the Wi-SUN discovery trickle parameters
00347         cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium;
00348         // Something in between
00349         // imin: 15 (32s)
00350         // doublings:5 (960s)
00351         // redundancy; 10
00352         ws_bbr_rpl_config(15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
00353         ws_pae_controller_timing_adjust(9); // medium limited network
00354     } else {
00355         // Configure the Wi-SUN discovery trickle parameters
00356         cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_large;
00357         // Wi-SUN Large network parameters
00358         // imin: 19 (524s, 9 min)
00359         // doublings:1 (1048s, 17 min)
00360         // redundancy; 10 May need some tuning still
00361         ws_bbr_rpl_config(19, 1, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
00362         ws_pae_controller_timing_adjust(24); // Very slow and high latency network
00363     }
00364     return;
00365 }
00366 
00367 void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
00368 {
00369     ws_bbr_seconds_timer(cur, seconds);
00370     ws_bootstrap_seconds_timer(cur, seconds);
00371     blacklist_ttl_update(seconds);
00372 }
00373 
00374 void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
00375 {
00376     ws_bootstrap_trickle_timer(cur, ticks);
00377     ws_nud_active_timer(cur, ticks);
00378 }
00379 
00380 
00381 void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
00382 {
00383     //Neighbor connectected update
00384     mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL);
00385     if (mac_neighbor) {
00386         ws_nud_entry_remove_active(cur, mac_neighbor);
00387     }
00388 }
00389 
00390 void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full)
00391 {
00392     tr_warn("ARO registration Failure %s", trace_ipv6(ll_address));
00393     if (cache_full) {
00394         blacklist_update(ll_address, false);
00395     }
00396     ws_bootstrap_aro_failure(cur, ll_address);
00397 }
00398 
00399 void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
00400 {
00401     tr_debug("neighbor remove %s", trace_ipv6(ll_address));
00402     ws_bootstrap_neighbor_remove(cur, ll_address);
00403 }
00404 
00405 
00406 
00407 bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
00408 {
00409     uint8_t child_count = 0;
00410     uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT;
00411 
00412     // Test API to limit child count
00413     if (test_max_child_count_override != 0xffff) {
00414         max_child_count = test_max_child_count_override;
00415     }
00416 
00417     //Validate Is EUI64 already allocated for any address
00418     if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) {
00419         tr_info("Child registration from old child");
00420         return true;
00421     }
00422 
00423     //Verify that we have Selected Parent
00424     if (interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && !rpl_control_parent_candidate_list_size(interface, true)) {
00425         tr_info("Do not accept new ARO child: no selected parent");
00426         return false;
00427     }
00428 
00429 
00430     ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
00431 
00432         if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {
00433             child_count++;
00434         }
00435     }
00436     if (child_count >= max_child_count) {
00437         tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
00438         return false;
00439     }
00440     tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
00441     return true;
00442 }
00443 
00444 bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
00445 {
00446     mac_neighbor_table_entry_t *neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(interface), eui64, ADDR_802_15_4_LONG );
00447     if (!neighbour) {
00448         return false;
00449     }
00450     ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index );
00451     ws_neighbor->negative_aro_send = true;
00452     neighbour->lifetime  = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; //Remove anyway if Packet is freed before MAC push
00453     return true;
00454 }
00455 
00456 void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh)
00457 {
00458     etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, neigh->index );
00459 
00460     if (neigh->nud_active  || !neigh->trusted_device  || !etx_entry || etx_entry->etx_samples) {
00461         return; //Do not trig Second NS if Active NUD already, not trusted or ETX samples already done
00462     }
00463 
00464     ws_bootstrap_etx_accelerate(interface, neigh);
00465 }
00466 
00467 uint32_t ws_common_version_lifetime_get(uint8_t config)
00468 {
00469     uint32_t lifetime;
00470     if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) {
00471         lifetime = PAN_VERSION_SMALL_NETWORK_LIFETIME;
00472     } else if (config == NETWORK_SIZE_MEDIUM) {
00473         lifetime = PAN_VERSION_MEDIUM_NETWORK_LIFETIME;
00474     } else {
00475         lifetime = PAN_VERSION_LARGE_NETWORK_LIFETIME;
00476     }
00477 
00478     return lifetime;
00479 
00480 }
00481 
00482 uint32_t ws_common_version_timeout_get(uint8_t config)
00483 {
00484     uint32_t lifetime;
00485     if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) {
00486         lifetime = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
00487     } else if (config == NETWORK_SIZE_MEDIUM) {
00488         lifetime = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
00489     } else {
00490         lifetime = PAN_VERSION_LARGE_NETWORK_TIMEOUT;
00491     }
00492 
00493     return lifetime;
00494 }
00495 
00496 
00497 #endif // HAVE_WS
00498