mirror of https://github.com/ARMmbed/mbed-os.git
1450 lines
56 KiB
C
1450 lines
56 KiB
C
/*
|
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "nsconfig.h"
|
|
#include "ns_types.h"
|
|
#include "ns_list.h"
|
|
#include "ns_trace.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "net_interface.h"
|
|
#include "eventOS_event.h"
|
|
#include "NWK_INTERFACE/Include/protocol.h"
|
|
#include "6LoWPAN/ws/ws_common.h"
|
|
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
|
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
|
#include "6LoWPAN/ws/ws_bootstrap.h"
|
|
#include "6LoWPAN/ws/ws_pae_controller.h"
|
|
#include "ws_management_api.h"
|
|
#include "MPL/mpl.h"
|
|
|
|
#define TRACE_GROUP "cstr"
|
|
|
|
#ifdef HAVE_WS
|
|
|
|
#define CFG_SETTINGS_OK 0
|
|
#define CFG_SETTINGS_CHANGED 1
|
|
|
|
#define CFG_FLAGS_DISABLE_VAL_SET 0x01
|
|
#define CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET 0x02
|
|
#define CFG_FLAGS_FORCE_INTERNAL_CONFIG 0x04
|
|
#define CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE 0x08
|
|
|
|
#define TRICKLE_IMIN_60_SECS 60
|
|
#define TRICKLE_IMIN_30_SECS 30
|
|
#define TRICKLE_IMIN_15_SECS 15
|
|
|
|
typedef struct ws_cfg_nw_size_s {
|
|
ws_gen_cfg_t gen; /**< General configuration */
|
|
ws_timing_cfg_t timing; /**< Timing configuration */
|
|
ws_bbr_cfg_t bbr; /**< RPL configuration */
|
|
ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */
|
|
ws_mpl_cfg_t mpl; /**< Multicast timing configuration*/
|
|
} ws_cfg_nw_size_t;
|
|
|
|
static uint32_t ws_test_temporary_entry_lifetime = 0;
|
|
typedef int8_t (*ws_cfg_default_set)(void *cfg);
|
|
typedef int8_t (*ws_cfg_validate)(void *cfg, void *new_cfg);
|
|
typedef int8_t (*ws_cfg_set)(protocol_interface_info_entry_t *cur, void *cfg, void *new_cfg, uint8_t *flags);
|
|
|
|
typedef struct {
|
|
ws_cfg_default_set default_set;
|
|
ws_cfg_validate validate;
|
|
ws_cfg_set set;
|
|
uint16_t setting_offset;
|
|
} ws_cfg_cb_t;
|
|
|
|
typedef union {
|
|
ws_gen_cfg_t gen;
|
|
ws_phy_cfg_t phy;
|
|
ws_timing_cfg_t timing;
|
|
ws_bbr_cfg_t bbr;
|
|
ws_fhss_cfg_t fhss;
|
|
ws_mpl_cfg_t mpl;
|
|
ws_sec_timer_cfg_t sec_timer;
|
|
ws_sec_prot_cfg_t sec_prot;
|
|
} ws_cfgs_t;
|
|
|
|
|
|
typedef struct cfg_devices_in_config {
|
|
uint8_t max_for_small;
|
|
uint8_t max_for_medium;
|
|
uint8_t max_for_large;
|
|
uint8_t max_for_xlarge;
|
|
} cfg_devices_in_config_t;
|
|
|
|
/* Table for amount of devices that certain configuration should be used
|
|
*
|
|
* larger data rates allow more devices to be used with faster settings.
|
|
*
|
|
* For example with network the size of 2000 devices we use
|
|
* Xlrage configuration with 50kbs data rate.
|
|
* Large configuration with 300kbs data rate.
|
|
* and with 600kbs data rate it is possible to use medium network settings.
|
|
*
|
|
*/
|
|
const cfg_devices_in_config_t devices_by_datarate[] = {
|
|
{ 1, 4, 10, 25}, // Configuration for 50 -100kbs
|
|
{ 1, 8, 15, 25}, // Configuration for 150kbs - 200kbs
|
|
{ 2, 15, 25, 50}, // Configuration for 300kbs
|
|
{ 3, 20, 40, 100}, // Configuration for 600kbs - 2400kbs
|
|
};
|
|
|
|
|
|
static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *external_cfg, uint8_t *cfg_flags, uint8_t *flags);
|
|
|
|
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg);
|
|
static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg);
|
|
static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg);
|
|
static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg);
|
|
static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg);
|
|
static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg);
|
|
static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg);
|
|
static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg);
|
|
static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg);
|
|
static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg);
|
|
static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg);
|
|
|
|
#define CFG_CB(default_cb, validate_cb, set_cb, offset) \
|
|
{ \
|
|
.default_set = (ws_cfg_default_set) default_cb, \
|
|
.validate = (ws_cfg_validate) validate_cb, \
|
|
.set = (ws_cfg_set) set_cb, \
|
|
.setting_offset = offset, \
|
|
}
|
|
|
|
// Create validate and set callback table
|
|
static const ws_cfg_cb_t cfg_cb[] = {
|
|
// Network size configuration must be done first
|
|
CFG_CB(ws_cfg_network_size_default_set, ws_cfg_network_size_validate, ws_cfg_network_size_set, offsetof(ws_cfg_t, gen)),
|
|
CFG_CB(ws_cfg_gen_default_set, ws_cfg_gen_validate, ws_cfg_gen_set, offsetof(ws_cfg_t, gen)),
|
|
CFG_CB(ws_cfg_phy_default_set, ws_cfg_phy_validate, ws_cfg_phy_set, offsetof(ws_cfg_t, phy)),
|
|
CFG_CB(ws_cfg_timing_default_set, ws_cfg_timing_validate, ws_cfg_timing_set, offsetof(ws_cfg_t, timing)),
|
|
CFG_CB(ws_cfg_bbr_default_set, ws_cfg_bbr_validate, ws_cfg_bbr_set, offsetof(ws_cfg_t, bbr)),
|
|
CFG_CB(ws_cfg_mpl_default_set, ws_cfg_mpl_validate, ws_cfg_mpl_set, offsetof(ws_cfg_t, mpl)),
|
|
CFG_CB(ws_cfg_fhss_default_set, ws_cfg_fhss_validate, ws_cfg_fhss_set, offsetof(ws_cfg_t, fhss)),
|
|
CFG_CB(ws_cfg_sec_timer_default_set, ws_cfg_sec_timer_validate, ws_cfg_sec_timer_set, offsetof(ws_cfg_t, sec_timer)),
|
|
CFG_CB(ws_cfg_sec_prot_default_set, ws_cfg_sec_prot_validate, ws_cfg_sec_prot_set, offsetof(ws_cfg_t, sec_prot)),
|
|
};
|
|
|
|
#define CFG_CB_NUM (sizeof(cfg_cb) / sizeof(ws_cfg_cb_t))
|
|
|
|
// Wisun configuration storage
|
|
ws_cfg_t ws_cfg;
|
|
|
|
// If automatic network size mode; external configuration shown to towards users of external APIs
|
|
ws_cfg_nw_size_t *nw_size_external_cfg = NULL;
|
|
|
|
static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *ws_cfg_ptr, uint8_t *cfg_flags, uint8_t *flags)
|
|
{
|
|
// In case target configuration is not set, uses ws_cfg storage
|
|
if (*cfg == NULL) {
|
|
// In case external configuration is not same as internal
|
|
if (nw_size_external_cfg && (!flags || !(*flags & CFG_FLAGS_FORCE_INTERNAL_CONFIG))) {
|
|
if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.gen) {
|
|
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->gen;
|
|
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.timing) {
|
|
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->timing;
|
|
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.bbr) {
|
|
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->bbr;
|
|
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.sec_prot) {
|
|
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->sec_prot;
|
|
} else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.mpl) {
|
|
*cfg = (ws_cfgs_t *) &nw_size_external_cfg->mpl;
|
|
} else {
|
|
*cfg = ws_cfg_ptr;
|
|
}
|
|
} else {
|
|
*cfg = ws_cfg_ptr;
|
|
}
|
|
|
|
if (valid_cb) {
|
|
int8_t ret = valid_cb(*cfg, new_cfg);
|
|
// On failure and if nothing is changed, returns
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!cfg_flags) {
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
*cfg_flags = 0;
|
|
if (flags) {
|
|
*cfg_flags |= *flags;
|
|
}
|
|
if (nw_size_external_cfg && !(*cfg_flags & CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET)) {
|
|
*cfg_flags |= CFG_FLAGS_DISABLE_VAL_SET;
|
|
}
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
#ifdef FEA_TRACE_SUPPORT
|
|
static void ws_cfg_trace(ws_cfgs_t *cfg, ws_cfgs_t *new_cfg, uint8_t size, char *name)
|
|
{
|
|
uint8_t *start = 0;
|
|
uint8_t *end = 0;
|
|
|
|
tr_debug("config set: %s, changed fields:", name);
|
|
|
|
bool print_index = true;
|
|
for (uint8_t i = 0; i < size; i++) {
|
|
if (((uint8_t *) cfg)[i] != ((uint8_t *) new_cfg)[i]) {
|
|
if (print_index) {
|
|
start = &((uint8_t *) new_cfg)[i];
|
|
print_index = false;
|
|
}
|
|
end = &((uint8_t *) new_cfg)[i];
|
|
} else {
|
|
if (start && end) {
|
|
tr_debug("i: %p v: %s ", (void *)(start - ((uint8_t *) new_cfg)), trace_array(start, end - start + 1));
|
|
}
|
|
start = NULL;
|
|
end = NULL;
|
|
print_index = true;
|
|
}
|
|
}
|
|
|
|
if (start && end) {
|
|
tr_debug("i: %p v: %s ", (void *)(start - ((uint8_t *) new_cfg)), trace_array(start, end - start + 1));
|
|
}
|
|
}
|
|
#else
|
|
#define ws_cfg_trace(cfg, new_cfg, size, name)
|
|
#endif
|
|
|
|
static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg)
|
|
{
|
|
cfg->network_size = NETWORK_SIZE_MEDIUM;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_gen_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, 0);
|
|
|
|
if (cfg->network_size != new_cfg->network_size) {
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
typedef void (*ws_cfg_network_size_config_set_size)(ws_cfg_nw_size_t *cfg);
|
|
|
|
int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_network_size_validate, (ws_cfgs_t *) &ws_cfg.gen, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
uint8_t old_network_size = cfg->network_size;
|
|
|
|
// If network size configuration has not changed, returns
|
|
if (cfg->network_size == new_cfg->network_size) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
cfg->network_size = new_cfg->network_size;
|
|
|
|
ws_cfg_nw_size_t nw_size_cfg;
|
|
ws_cfg_gen_get(&nw_size_cfg.gen, NULL);
|
|
ws_cfg_timing_get(&nw_size_cfg.timing, NULL);
|
|
ws_cfg_bbr_get(&nw_size_cfg.bbr, NULL);
|
|
ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot, NULL);
|
|
ws_cfg_mpl_get(&nw_size_cfg.mpl, NULL);
|
|
|
|
ws_cfg_network_size_config_set_size set_function = NULL;
|
|
|
|
if (ws_cfg_network_config_get(cur) == CONFIG_CERTIFICATE) {
|
|
set_function = ws_cfg_network_size_config_set_certificate;
|
|
} else if (ws_cfg_network_config_get(cur) == CONFIG_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
set_function = ws_cfg_network_size_config_set_small;
|
|
} else if (ws_cfg_network_config_get(cur) == CONFIG_MEDIUM) {
|
|
set_function = ws_cfg_network_size_config_set_medium;
|
|
} else if (ws_cfg_network_config_get(cur) == CONFIG_LARGE) {
|
|
set_function = ws_cfg_network_size_config_set_large;
|
|
} else {
|
|
set_function = ws_cfg_network_size_config_set_xlarge;
|
|
}
|
|
|
|
// Overrides the values on the new configuration
|
|
if (set_function != NULL) {
|
|
set_function(&nw_size_cfg);
|
|
}
|
|
|
|
/* If no longer in an automatic network size mode, frees automatic configuration,
|
|
so that new configuration is set */
|
|
if (nw_size_external_cfg && old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ns_dyn_mem_free(nw_size_external_cfg);
|
|
nw_size_external_cfg = NULL;
|
|
}
|
|
|
|
uint8_t set_flags = 0;
|
|
if (cfg->network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
set_flags = CFG_FLAGS_DISABLE_VAL_SET;
|
|
}
|
|
/* Sets values if changed or network size has been previously automatic (to make sure
|
|
the settings are in sync */
|
|
if (ws_cfg_gen_validate(&ws_cfg.gen, &nw_size_cfg.gen) == CFG_SETTINGS_CHANGED ||
|
|
old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ws_cfg_gen_set(cur, &ws_cfg.gen, &nw_size_cfg.gen, &set_flags);
|
|
}
|
|
if (ws_cfg_timing_validate(&ws_cfg.timing, &nw_size_cfg.timing) == CFG_SETTINGS_CHANGED ||
|
|
old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ws_cfg_timing_set(cur, &ws_cfg.timing, &nw_size_cfg.timing, &set_flags);
|
|
}
|
|
if (ws_cfg_bbr_validate(&ws_cfg.bbr, &nw_size_cfg.bbr) == CFG_SETTINGS_CHANGED ||
|
|
old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ws_cfg_bbr_set(cur, &ws_cfg.bbr, &nw_size_cfg.bbr, &set_flags);
|
|
}
|
|
if (ws_cfg_sec_prot_validate(&ws_cfg.sec_prot, &nw_size_cfg.sec_prot) == CFG_SETTINGS_CHANGED ||
|
|
old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ws_cfg_sec_prot_set(cur, &ws_cfg.sec_prot, &nw_size_cfg.sec_prot, &set_flags);
|
|
}
|
|
if (ws_cfg_mpl_validate(&ws_cfg.mpl, &nw_size_cfg.mpl) == CFG_SETTINGS_CHANGED ||
|
|
old_network_size == NETWORK_SIZE_AUTOMATIC) {
|
|
ws_cfg_mpl_set(cur, &ws_cfg.mpl, &nw_size_cfg.mpl, &set_flags);
|
|
}
|
|
|
|
// If is in an automatic network size mode, updates automatic configuration
|
|
if (cfg->network_size == NETWORK_SIZE_AUTOMATIC && cur) {
|
|
ws_cfg_network_size_configure(cur, cur->ws_info->pan_information.pan_size);
|
|
}
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size)
|
|
{
|
|
// Read settings that are affected by network size
|
|
ws_cfg_nw_size_t new_nw_size_cfg;
|
|
uint8_t flags = CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET | CFG_FLAGS_FORCE_INTERNAL_CONFIG;
|
|
|
|
ws_cfg_gen_get(&new_nw_size_cfg.gen, &flags);
|
|
ws_cfg_timing_get(&new_nw_size_cfg.timing, &flags);
|
|
ws_cfg_bbr_get(&new_nw_size_cfg.bbr, &flags);
|
|
ws_cfg_sec_prot_get(&new_nw_size_cfg.sec_prot, &flags);
|
|
ws_cfg_mpl_get(&new_nw_size_cfg.mpl, &flags);
|
|
|
|
if (!nw_size_external_cfg) {
|
|
nw_size_external_cfg = ns_dyn_mem_alloc(sizeof(ws_cfg_nw_size_t));
|
|
if (!nw_size_external_cfg) {
|
|
return -1;
|
|
}
|
|
memcpy(nw_size_external_cfg, &new_nw_size_cfg, sizeof(ws_cfg_nw_size_t));
|
|
}
|
|
|
|
// Small
|
|
if (network_size < 100) {
|
|
// Automatic
|
|
ws_cfg_network_size_config_set_small(&new_nw_size_cfg);
|
|
} else if (network_size < 800) {
|
|
// Medium
|
|
ws_cfg_network_size_config_set_medium(&new_nw_size_cfg);
|
|
} else if (network_size < 1500) {
|
|
// Medium
|
|
ws_cfg_network_size_config_set_large(&new_nw_size_cfg);
|
|
} else {
|
|
// Large
|
|
ws_cfg_network_size_config_set_xlarge(&new_nw_size_cfg);
|
|
}
|
|
|
|
ws_cfg_gen_set(cur, NULL, &new_nw_size_cfg.gen, &flags);
|
|
ws_cfg_timing_set(cur, NULL, &new_nw_size_cfg.timing, &flags);
|
|
ws_cfg_bbr_set(cur, NULL, &new_nw_size_cfg.bbr, &flags);
|
|
ws_cfg_sec_prot_set(cur, NULL, &new_nw_size_cfg.sec_prot, &flags);
|
|
ws_cfg_mpl_set(cur, &ws_cfg.mpl, &new_nw_size_cfg.mpl, &flags);
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur)
|
|
{
|
|
// Get size of the network Amount of devices in the network
|
|
// Get the data rate of the network
|
|
// Adjust the configuration type based on the network size and data rate
|
|
|
|
(void)cur;
|
|
|
|
ws_gen_cfg_t cfg;
|
|
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
|
|
return CONFIG_SMALL;
|
|
}
|
|
ws_phy_cfg_t phy_cfg;
|
|
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
|
|
return CONFIG_SMALL;
|
|
}
|
|
|
|
uint32_t data_rate = ws_get_datarate_using_operating_mode(phy_cfg.operating_mode);
|
|
uint8_t index;
|
|
if (data_rate < 150000) {
|
|
index = 0;
|
|
} else if (data_rate < 300000) {
|
|
index = 1;
|
|
} else if (data_rate < 600000) {
|
|
index = 2;
|
|
} else {
|
|
index = 3;
|
|
}
|
|
|
|
if (cfg.network_size == NETWORK_SIZE_CERTIFICATE) {
|
|
return CONFIG_CERTIFICATE;
|
|
} else if (cfg.network_size <= devices_by_datarate[index].max_for_small) {
|
|
return CONFIG_SMALL;
|
|
} else if (cfg.network_size <= devices_by_datarate[index].max_for_medium) {
|
|
return CONFIG_MEDIUM;
|
|
} else if (cfg.network_size <= devices_by_datarate[index].max_for_large) {
|
|
return CONFIG_LARGE;
|
|
}
|
|
return CONFIG_XLARGE;
|
|
}
|
|
|
|
|
|
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN parent configuration
|
|
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
|
|
|
// Configure the Wi-SUN timing trickle parameter
|
|
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds
|
|
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds
|
|
cfg->timing.disc_trickle_k = 1;
|
|
cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
|
|
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
|
|
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT;
|
|
|
|
// RPL configuration
|
|
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds
|
|
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128
|
|
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
|
|
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
|
|
|
|
// EAPOL configuration
|
|
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
|
|
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
|
|
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
|
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
|
|
|
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
|
|
|
|
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
// Multicast timing configuration
|
|
cfg->mpl.mpl_trickle_imin = MPL_SMALL_IMIN;
|
|
cfg->mpl.mpl_trickle_imax = MPL_SMALL_IMAX;
|
|
cfg->mpl.mpl_trickle_k = MPL_SMALL_K;
|
|
cfg->mpl.mpl_trickle_timer_exp = MPL_SMALL_EXPIRATIONS;
|
|
cfg->mpl.seed_set_entry_lifetime = MPL_SMALL_SEED_LIFETIME;
|
|
|
|
}
|
|
|
|
static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN parent configuration
|
|
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
|
|
|
// Configure the Wi-SUN timing trickle parameters
|
|
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds
|
|
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes
|
|
cfg->timing.disc_trickle_k = 1;
|
|
cfg->timing.pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
|
|
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
|
|
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_MEDIUM_TIMEOUT;
|
|
|
|
// RPL configuration
|
|
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 17; 128s
|
|
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 3; 1024s
|
|
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10
|
|
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
|
|
|
|
// EAPOL configuration
|
|
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
|
|
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
|
|
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
|
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
|
|
|
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
|
|
|
|
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->sec_prot.initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->sec_prot.initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
// Multicast timing configuration
|
|
cfg->mpl.mpl_trickle_imin = MPL_MEDIUM_IMIN;
|
|
cfg->mpl.mpl_trickle_imax = MPL_MEDIUM_IMAX;
|
|
cfg->mpl.mpl_trickle_k = MPL_MEDIUM_K;
|
|
cfg->mpl.mpl_trickle_timer_exp = MPL_MEDIUM_EXPIRATIONS;
|
|
cfg->mpl.seed_set_entry_lifetime = MPL_MEDIUM_SEED_LIFETIME;
|
|
}
|
|
|
|
static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN parent configuration
|
|
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
|
|
|
// Configure the Wi-SUN timing trickle parameters
|
|
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 2; // 240 seconds
|
|
cfg->timing.disc_trickle_imax = 1536; // 1536 seconds; 25 minutes
|
|
cfg->timing.disc_trickle_k = 1;
|
|
cfg->timing.pan_timeout = PAN_VERSION_LARGE_NETWORK_TIMEOUT;
|
|
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE;
|
|
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT;
|
|
|
|
// RPL configuration
|
|
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 18; 262s, 4.5min
|
|
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_LARGE; // 3; 2048s, 34min
|
|
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10
|
|
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
|
|
|
|
// EAPOL configuration
|
|
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN;
|
|
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX;
|
|
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
|
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
|
|
|
|
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
|
|
|
|
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->sec_prot.initial_key_imin = LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->sec_prot.initial_key_imax = LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->sec_prot.initial_key_retry_cnt = LARGE_NW_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
// Multicast timing configuration
|
|
cfg->mpl.mpl_trickle_imin = MPL_LARGE_IMIN;
|
|
cfg->mpl.mpl_trickle_imax = MPL_LARGE_IMAX;
|
|
cfg->mpl.mpl_trickle_k = MPL_LARGE_K;
|
|
cfg->mpl.mpl_trickle_timer_exp = MPL_LARGE_EXPIRATIONS;
|
|
cfg->mpl.seed_set_entry_lifetime = MPL_LARGE_SEED_LIFETIME;
|
|
|
|
}
|
|
|
|
static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN parent configuration
|
|
cfg->gen.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
|
|
|
// Configure the Wi-SUN timing trickle parameters
|
|
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 2; // 240 seconds
|
|
cfg->timing.disc_trickle_imax = 1920; // 1920 seconds; 32 minutes
|
|
cfg->timing.disc_trickle_k = 1;
|
|
cfg->timing.pan_timeout = PAN_VERSION_XLARGE_NETWORK_TIMEOUT;
|
|
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE;
|
|
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT;
|
|
|
|
// RPL configuration
|
|
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_XLARGE; // 18; 262s, 4.5min
|
|
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_XLARGE; // 4; 2048s, 34min
|
|
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_XLARGE; // 10
|
|
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
|
|
|
|
// EAPOL configuration
|
|
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN;
|
|
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX;
|
|
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
|
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
|
|
|
|
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
|
|
|
|
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->sec_prot.initial_key_imin = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->sec_prot.initial_key_imax = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->sec_prot.initial_key_retry_cnt = EXTRA_LARGE_NW_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
// Multicast timing configuration
|
|
cfg->mpl.mpl_trickle_imin = MPL_XLARGE_IMIN;
|
|
cfg->mpl.mpl_trickle_imax = MPL_XLARGE_IMAX;
|
|
cfg->mpl.mpl_trickle_k = MPL_XLARGE_K;
|
|
cfg->mpl.mpl_trickle_timer_exp = MPL_XLARGE_EXPIRATIONS;
|
|
cfg->mpl.seed_set_entry_lifetime = MPL_XLARGE_SEED_LIFETIME;
|
|
}
|
|
|
|
static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN parent configuration
|
|
cfg->gen.rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->gen.rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX;
|
|
|
|
// Configure the Wi-SUN timing trickle parameters
|
|
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds
|
|
cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds
|
|
cfg->timing.disc_trickle_k = 1;
|
|
cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
|
|
cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
|
|
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_SMALL_TIMEOUT;
|
|
|
|
// RPL configuration (small)
|
|
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds
|
|
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128
|
|
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
|
|
cfg->bbr.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->bbr.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
|
|
|
|
// EAPOL configuration
|
|
cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
|
|
cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
|
|
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
|
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
|
|
|
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
|
|
|
|
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
// Multicast timing configuration for certification uses the LARGE values as it is the one mentioned ins specification
|
|
cfg->mpl.mpl_trickle_imin = MPL_XLARGE_IMIN;
|
|
cfg->mpl.mpl_trickle_imax = MPL_XLARGE_IMAX;
|
|
cfg->mpl.mpl_trickle_k = MPL_XLARGE_K;
|
|
cfg->mpl.mpl_trickle_timer_exp = MPL_XLARGE_EXPIRATIONS;
|
|
cfg->mpl.seed_set_entry_lifetime = MPL_XLARGE_SEED_LIFETIME;
|
|
}
|
|
|
|
static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg)
|
|
{
|
|
memset(cfg->network_name, 0, sizeof(cfg->network_name));
|
|
cfg->network_pan_id = 0xffff;
|
|
cfg->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
|
cfg->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_gen_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, 0);
|
|
|
|
if (strlen(new_cfg->network_name) > 32) {
|
|
return CFG_SETTINGS_ERROR_GEN_CONF;
|
|
}
|
|
|
|
// Regulator domain, operating mode or class has changed
|
|
if (strcmp(cfg->network_name, new_cfg->network_name) != 0 ||
|
|
cfg->network_pan_id != new_cfg->network_pan_id ||
|
|
cfg->rpl_parent_candidate_max != new_cfg->rpl_parent_candidate_max ||
|
|
cfg->rpl_selected_parent_max != new_cfg->rpl_selected_parent_max) {
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
(void) cur;
|
|
(void) flags;
|
|
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_gen_validate, (ws_cfgs_t *) &ws_cfg.gen, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_gen_cfg_t), "gen");
|
|
|
|
if (&cfg->network_name != &new_cfg->network_name) {
|
|
strncpy(cfg->network_name, new_cfg->network_name, 32);
|
|
}
|
|
cfg->network_pan_id = new_cfg->network_pan_id;
|
|
cfg->rpl_parent_candidate_max = new_cfg->rpl_parent_candidate_max;
|
|
cfg->rpl_selected_parent_max = new_cfg->rpl_selected_parent_max;
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
|
|
ws_bootstrap_restart_delayed(cur->id);
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg)
|
|
{
|
|
// FHSS configuration
|
|
cfg->regulatory_domain = REG_DOMAIN_EU;
|
|
cfg->operating_mode = OPERATING_MODE_3;
|
|
cfg->operating_class = 2;
|
|
cfg->phy_mode_id = 255;
|
|
cfg->channel_plan_id = 255;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_phy_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.phy, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.phy, 0, 0);
|
|
|
|
// Regulator domain, operating mode or class has changed
|
|
if (cfg->regulatory_domain != new_cfg->regulatory_domain ||
|
|
cfg->operating_mode != new_cfg->operating_mode ||
|
|
cfg->operating_class != new_cfg->operating_class ||
|
|
cfg->phy_mode_id != new_cfg->phy_mode_id ||
|
|
cfg->channel_plan_id != new_cfg->channel_plan_id) {
|
|
|
|
ws_hopping_schedule_t hopping_schdule = {
|
|
.regulatory_domain = new_cfg->regulatory_domain,
|
|
.operating_mode = new_cfg->operating_mode,
|
|
.operating_class = new_cfg->operating_class,
|
|
.phy_mode_id = new_cfg->phy_mode_id,
|
|
.channel_plan_id = new_cfg->channel_plan_id
|
|
};
|
|
|
|
// Check that new settings are valid
|
|
if (ws_common_regulatory_domain_config(NULL, &hopping_schdule) < 0) {
|
|
// Invalid regulatory domain set
|
|
return CFG_SETTINGS_ERROR_PHY_CONF;
|
|
}
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_phy_validate, (ws_cfgs_t *) &ws_cfg.phy, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
// Check settings and configure interface
|
|
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
// Set operating mode for FSK if given with PHY mode ID
|
|
if ((new_cfg->phy_mode_id == 1) || (new_cfg->phy_mode_id == 17)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1a;
|
|
} else if ((new_cfg->phy_mode_id == 2) || (new_cfg->phy_mode_id == 18)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1b;
|
|
} else if ((new_cfg->phy_mode_id == 3) || (new_cfg->phy_mode_id == 19)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2a;
|
|
} else if ((new_cfg->phy_mode_id == 4) || (new_cfg->phy_mode_id == 20)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2b;
|
|
} else if ((new_cfg->phy_mode_id == 5) || (new_cfg->phy_mode_id == 21)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
|
|
} else if ((new_cfg->phy_mode_id == 6) || (new_cfg->phy_mode_id == 22)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4a;
|
|
} else if ((new_cfg->phy_mode_id == 7) || (new_cfg->phy_mode_id == 23)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4b;
|
|
} else if ((new_cfg->phy_mode_id == 8) || (new_cfg->phy_mode_id == 24)) {
|
|
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_5;
|
|
} else {
|
|
cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode;
|
|
}
|
|
cur->ws_info->hopping_schdule.phy_mode_id = new_cfg->phy_mode_id;
|
|
cur->ws_info->hopping_schdule.channel_plan_id = new_cfg->channel_plan_id;
|
|
cur->ws_info->hopping_schdule.regulatory_domain = new_cfg->regulatory_domain;
|
|
cur->ws_info->hopping_schdule.operating_class = new_cfg->operating_class;
|
|
|
|
if (ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule) < 0) {
|
|
return CFG_SETTINGS_ERROR_PHY_CONF;
|
|
}
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_phy_cfg_t), "phy");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
|
|
ws_bootstrap_restart_delayed(cur->id);
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg)
|
|
{
|
|
// Configure the Wi-SUN timing trickle parameters
|
|
cfg->disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds
|
|
cfg->disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes
|
|
cfg->disc_trickle_k = 1;
|
|
cfg->pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
|
|
cfg->temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
|
|
cfg->temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_MEDIUM_TIMEOUT;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_timing_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.timing, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.timing, 0, 0);
|
|
|
|
if (cfg->disc_trickle_imin != new_cfg->disc_trickle_imin ||
|
|
cfg->disc_trickle_imax != new_cfg->disc_trickle_imax ||
|
|
cfg->disc_trickle_k != new_cfg->disc_trickle_k ||
|
|
cfg->pan_timeout != new_cfg->pan_timeout ||
|
|
cfg->temp_link_min_timeout != new_cfg->temp_link_min_timeout) {
|
|
|
|
// Discovery Imin 1 to 255
|
|
if (new_cfg->disc_trickle_imin < 1 || new_cfg->disc_trickle_imin > 255) {
|
|
return CFG_SETTINGS_ERROR_TIMING_CONF;
|
|
}
|
|
// Discovery Imax, 1 to 8 doublings of imin
|
|
if (new_cfg->disc_trickle_imax < new_cfg->disc_trickle_imin * 2 ||
|
|
new_cfg->disc_trickle_imax > new_cfg->disc_trickle_imin * 256) {
|
|
return CFG_SETTINGS_ERROR_TIMING_CONF;
|
|
}
|
|
// Discovery k parameter defined to be 1
|
|
if (cfg->disc_trickle_k != 1) {
|
|
return CFG_SETTINGS_ERROR_TIMING_CONF;
|
|
}
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_timing_validate, (ws_cfgs_t *) &ws_cfg.timing, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
cur->ws_info->trickle_params_pan_discovery.Imin = new_cfg->disc_trickle_imin * 10;
|
|
cur->ws_info->trickle_params_pan_discovery.Imax = new_cfg->disc_trickle_imax * 10;
|
|
cur->ws_info->trickle_params_pan_discovery.k = new_cfg->disc_trickle_k;
|
|
cur->ws_info->trickle_params_pan_discovery.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE;
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_timing_cfg_t), "timing");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg)
|
|
{
|
|
// Something in between
|
|
// imin: 17 (128s)
|
|
// doublings:3 (1024s)
|
|
// redundancy; 10
|
|
//ws_bbr_rpl_config(cur, 17, 3, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
|
|
|
|
cfg->dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 128s
|
|
cfg->dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 1024s
|
|
cfg->dio_redundancy_constant = 10;
|
|
cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
|
cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
|
cfg->dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_bbr_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.bbr, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.bbr, 0, 0);
|
|
|
|
if (cfg->dio_interval_min != new_cfg->dio_interval_min ||
|
|
cfg->dio_interval_doublings != new_cfg->dio_interval_doublings ||
|
|
cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant ||
|
|
cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase ||
|
|
cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase ||
|
|
cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime) {
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
(void) cur;
|
|
(void) flags;
|
|
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_bbr_validate, (ws_cfgs_t *) &ws_cfg.bbr, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (!(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
// cur is optional, default values are for Wi-SUN small network parameters,
|
|
ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings,
|
|
new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase,
|
|
new_cfg->min_hop_rank_increase);
|
|
ws_bbr_dhcp_address_lifetime_set(cur, new_cfg->dhcp_address_lifetime);
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_bbr_cfg_t), "rpl");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg)
|
|
{
|
|
// MPL configuration
|
|
cfg->mpl_trickle_imin = MPL_MEDIUM_IMIN;
|
|
cfg->mpl_trickle_imax = MPL_MEDIUM_IMAX;
|
|
cfg->mpl_trickle_k = MPL_MEDIUM_K;
|
|
cfg->mpl_trickle_timer_exp = MPL_MEDIUM_EXPIRATIONS;
|
|
cfg->seed_set_entry_lifetime = MPL_MEDIUM_SEED_LIFETIME;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_mpl_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.mpl, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.mpl, 0, 0);
|
|
|
|
// MPL configuration has changed
|
|
if (cfg->mpl_trickle_imin != new_cfg->mpl_trickle_imin ||
|
|
cfg->mpl_trickle_imax != new_cfg->mpl_trickle_imax ||
|
|
cfg->mpl_trickle_k != new_cfg->mpl_trickle_k ||
|
|
cfg->mpl_trickle_timer_exp != new_cfg->mpl_trickle_timer_exp ||
|
|
cfg->seed_set_entry_lifetime != new_cfg->seed_set_entry_lifetime) {
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
|
|
// In Wi-SUN Border router will have modified settings to improve reliability
|
|
if (cur && cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
|
// Border router sends multiple packets to ensure start of sequence
|
|
if (new_cfg->mpl_trickle_timer_exp < MPL_BORDER_ROUTER_MIN_EXPIRATIONS) {
|
|
new_cfg->mpl_trickle_timer_exp = MPL_BORDER_ROUTER_MIN_EXPIRATIONS;
|
|
// Lifetime is calculated using the original IMAX
|
|
new_cfg->seed_set_entry_lifetime = new_cfg->mpl_trickle_imax * new_cfg->mpl_trickle_timer_exp * MPL_SAFE_HOP_COUNT;
|
|
}
|
|
// Border router should have shorter IMAX to speed startup
|
|
if (new_cfg->mpl_trickle_imax > MPL_BORDER_ROUTER_MAXIMUM_IMAX) {
|
|
new_cfg->mpl_trickle_imax = MPL_BORDER_ROUTER_MAXIMUM_IMAX;
|
|
}
|
|
}
|
|
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_mpl_validate, (ws_cfgs_t *) &ws_cfg.mpl, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
cur->mpl_data_trickle_params.Imin = MPL_MS_TO_TICKS(new_cfg->mpl_trickle_imin * 1000);
|
|
cur->mpl_data_trickle_params.Imax = MPL_MS_TO_TICKS(new_cfg->mpl_trickle_imax * 1000);
|
|
cur->mpl_data_trickle_params.k = new_cfg->mpl_trickle_k;
|
|
cur->mpl_data_trickle_params.TimerExpirations = new_cfg->mpl_trickle_timer_exp;
|
|
cur->mpl_seed_set_entry_lifetime = new_cfg->seed_set_entry_lifetime;
|
|
|
|
if (cur->mpl_domain) {
|
|
// Update MPL settings
|
|
mpl_domain_change_timing(cur->mpl_domain, &cur->mpl_data_trickle_params, cur->mpl_seed_set_entry_lifetime);
|
|
}
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_mpl_cfg_t), "mpl");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg)
|
|
{
|
|
// Set defaults for the device. user can modify these.
|
|
cfg->fhss_uc_fixed_channel = 0xffff;
|
|
cfg->fhss_bc_fixed_channel = 0xffff;
|
|
cfg->fhss_uc_dwell_interval = WS_FHSS_UC_DWELL_INTERVAL;
|
|
cfg->fhss_bc_interval = WS_FHSS_BC_INTERVAL;
|
|
cfg->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL;
|
|
cfg->fhss_uc_channel_function = WS_DH1CF;
|
|
cfg->fhss_bc_channel_function = WS_DH1CF;
|
|
|
|
for (uint8_t n = 0; n < 8; n++) {
|
|
cfg->fhss_channel_mask[n] = 0xffffffff;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_fhss_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.fhss, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.fhss, 0, 0);
|
|
|
|
if (memcmp(cfg->fhss_channel_mask, new_cfg->fhss_channel_mask, sizeof(uint32_t) * 8) != 0 ||
|
|
cfg->fhss_uc_dwell_interval != new_cfg->fhss_uc_dwell_interval ||
|
|
cfg->fhss_bc_dwell_interval != new_cfg->fhss_bc_dwell_interval ||
|
|
cfg->fhss_bc_interval != new_cfg->fhss_bc_interval ||
|
|
cfg->fhss_uc_channel_function != new_cfg->fhss_uc_channel_function ||
|
|
cfg->fhss_bc_channel_function != new_cfg->fhss_bc_channel_function ||
|
|
cfg->fhss_uc_fixed_channel != new_cfg->fhss_uc_fixed_channel ||
|
|
cfg->fhss_bc_fixed_channel != new_cfg->fhss_bc_fixed_channel) {
|
|
|
|
if (new_cfg->fhss_uc_dwell_interval < 15) {
|
|
return CFG_SETTINGS_ERROR_FHSS_CONF;
|
|
}
|
|
|
|
if (new_cfg->fhss_bc_dwell_interval < 100) {
|
|
return CFG_SETTINGS_ERROR_FHSS_CONF;
|
|
}
|
|
|
|
if (cfg->fhss_uc_channel_function != WS_FIXED_CHANNEL &&
|
|
cfg->fhss_uc_channel_function != WS_VENDOR_DEF_CF &&
|
|
cfg->fhss_uc_channel_function != WS_DH1CF &&
|
|
cfg->fhss_uc_channel_function != WS_TR51CF) {
|
|
return CFG_SETTINGS_ERROR_FHSS_CONF;
|
|
}
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_fhss_set(protocol_interface_info_entry_t *cur, ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
(void) cur;
|
|
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_fhss_validate, (ws_cfgs_t *) &ws_cfg.fhss, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_fhss_cfg_t), "fhss");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
if (cfg->fhss_uc_channel_function == WS_FIXED_CHANNEL && cfg->fhss_uc_fixed_channel == 0xffff) {
|
|
cfg->fhss_uc_fixed_channel = 0;
|
|
tr_warn("UC fixed channel not configured. Set to 0");
|
|
}
|
|
|
|
if (cfg->fhss_uc_channel_function != WS_FIXED_CHANNEL) {
|
|
cfg->fhss_uc_fixed_channel = 0xffff;
|
|
}
|
|
|
|
if (cfg->fhss_bc_channel_function == WS_FIXED_CHANNEL && cfg->fhss_bc_fixed_channel == 0xffff) {
|
|
cfg->fhss_bc_fixed_channel = 0;
|
|
tr_warn("BC fixed channel not configured. Set to 0");
|
|
}
|
|
|
|
if (cfg->fhss_bc_channel_function != WS_FIXED_CHANNEL) {
|
|
cfg->fhss_bc_fixed_channel = 0xffff;
|
|
}
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
|
|
ws_bootstrap_restart_delayed(cur->id);
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg)
|
|
{
|
|
cfg->gtk_expire_offset = DEFAULT_GTK_EXPIRE_OFFSET;
|
|
cfg->pmk_lifetime = DEFAULT_PMK_LIFETIME;
|
|
cfg->ptk_lifetime = DEFAULT_PTK_LIFETIME;
|
|
cfg->gtk_new_act_time = DEFAULT_GTK_NEW_ACTIVATION_TIME;
|
|
cfg->revocat_lifetime_reduct = DEFAULT_REVOCATION_LIFETIME_REDUCTION;
|
|
cfg->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN;
|
|
cfg->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX;
|
|
cfg->gtk_max_mismatch = DEFAULT_GTK_MAX_MISMATCH;
|
|
cfg->gtk_new_install_req = DEFAULT_GTK_NEW_INSTALL_REQUIRED;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_sec_timer_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.sec_timer, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.sec_timer, 0, 0);
|
|
|
|
if (cfg->gtk_expire_offset != new_cfg->gtk_expire_offset ||
|
|
cfg->pmk_lifetime != new_cfg->pmk_lifetime ||
|
|
cfg->ptk_lifetime != new_cfg->ptk_lifetime ||
|
|
cfg->gtk_new_act_time != new_cfg->gtk_new_act_time ||
|
|
cfg->revocat_lifetime_reduct != new_cfg->revocat_lifetime_reduct ||
|
|
cfg->gtk_request_imin != new_cfg->gtk_request_imin ||
|
|
cfg->gtk_request_imax != new_cfg->gtk_request_imax ||
|
|
cfg->gtk_max_mismatch != new_cfg->gtk_max_mismatch ||
|
|
cfg->gtk_new_install_req != new_cfg->gtk_new_install_req) {
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_sec_timer_validate, (ws_cfgs_t *) &ws_cfg.sec_timer, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
ws_pae_controller_configure(cur, new_cfg, NULL);
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_timer_cfg_t), "sec_timer");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg)
|
|
{
|
|
cfg->sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN;
|
|
cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
|
|
cfg->sec_prot_trickle_timer_exp = 2;
|
|
cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
|
cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
|
|
cfg->initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
|
cfg->initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
|
cfg->initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
|
cfg->initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags)
|
|
{
|
|
ws_sec_prot_cfg_t *get_cfg = NULL;
|
|
ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.sec_prot, 0, flags);
|
|
*cfg = *get_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg)
|
|
{
|
|
ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.sec_prot, 0, 0);
|
|
|
|
if (cfg->sec_prot_trickle_imin != new_cfg->sec_prot_trickle_imin ||
|
|
cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax ||
|
|
cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp ||
|
|
cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout ||
|
|
cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication ||
|
|
cfg->initial_key_retry_delay != new_cfg->initial_key_retry_delay ||
|
|
cfg->initial_key_imin != new_cfg->initial_key_retry_delay ||
|
|
cfg->initial_key_imax != new_cfg->initial_key_retry_delay ||
|
|
cfg->initial_key_retry_cnt != new_cfg->initial_key_retry_delay) {
|
|
|
|
return CFG_SETTINGS_CHANGED;
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg, uint8_t *flags)
|
|
{
|
|
uint8_t cfg_flags;
|
|
int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_sec_prot_validate, (ws_cfgs_t *) &ws_cfg.sec_prot, &cfg_flags, flags);
|
|
if (ret != CFG_SETTINGS_CHANGED) {
|
|
return ret;
|
|
}
|
|
|
|
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
|
ws_pae_controller_configure(cur, NULL, new_cfg);
|
|
}
|
|
|
|
if (cfg == new_cfg) {
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_prot_cfg_t), "sec_prot");
|
|
|
|
*cfg = *new_cfg;
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_init(void)
|
|
{
|
|
ws_cfg_settings_default_set();
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_default_set(void)
|
|
{
|
|
int8_t ret_value = 0;
|
|
|
|
// Set default configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
if (cfg_cb[index].default_set) {
|
|
if (cfg_cb[index].default_set(
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset) < 0) {
|
|
ret_value = CFG_SETTINGS_OTHER_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set new configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
uint8_t flags = 0;
|
|
if (cfg_cb[index].set(NULL,
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
&flags) < 0) {
|
|
tr_info("FATAL CONFIG FAILURE");
|
|
ret_value = CFG_SETTINGS_OTHER_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur)
|
|
{
|
|
int8_t ret_value = 0;
|
|
|
|
cur->ws_info->cfg = &ws_cfg;
|
|
|
|
// Set new configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
uint8_t flags = CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE;
|
|
// Validation
|
|
if (cfg_cb[index].set) {
|
|
if (cfg_cb[index].set(cur,
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
&flags) < 0) {
|
|
tr_info("FATAL CONFIG FAILURE");
|
|
ret_value = CFG_SETTINGS_OTHER_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_get(protocol_interface_info_entry_t *cur, ws_cfg_t *cfg)
|
|
{
|
|
(void) cur;
|
|
|
|
*cfg = ws_cfg;
|
|
|
|
ws_cfg_gen_get(&cfg->gen, NULL);
|
|
ws_cfg_timing_get(&cfg->timing, NULL);
|
|
ws_cfg_bbr_get(&cfg->bbr, NULL);
|
|
ws_cfg_sec_prot_get(&cfg->sec_prot, NULL);
|
|
ws_cfg_mpl_get(&cfg->mpl, NULL);
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_validate(protocol_interface_info_entry_t *cur, struct ws_cfg_s *new_cfg)
|
|
{
|
|
(void) cur;
|
|
|
|
// Validate new configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
if (cfg_cb[index].validate) {
|
|
int8_t ret = cfg_cb[index].validate(
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
((uint8_t *)new_cfg) + cfg_cb[index].setting_offset);
|
|
if (ret < 0) {
|
|
// Validation failed
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CFG_SETTINGS_OK;
|
|
}
|
|
|
|
int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_cfg)
|
|
{
|
|
int8_t ret_value = CFG_SETTINGS_OK;
|
|
|
|
bool call_cfg_set[CFG_CB_NUM];
|
|
|
|
// Validate new configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
if (cfg_cb[index].validate) {
|
|
int8_t ret = cfg_cb[index].validate(
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
((uint8_t *)new_cfg) + cfg_cb[index].setting_offset);
|
|
|
|
if (ret < 0) {
|
|
// Validation failed
|
|
return ret;
|
|
} else if (ret == CFG_SETTINGS_CHANGED) {
|
|
call_cfg_set[index] = true;
|
|
} else {
|
|
call_cfg_set[index] = false;
|
|
}
|
|
} else {
|
|
// If validation not needed, set right away
|
|
call_cfg_set[index] = true;
|
|
}
|
|
}
|
|
|
|
// Set new configuration values
|
|
for (uint8_t index = 0; index < CFG_CB_NUM; index++) {
|
|
uint8_t flags = 0;
|
|
// Validation
|
|
if (call_cfg_set[index]) {
|
|
if (cfg_cb[index].set(cur,
|
|
((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset,
|
|
((uint8_t *)new_cfg) + cfg_cb[index].setting_offset, &flags) < 0) {
|
|
tr_info("FATAL CONFIG FAILURE");
|
|
ret_value = CFG_SETTINGS_OTHER_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
uint32_t ws_cfg_neighbour_temporary_lifetime_get(void)
|
|
{
|
|
if (ws_test_temporary_entry_lifetime) {
|
|
return ws_test_temporary_entry_lifetime;
|
|
}
|
|
return WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME;
|
|
}
|
|
void ws_cfg_neighbour_temporary_lifetime_set(uint32_t lifetime)
|
|
{
|
|
if (lifetime >= WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME || lifetime == 0) {
|
|
if (lifetime > WS_NEIGHBOR_LINK_TIMEOUT) {
|
|
lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
|
|
}
|
|
ws_test_temporary_entry_lifetime = lifetime;
|
|
}
|
|
}
|
|
|
|
#endif //HAVE_WS
|