Merge commit 'fa7202c2e699b26a024d38657a6e495e073fea07'

* commit 'fa7202c2e699b26a024d38657a6e495e073fea07':
  Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 4a3c5c525b..225a4af94f
pull/15103/head
Arto Kinnunen 2021-09-23 13:05:27 +03:00
commit b1adec9028
100 changed files with 6779 additions and 2517 deletions

View File

@ -129,10 +129,11 @@ typedef void mcps_data_request(const mac_api_t *api, const mcps_data_req_t *data
* @param ie_ext Information element list to MCPS-DATA.request
* @param asynch_channel_list Optional channel list to asynch data request. Give NULL when normal data request.
* @param priority Data request priority level
* @param phy_mode_id Use mode switch if given phy_mode_id > 0
*
* Asynch data request is mac standard extension. asynch_channel_list include channel mask which channel message is requested to send.
*/
typedef void mcps_data_request_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const struct channel_list_s *asynch_channel_list, mac_data_priority_t priority);
typedef void mcps_data_request_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const struct channel_list_s *asynch_channel_list, mac_data_priority_t priority, uint8_t phy_mode_id);
/**
* @brief mcps_purge_request MCPS_PURGE request call
@ -192,6 +193,16 @@ typedef void mcps_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_t
typedef void mcps_edfe_handler(const mac_api_t *api, mcps_edfe_response_t *response_message);
/**
* @brief mode_switch_resolver Callback to resolve configuration behind received PHY mode ID
* @param api The API which handled the response
* @param phy_mode_id PHY mode ID to be resolved
* @param rf_config Resolved configuration
* @return 0 in case of success, negative otherwise
*/
typedef int8_t mode_switch_resolver(const mac_api_t *api, uint8_t phy_mode_id, phy_rf_channel_configuration_s *rf_config);
/**
* @brief mcps_purge_confirm MCPS-PURGE confirm is called as a response to MCPS-PURGE request
* @param api The API which handled the request
@ -272,6 +283,16 @@ typedef int8_t mac_api_enable_mcps_ext(mac_api_t *api,
typedef int8_t mac_api_enable_mcps_edfe_ext(mac_api_t *api,
mcps_edfe_handler *edfe_ind_cb);
/**
* @brief mac_api_mode_switch_resolver_ext Initialises mode switch resolver callback. Upper layer must configure function when mode switch is used.
* @param api mac_api_t pointer, which is created by application.
* @param mode_resolver_cb Upper layer function to resolve received PHY mode ID
* @param base_phy_mode Base PHY mode, device returns to this mode after mode switch transmission or reception
* @return -1 if error, 0 otherwise
*/
typedef int8_t mac_api_mode_switch_resolver_ext(mac_api_t *api,
mode_switch_resolver *mode_resolver_cb, uint8_t base_phy_mode);
/**
* \brief Struct mac_api_s defines functions for two-way communications between external MAC and Upper layer.
* Application creates mac_api_t object by calling external MAC's creator function.
@ -279,30 +300,32 @@ typedef int8_t mac_api_enable_mcps_edfe_ext(mac_api_t *api,
* Then MAC is operated by Upper layer by calling MLME or MCPS primitive functions.
*/
struct mac_api_s {
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
mac_api_enable_mcps_ext *mac_mcps_extension_enable; /**< MAC MCPS IE extension enable function, optional feature */
mac_api_enable_mcps_edfe_ext *mac_mcps_edfe_enable; /**< MAC MCPS MCPS EDFE frame extension enable function, optional feature */
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
mac_api_enable_mcps_ext *mac_mcps_extension_enable; /**< MAC MCPS IE extension enable function, optional feature */
mac_api_enable_mcps_edfe_ext *mac_mcps_edfe_enable; /**< MAC MCPS MCPS EDFE frame extension enable function, optional feature */
mac_api_mode_switch_resolver_ext *mac_mode_switch_resolver_set; /**< MAC Mode switch resolver function set, optional feature */
//External MAC callbacks
mlme_request *mlme_req; /**< MAC MLME request function to use */
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
mcps_data_request_ext *mcps_data_req_ext; /**< MAC MCPS data request with Information element extension function to use */
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
mlme_request *mlme_req; /**< MAC MLME request function to use */
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
mcps_data_request_ext *mcps_data_req_ext; /**< MAC MCPS data request with Information element extension function to use */
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
//Upper layer callbacksMLME_ASSOCIATE
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
mcps_data_confirm_ext *data_conf_ext_cb; /**< MAC MCPS data confirm with payload callback function */
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
mcps_data_indication_ext *data_ind_ext_cb; /**< MAC MCPS data indication with IE extension's callback function */
mcps_edfe_handler *edfe_ind_cb; /**< MAC MCPS EDFE detection extension's callback function */
mcps_ack_data_req_ext *enhanced_ack_data_req_cb; /**< Enhanced ACK IE element and payload request from MAC user */
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
mlme_indication *mlme_ind_cb; /**< MAC MLME indication callback function */
mac_ext_mac64_address_set *mac64_set; /**< MAC extension function to set mac64 address */
mac_ext_mac64_address_get *mac64_get; /**< MAC extension function to get mac64 address */
mac_storage_decription_sizes_get *mac_storage_sizes_get; /**< Getter function to query data storage sizes from MAC */
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
mcps_data_confirm_ext *data_conf_ext_cb; /**< MAC MCPS data confirm with payload callback function */
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
mcps_data_indication_ext *data_ind_ext_cb; /**< MAC MCPS data indication with IE extension's callback function */
mcps_edfe_handler *edfe_ind_cb; /**< MAC MCPS EDFE detection extension's callback function */
mode_switch_resolver *mode_resolver_cb; /**< MAC Mode switch resolver callback function */
mcps_ack_data_req_ext *enhanced_ack_data_req_cb; /**< Enhanced ACK IE element and payload request from MAC user */
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
mlme_indication *mlme_ind_cb; /**< MAC MLME indication callback function */
mac_ext_mac64_address_set *mac64_set; /**< MAC extension function to set mac64 address */
mac_ext_mac64_address_get *mac64_get; /**< MAC extension function to get mac64 address */
mac_storage_decription_sizes_get *mac_storage_sizes_get; /**< Getter function to query data storage sizes from MAC */
int8_t parent_id; /**< Upper layer id */
uint16_t phyMTU; /**< Maximum Transmission Unit(MTU) used by MAC*/
int8_t parent_id; /**< Upper layer id */
uint16_t phyMTU; /**< Maximum Transmission Unit(MTU) used by MAC*/
};
/**

View File

@ -39,6 +39,23 @@ extern "C" {
#include "ns_types.h"
/**
* \brief Set Wi-SUN version number
*
* Sets the Wi-SUN protocol version.
* 1 = Wi-SUN FAN 1.0
* 2 = Wi-SUN FAN 1.1
*
* Set version to 0 to stop override and use stack default
*
* \param interface_id Network Interface
* \param version Wi-SUN version
*
* \return 0 OK
* \return <0 Failure
*/
int ws_test_version_set(int8_t interface_id, uint8_t version);
/**
* \brief Set Pan size.
*

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef NET_WS_TEST_EXT_H_
#define NET_WS_TEST_EXT_H_
/**
* \file net_ws_test_ext.h
* \brief Wi-SUN Library External Test API.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
/* Test procedure triggers
*
* Example about using the triggers during bootstrap to trigger
* messages and state transitions.
*
* Border Router Node
*
* Join state 1 (select PAN)
*
* PROC_PA
* ------- PAN Advertisement------------>
*
* PROC_EAPOL
* Select EAPOL target
* Join state 2 (authenticate)
* <------ EAPOL authentication -------->
* Join State 3 (acquire PAN configuration)
*
* PROC_PC
* ------- PAN Configuration ----------->
* Join state 4 (configure routing)
*
* PROC_DIO
* ------- DIO ------------------------->
* Neighbor discovery (NS probing for ETX)
* Create RPL candidate parent set
*
* PROC_RPL
* Select RPL parent
* <------ DHCP ------------------------>
*
* PROC_DAO
* <------ DAO --------------------------
* ------- DAO acknowledge ------------->
*
* Join state 5 (operational)
*
*
* On automatic mode the PROC_PAS, PROC_EAPOL, PROC_PCS, PROC_DIS and PROC_RPL
* will be triggered automatically by the node during the bootstrap.
*
*/
/**
* @brief Test procedure triggers.
*/
typedef enum {
PROC_DIS, /* trigger DODAG information object solicit (node) */
PROC_DIO, /* trigger DODAG information object (BR, node) */
PROC_DAO, /* trigger Destination advertisement object (node) */
PROC_PAS, /* trigger PAN Advertisement Solicit (node) */
PROC_PA, /* trigger PAN Advertisement (BR, node) */
PROC_PCS, /* trigger PAN Configuration Solicit (node) */
PROC_PC, /* trigger PAN Configuration (BR, node) */
PROC_EAPOL, /* trigger EAPOL target selection (initiates authentication, node) */
PROC_RPL, /* trigger RPL parent selection (node) */
PROC_AUTO_ON, /* trigger bootstrap test procedures automatically */
PROC_AUTO_OFF, /* disable automatic bootstrap test procedure triggering */
MSG_NONE
} ws_test_proc_t;
/**
* Trigger a test procedure
*
* Can be used to trigger a test procedure, e.g. to send a message (DIS,
* DIO, DAO, PAS, PS, PCS and PC) or to trigger bootstrap state change
* on node e.g. EAPOL target selection.
*
* \param interface_id Network Interface ID >= 0 or -1 for Wi-SUN mesh interface
* Default value is -1
* \param procedure Triggered procedure
* \param parameters Parameters for future extensions, shall be set to NULL
*
* \return 0 Success
* \return <0 Failure
*/
int ws_test_procedure_trigger(int8_t interface_id, ws_test_proc_t procedure, void *parameters);
#ifdef __cplusplus
}
#endif
#endif /* NET_WS_TEST_EXT_H_ */

View File

@ -61,23 +61,39 @@ static inline void ns_sha256_clone(ns_sha256_context *dst,
static inline void ns_sha256_starts(ns_sha256_context *ctx)
{
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256_starts(ctx, 0);
#else
(void)mbedtls_sha256_starts_ret(ctx, 0);
#endif
}
static inline void ns_sha256_update(ns_sha256_context *ctx, const void *input,
size_t ilen)
{
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256_update(ctx, input, ilen);
#else
(void)mbedtls_sha256_update_ret(ctx, input, ilen);
#endif
}
static inline void ns_sha256_finish(ns_sha256_context *ctx, void *output)
{
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256_finish(ctx, output);
#else
(void)mbedtls_sha256_finish_ret(ctx, output);
#endif
}
static inline void ns_sha256(const void *input, size_t ilen, void *output)
{
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256(input, ilen, output, 0);
#else
(void)mbedtls_sha256_ret(input, ilen, output, 0);
#endif
}
/* Extensions to standard mbed TLS - output the first bits of a hash only */
@ -85,10 +101,18 @@ static inline void ns_sha256(const void *input, size_t ilen, void *output)
static inline void ns_sha256_finish_nbits(ns_sha256_context *ctx, void *output, unsigned obits)
{
if (obits == 256) {
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256_finish(ctx, output);
#else
(void)mbedtls_sha256_finish_ret(ctx, output);
#endif
} else {
uint8_t sha256[32];
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256_finish(ctx, sha256);
#else
(void)mbedtls_sha256_finish_ret(ctx, sha256);
#endif
memcpy(output, sha256, obits / 8);
}
}
@ -96,10 +120,18 @@ static inline void ns_sha256_finish_nbits(ns_sha256_context *ctx, void *output,
static inline void ns_sha256_nbits(const void *input, size_t ilen, void *output, unsigned obits)
{
if (obits == 256) {
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256(input, ilen, output, 0);
#else
(void)mbedtls_sha256_ret(input, ilen, output, 0);
#endif
} else {
uint8_t sha256[32];
#if (MBEDTLS_VERSION_MAJOR >= 3)
(void)mbedtls_sha256(input, ilen, sha256, 0);
#else
(void)mbedtls_sha256_ret(input, ilen, sha256, 0);
#endif
memcpy(output, sha256, obits / 8);
}
}

View File

@ -28,6 +28,24 @@
#include "ns_types.h"
/**
* Time zone information structure.
*
* Daylight saving time and time zone information learned by network stack
*
*/
typedef struct timezone_info {
/** Timestamp of the Daylight saving time change*/
uint64_t timestamp;
/** Time zone information in minutes*/
int16_t timezone;
/** Change that is applied when timestamp is reached*/
int16_t deviation;
/** Time configuration status bit field
* "bit xxxxxxxxxxxxxxxS" 0 = false 1 = true Daylight saving time status*/
uint16_t status;
} timezone_info_t;
/**
* System time read callback.
*
@ -48,6 +66,22 @@ typedef uint64_t ns_time_api_system_time_callback(void);
*/
typedef void ns_time_api_system_time_write_callback(uint64_t write_time);
/**
* New time zone and daylight saving time information learned from stack.
*
* Called when network stack learns the time zone and daylights saving time information.
*
* In Wi-SUN Border router can distribute this information to synchronize all nodes in network.
* This information is updated roughly once a day using DHCPv6 protocol
*
* If network stack does not have the information this is not called and can be called when information becomes available.
* This can be called multiple times with same information.
*
* \param info_ptr time zone and daylight saving time configuration.
*
*/
typedef void ns_time_api_time_configuration_notify_callback(timezone_info_t *info_ptr);
/**
* System time read callback set.
*
@ -68,4 +102,15 @@ void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callb
*/
void ns_time_api_system_time_write_callback_set(ns_time_api_system_time_write_callback callback_wr);
/**
* Set system time configuration notify callback.
*
* Sets system time configuration notify callback that is called if network stack
* learns time information from other devices in the network.
*
* \param callback_wr system time write callback.
*
*/
void ns_time_api_time_configuration_notify_callback_set(ns_time_api_time_configuration_notify_callback callback_wr);
#endif /* NS_TIME_API_H_ */

View File

@ -143,6 +143,7 @@ typedef struct phy_signal_info_s {
typedef struct phy_csma_params {
uint32_t backoff_time; /**< CSMA Backoff us time before start CCA & TX. 0 should disable current backoff*/
bool cca_enabled; /**< True will affect CCA check false start TX direct after backoff */
bool mode_switch_phr; /**< True - Frame is a mode switch PHR. In this case PHY driver should skip FCS and send two byte PHR as it is given by TX callback */
} phy_csma_params_t;
/** PHY modulation scheme */

View File

@ -74,6 +74,20 @@ typedef struct bbr_radius_timing {
uint8_t radius_retry_count;
} bbr_radius_timing_t;
/**
* \brief Daylights saving time parameters.
*/
typedef struct bbr_timezone_configuration {
/** Timestamp of the Daylight saving time change*/
uint64_t timestamp;
/** Time zone information in minutes*/
int16_t timezone;
/** Change that is applied when timestamp is reached*/
int16_t deviation;
/** Time configuration status bit field
* "bit xxxxxxxxxxxxxxxS" 0 = false 1 = true Daylight saving time status*/
uint16_t status;
} bbr_timezone_configuration_t;
/**
* Start backbone border router service.
*
@ -521,4 +535,22 @@ int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timi
*/
int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr);
/**
* \brief A function to set time zone and daylights saving time configuration
*
* Border router distributes this information in DHCP Reply messages to
* all the devices joining to the Wi-SUN mesh network.
*
* Border router keeps this information until reboot and continues to distribute the information.
* If the information is changed the updates are sent to devices in network when they
* renew their address. This can take time from 1 to 24 hours
*
* \param interface_id Network interface ID.
* \param daylight_saving_time_ptr daylights saving time configuration. NULL if you want to remove the configuration.
*
* \return < 0 failure
* \return >= 0 success
*/
int ws_bbr_timezone_configuration_set(int8_t interface_id, bbr_timezone_configuration_t *daylight_saving_time_ptr);
#endif /* WS_BBR_API_H_ */

View File

@ -78,6 +78,17 @@ extern "C" {
#define CHANNEL_SPACING_800 0x05 /**< 800 khz */
#define CHANNEL_SPACING_1200 0x06 /**< 1200 khz */
/*
* Wi-SUN FAN 1.1 Phy capability types.
*
*/
#define WS_PHY_TYPE_ID_FSK 0 /**< FSK phy type */
#define WS_PHY_TYPE_ID_FSK_FEC 1 /**< FSK with FEC phy type */
#define WS_PHY_TYPE_ID_OFDM1 2 /**< OFDM1 phy type */
#define WS_PHY_TYPE_ID_OFDM2 3 /**< OFDM2 phy type */
#define WS_PHY_TYPE_ID_OFDM3 4 /**< OFDM3 phy type */
#define WS_PHY_TYPE_ID_OFDM4 5 /**< OFDM4 phy type */
/*
* Network Size definitions are device amount in hundreds of devices.
* These definitions are meant to give some estimates of sizes. Any value can be given as parameter
@ -225,6 +236,28 @@ typedef struct ws_neighbour_info {
ws_management_neighbor_type_e type;
} ws_neighbour_info_t;
/**
* @brief ws_management_pcap_t Wi-SUN FAN 1.1 Phy Capability type and operating mode
*/
typedef struct ws_management_pcap {
/** Phy type */
uint8_t phy_type;
/** Phy operating mode */
uint16_t operating_mode;
} ws_management_pcap_t;
/**
* @brief ws_management_pcap_info_t Wi-SUN FAN 1.1 Phy Capability list for MDR support
*/
typedef struct ws_management_pcap_info {
/** Length of the capability */
uint8_t length_of_list: 3;
/** Capability information */
ws_management_pcap_t pcap[7];
} ws_management_pcap_info_t;
/**
* Initialize Wi-SUN stack.
*
@ -875,6 +908,20 @@ int ws_device_min_sens_set(
int8_t interface_id,
uint8_t device_min_sens);
/**
* Set Phy Capability support for MDR, FAN 1.1 feature
*
*
* \param interface_id Network interface ID.
* \param pcap_list pointer to supported list
*
* \return 0 Success.
* \return <0 Failure.
*/
int ws_management_phy_capability_set(
int8_t interface_id,
ws_management_pcap_info_t *pcap_list);
#ifdef __cplusplus
}
#endif

View File

@ -118,7 +118,7 @@ static uint8_t protocol_buffer_valid(buffer_t *b, protocol_interface_info_entry_
void protocol_init(void)
{
tr_debug("P.Init\n");
tr_debug("P.Init");
#ifdef PANA
sec_libray_init();
#endif
@ -134,7 +134,7 @@ void protocol_6lowpan_stack(buffer_t *b)
{
protocol_interface_info_entry_t *cur = b->interface;
if (protocol_buffer_valid(b, cur) == 0) {
tr_debug("Drop Packets\n");
tr_debug("Drop Packets");
buffer_free(b);
return;
}
@ -230,7 +230,7 @@ void protocol_6lowpan_stack(buffer_t *b)
b = tcp_up(b);
break;
default:
tr_debug("LLL\n");
tr_debug("LLL");
b = buffer_free(b);
break;
}
@ -871,7 +871,7 @@ bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_am
}
// For small networks sets 10 seconds stagger
if (network_size <= 100 && ws_info(cur_interface)) {
if (ws_info(cur_interface) && (network_size <= 100 || ws_test_proc_auto_trg(cur_interface))) {
stagger_value = 10;
} else {
stagger_value = 1 + ((data_amount * 1024 * 8 * network_size) / datarate);

View File

@ -1548,7 +1548,7 @@ int8_t arm_network_processor_up(protocol_interface_info_entry_t *cur)
{
int8_t ret_val = -1;
if ((cur->configure_flags & INTERFACE_SETUP_NETWORK_DRIVER_MASK) != INTERFACE_SETUP_NETWORK_DRIVER_READY) {
tr_debug("Interface not yet fully configured\n");
tr_debug("Interface not yet fully configured");
ret_val = -5;
} else {
protocol_6lowpan_register_handlers(cur);
@ -2123,7 +2123,7 @@ static void nwk_rpl_dio_scan(protocol_interface_info_entry_t *cur)
if (nwk_bootstrap_icmp_rpl_dis_msg_tx(cur)) {
cur->bootsrap_state_machine_cnt = 45 << cur->nwk_rpl_scan_counter;
cur->nwk_rpl_scan_counter++;
tr_debug("MC_DIS\n");
tr_debug("MC_DIS");
cur->nwk_bootstrap_state = ER_RPL_SCAN;
} else {
cur->bootsrap_state_machine_cnt = 3;

View File

@ -476,13 +476,14 @@ void mac_helper_security_key_clean(protocol_interface_info_entry_t *interface)
void mac_helper_coordinator_address_set(protocol_interface_info_entry_t *interface, addrtype_t adr_type, uint8_t *adr_ptr)
{
uint16_t short_addr;
mlme_set_t set_req;
set_req.attr_index = 0;
if (adr_type == ADDR_802_15_4_SHORT) {
memcpy(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, adr_ptr, 2);
interface->mac_parameters->mac_cordinator_info.cord_adr_mode = MAC_ADDR_MODE_16_BIT;
uint16_t short_addr = common_read_16_bit(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address);
short_addr = common_read_16_bit(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address);
set_req.attr = macCoordShortAddress;
set_req.value_pointer = &short_addr;
set_req.value_size = 2;

View File

@ -144,6 +144,33 @@ uint16_t mac_ie_nested_discover(uint8_t *payload_ptr, uint16_t length, mac_neste
return 0;
}
uint16_t mac_ie_nested_tagged_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t *nested_ie, uint8_t sub_tag_id)
{
mac_nested_payload_IE_t ie_element;
uint8_t *sub_tag_ptr;
while (length >= 2) {
mac_ie_nested_id_parse(&ie_element, payload_ptr);
if (length < ie_element.length + 2) {
return 0;
}
sub_tag_ptr = ie_element.content_ptr;
if (ie_element.length > 1 && nested_ie->id == ie_element.id && *sub_tag_ptr == sub_tag_id) {
sub_tag_ptr++;
ie_element.length--;
nested_ie->content_ptr = sub_tag_ptr;
nested_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint8_t mac_ie_header_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t *header_ie)
{
mac_header_IE_t ie_element;

View File

@ -49,6 +49,9 @@ uint16_t mac_ie_payload_discover(uint8_t *payload_ptr, uint16_t length, struct m
/** Nested IE element discover inside parsed payload element */
uint16_t mac_ie_nested_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t *nested_ie);
/** Nested IE element discover with Sub Tag ID inside parsed payload element */
uint16_t mac_ie_nested_tagged_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t *nested_ie, uint8_t sub_tag_id);
/** Header IE elemnt discover */
uint8_t mac_ie_header_discover(uint8_t *header_ptr, uint16_t length, struct mac_header_IE_s *header_ie);

View File

@ -2308,7 +2308,7 @@ void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
break;
case ER_BOOTSRAP_DONE:
tr_debug("Thread SM:Bootstrap Done");
tr_info("Thread SM:Bootstrap Done");
cur->nwk_nd_re_scan_count = 0;
break;
case ER_BOOTSTRAP_SCAN_FAIL:

View File

@ -262,7 +262,7 @@ static int thread_commissioning_active_get_cb(int8_t service_id, uint8_t source_
if ((len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr)) > 0) {
state = COMMISSIONING_STATE_ACCEPT;
tr_debug(" TLV ml prefix=%s\r\n", trace_array(ptr, len));
tr_debug(" TLV ml prefix=%s", trace_array(ptr, len));
memcpy(this->leader_address, ptr, 8);
memcpy(this->leader_address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
common_write_16_bit(0xfc00, this->leader_address + 14);

View File

@ -2006,7 +2006,7 @@ void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mac_neigh
if (!thread_i_am_router(cur) && thread_endnode_parent && thread_endnode_parent->shortAddress == neighbour->mac16) {
if (cur->nwk_bootstrap_state != ER_CHILD_ID_REQ) {
tr_warn("End device lost parent, reset!\n");
tr_warn("End device lost parent, reset!");
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
}
}
@ -2238,18 +2238,18 @@ int thread_common_primary_bbr_get(struct protocol_interface_info_entry *cur, uin
(service_tlv_ptr[0] & 0x80) && // THREAD_ENTERPRISE_NUMBER
service_tlv_ptr[1] == 1 && // length 1
service_tlv_ptr[2] == THREAD_SERVICE_DATA_BBR) {
//tr_info("BBR service TLV: %s\r\n", trace_array(service_tlv_ptr, service_tlv_len));
//tr_info("BBR service TLV: %s", trace_array(service_tlv_ptr, service_tlv_len));
// try to parse SUB-TLVs
// network_data_server_tlv_parse(service_tlv_ptr, tlv_length);
uint16_t server_tlv_len = 0;
uint8_t *server_tlv_ptr = thread_common_server_tlv_list_get(service_tlv_ptr, service_tlv_len, &server_tlv_len);
uint16_t found_tlv_len;
uint8_t *found_tlv = NULL;
//tr_info("BBR server TLV: %s\r\n", trace_array(server_tlv_ptr, server_tlv_len));
//tr_info("BBR server TLV: %s", trace_array(server_tlv_ptr, server_tlv_len));
do {
found_tlv_len = thread_meshcop_tlv_find_next(server_tlv_ptr, server_tlv_len, THREAD_NWK_DATA_TYPE_SERVER_DATA | THREAD_NWK_STABLE_DATA, &found_tlv);
if (found_tlv && found_tlv_len > 8) {
//tr_info("BBR server TLV: %s\r\n", trace_array(found_tlv, found_tlv_len));
//tr_info("BBR server TLV: %s", trace_array(found_tlv, found_tlv_len));
if (addr_ptr) {
thread_addr_write_mesh_local_16(addr_ptr, common_read_16_bit(found_tlv), cur->thread_info);
}

View File

@ -1137,7 +1137,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
} else {
mcps_data_req_ie_list_t ie_list;
memset(&ie_list, 0, sizeof(mcps_data_req_ie_list_t));
cur->mac_api->mcps_data_req_ext(cur->mac_api, &dataReq, &ie_list, NULL, data_priority);
cur->mac_api->mcps_data_req_ext(cur->mac_api, &dataReq, &ie_list, NULL, data_priority, 0);
}
}

View File

@ -70,7 +70,7 @@ static uint8_t current_instance_id = RPL_INSTANCE_ID;
//TAG ID This must be update if NVM_BBR_INFO_LEN or data structure
#define NVM_BBR_INFO_TAG 1
// BSI 2 bytes
#define NVM_BBR_INFO_LEN 2
#define NVM_BBR_INFO_LEN 4
typedef struct bbr_info_nvm_tlv {
uint16_t tag; /**< Unique tag */
@ -97,6 +97,9 @@ static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
static bbr_timezone_configuration_t *bbr_time_config = NULL;
static rpl_dodag_conf_t rpl_conf = {
// Lifetime values
.default_lifetime = 120,
@ -132,41 +135,57 @@ static bbr_info_nvm_tlv_t bbr_info_nvm_tlv = {
};
static uint16_t ws_bbr_fhss_bsi = 0;
static uint16_t ws_bbr_pan_id = 0xffff;
static int8_t ws_bbr_nvm_info_read(bbr_info_nvm_tlv_t *tlv_entry)
static int8_t ws_bbr_info_tlv_read(bbr_info_nvm_tlv_t *tlv_entry, uint16_t *bsi, uint16_t *pan_id)
{
tlv_entry->tag = NVM_BBR_INFO_TAG;
tlv_entry->len = NVM_BBR_INFO_LEN;
int8_t ret_val = ws_pae_nvm_store_tlv_file_read(BBR_INFO_FILE, (nvm_tlv_t *) &bbr_info_nvm_tlv);
if (ret_val < 0 || tlv_entry->tag != NVM_BBR_INFO_TAG || tlv_entry->len != NVM_BBR_INFO_LEN) {
ws_pae_nvm_store_tlv_file_remove(BBR_INFO_FILE);
tlv_entry->len = 0;
if (tlv_entry->tag != NVM_BBR_INFO_TAG || tlv_entry->len != NVM_BBR_INFO_LEN) {
return -1;
}
uint8_t *tlv = (uint8_t *) &tlv_entry->data[0];
*bsi = common_read_16_bit(tlv);
tlv += 2;
*pan_id = common_read_16_bit(tlv);
return 0;
}
static void ws_bbr_nvm_info_write(bbr_info_nvm_tlv_t *tlv_entry)
static void ws_bbr_info_tlv_write(bbr_info_nvm_tlv_t *tlv_entry, uint16_t bsi, uint16_t pan_id)
{
tlv_entry->tag = NVM_BBR_INFO_TAG;
tlv_entry->len = NVM_BBR_INFO_LEN;
ws_pae_nvm_store_tlv_file_write(BBR_INFO_FILE, (nvm_tlv_t *) tlv_entry);
tr_debug("BBR info NVM update");
uint8_t *tlv = (uint8_t *) &tlv_entry->data[0];
tlv = common_write_16_bit(bsi, tlv);
common_write_16_bit(pan_id, tlv);
}
static uint16_t ws_bbr_bsi_read(bbr_info_nvm_tlv_t *tlv_entry)
static int8_t ws_bbr_nvm_info_read(uint16_t *bsi, uint16_t *pan_id)
{
if (tlv_entry->tag != NVM_BBR_INFO_TAG || tlv_entry->len != NVM_BBR_INFO_LEN) {
return 0;
ws_pae_nvm_store_generic_tlv_create((nvm_tlv_t *) &bbr_info_nvm_tlv, NVM_BBR_INFO_TAG, NVM_BBR_INFO_LEN);
if (ws_pae_nvm_store_tlv_file_read(BBR_INFO_FILE, (nvm_tlv_t *) &bbr_info_nvm_tlv) < 0) {
ws_pae_nvm_store_tlv_file_remove(BBR_INFO_FILE);
return -1;
}
return common_read_16_bit(tlv_entry->data + BBR_NVM_BSI_OFFSET);
if (ws_bbr_info_tlv_read(&bbr_info_nvm_tlv, bsi, pan_id) < 0) {
ws_pae_nvm_store_tlv_file_remove(BBR_INFO_FILE);
return -1;
}
return 0;
}
static void ws_bbr_bsi_write(bbr_info_nvm_tlv_t *tlv_entry, uint16_t bsi)
static void ws_bbr_nvm_info_write(uint16_t bsi, uint16_t pan_id)
{
common_write_16_bit(bsi, tlv_entry->data + BBR_NVM_BSI_OFFSET);
ws_bbr_info_tlv_write(&bbr_info_nvm_tlv, bsi, pan_id);
ws_pae_nvm_store_tlv_file_write(BBR_INFO_FILE, (nvm_tlv_t *) &bbr_info_nvm_tlv);
tr_debug("BBR info NVM update");
}
static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version)
@ -488,24 +507,32 @@ static uint8_t *ws_bbr_dhcp_server_dynamic_vendor_data_write(int8_t interfaceId,
// If local time is not available vendor data is not written and data_len is not modified
(void)interfaceId;
uint64_t time_read;
uint64_t time_read = 0;
if (0 != ns_time_system_time_read(&time_read)) {
return ptr;
}
ns_time_system_time_read(&time_read);
if (data_len) {
*data_len += net_vendor_option_current_time_length();
if (time_read) {
*data_len += net_vendor_option_current_time_length();
}
if (bbr_time_config) {
*data_len += net_vendor_option_time_configuration_length();
}
}
if (!ptr) {
return ptr;
}
time_read += 2208988800; // Time starts now from the 0 era instead of First day of Unix (1 Jan 1970)
if (time_read) {
time_read += 2208988800; // Time starts now from the 0 era instead of First day of Unix (1 Jan 1970)
uint32_t era = time_read / (uint64_t)(4294967296);
uint32_t timestamp = time_read - (era * (uint64_t)(4294967296));
ptr = net_vendor_option_current_time_write(ptr, era, timestamp, 0);
uint32_t era = time_read / (uint64_t)(4294967296);
uint32_t timestamp = time_read - (era * (uint64_t)(4294967296));
ptr = net_vendor_option_current_time_write(ptr, era, timestamp, 0);
}
if (bbr_time_config) {
ptr = net_vendor_option_time_configuration_write(ptr, bbr_time_config->timestamp, bbr_time_config->timezone, bbr_time_config->deviation, bbr_time_config->status);
}
return ptr;
}
@ -953,24 +980,21 @@ static void ws_bbr_forwarding_cb(protocol_interface_info_entry_t *interface, buf
}
}
void ws_bbr_init(protocol_interface_info_entry_t *interface)
{
(void) interface;
//Read From NVM
if (ws_bbr_nvm_info_read(&bbr_info_nvm_tlv) < 0) {
if (ws_bbr_nvm_info_read(&ws_bbr_fhss_bsi, &ws_bbr_pan_id) < 0) {
//NVM value not available Randomize Value Here by first time
ws_bbr_fhss_bsi = randLIB_get_16bit();
tr_debug("Randomized init value BSI %u", ws_bbr_fhss_bsi);
} else {
ws_bbr_fhss_bsi = ws_bbr_bsi_read(&bbr_info_nvm_tlv);
tr_debug("Read BSI %u from NVM", ws_bbr_fhss_bsi);
tr_debug("Read PAN ID %u from NVM", ws_bbr_pan_id);
}
interface->if_common_forwarding_out_cb = &ws_bbr_forwarding_cb;
}
uint16_t ws_bbr_bsi_generate(protocol_interface_info_entry_t *interface)
{
(void) interface;
@ -979,11 +1003,16 @@ uint16_t ws_bbr_bsi_generate(protocol_interface_info_entry_t *interface)
//Update value for next round
ws_bbr_fhss_bsi++;
//Store To NVN
ws_bbr_bsi_write(&bbr_info_nvm_tlv, ws_bbr_fhss_bsi);
ws_bbr_nvm_info_write(&bbr_info_nvm_tlv);
ws_bbr_nvm_info_write(ws_bbr_fhss_bsi, ws_bbr_pan_id);
return bsi;
}
uint16_t ws_bbr_pan_id_get(protocol_interface_info_entry_t *interface)
{
(void) interface;
return ws_bbr_pan_id;
}
#endif //HAVE_WS_BORDER_ROUTER
/* Public APIs
@ -1188,7 +1217,7 @@ int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uin
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
ws_bbr_cfg_t cfg;
if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
if (ws_cfg_bbr_get(&cfg) < 0) {
return -1;
}
@ -1202,7 +1231,7 @@ int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uin
cfg.dio_redundancy_constant = dio_redundancy_constant;
}
if (ws_cfg_bbr_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_bbr_set(cur, &cfg, 0) < 0) {
return -2;
}
@ -1224,7 +1253,7 @@ int ws_bbr_rpl_parameters_get(int8_t interface_id, uint8_t *dio_interval_min, ui
}
ws_bbr_cfg_t cfg;
if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
if (ws_cfg_bbr_get(&cfg) < 0) {
return -2;
}
@ -1246,7 +1275,7 @@ int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
ws_bbr_cfg_t cfg;
if (ws_cfg_bbr_get(&cfg, NULL) < 0) {
if (ws_cfg_bbr_get(&cfg) < 0) {
return -2;
}
@ -1260,7 +1289,7 @@ int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min
cfg.dio_redundancy_constant = dio_redundancy_constant;
}
if (ws_cfg_bbr_validate(NULL, &cfg) < 0) {
if (ws_cfg_bbr_validate(&cfg) < 0) {
return -3;
}
@ -1289,8 +1318,7 @@ int ws_bbr_bsi_set(int8_t interface_id, uint16_t new_bsi)
ws_bootstrap_restart_delayed(cur->id);
}
ws_bbr_bsi_write(&bbr_info_nvm_tlv, new_bsi);
ws_bbr_nvm_info_write(&bbr_info_nvm_tlv);
ws_bbr_nvm_info_write(ws_bbr_fhss_bsi, ws_bbr_pan_id);
ws_bbr_fhss_bsi = new_bsi;
return 0;
#else
@ -1299,24 +1327,16 @@ int ws_bbr_bsi_set(int8_t interface_id, uint16_t new_bsi)
#endif
}
int ws_bbr_pan_configuration_set(int8_t interface_id, uint16_t pan_id)
{
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
return -1;
if (ws_bbr_pan_id != pan_id) {
ws_bbr_pan_id = pan_id;
// Store to NVM and restart bootstrap
ws_bbr_nvm_info_write(ws_bbr_fhss_bsi, ws_bbr_pan_id);
ws_bootstrap_restart_delayed(interface_id);
}
cfg.network_pan_id = pan_id;
if (ws_cfg_gen_set(cur, NULL, &cfg, 0) < 0) {
return -2;
}
return 0;
#else
(void) pan_id;
@ -1332,12 +1352,7 @@ int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id)
return -1;
}
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
return -2;
}
*pan_id = cfg.network_pan_id;
*pan_id = ws_bbr_pan_id;
return 0;
#else
@ -1349,21 +1364,10 @@ int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id)
int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id)
{
(void) interface_id;
(void) pan_id;
#ifdef HAVE_WS_BORDER_ROUTER
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
return -1;
}
cfg.network_pan_id = pan_id;
if (ws_cfg_gen_validate(NULL, &cfg) < 0) {
return -2;
}
return 0;
#else
(void) pan_id;
return -1;
#endif
}
@ -1553,3 +1557,32 @@ update_information:
return -1;
#endif
}
int ws_bbr_timezone_configuration_set(int8_t interface_id, bbr_timezone_configuration_t *daylight_saving_time_ptr)
{
#ifdef HAVE_WS_BORDER_ROUTER
(void) interface_id;
if (!daylight_saving_time_ptr) {
// Delete configuration
ns_dyn_mem_free(bbr_time_config);
bbr_time_config = NULL;
return 0;
}
if (!bbr_time_config) {
bbr_time_config = ns_dyn_mem_alloc(sizeof(bbr_timezone_configuration_t));
}
if (!bbr_time_config) {
return -2;
}
*bbr_time_config = *daylight_saving_time_ptr;
return 0;
#else
(void) interface_id;
(void) daylight_saving_time_ptr;
return -1;
#endif
}

View File

@ -38,6 +38,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
bool ws_bbr_backbone_address_get(uint8_t *address);
uint16_t ws_bbr_bsi_generate(protocol_interface_info_entry_t *interface);
uint16_t ws_bbr_pan_id_get(protocol_interface_info_entry_t *interface);
void ws_bbr_init(protocol_interface_info_entry_t *interface);
#else
@ -50,6 +51,7 @@ void ws_bbr_init(protocol_interface_info_entry_t *interface);
#define ws_bbr_ready_to_start(cur) true
#define ws_bbr_backbone_address_get(address) 0
#define ws_bbr_bsi_generate(interface) 0
#define ws_bbr_pan_id_get(interface) 0
#define ws_bbr_init(interface) (void) 0
#endif //HAVE_WS_BORDER_ROUTER

View File

@ -26,17 +26,53 @@ typedef enum {
WS_OPERATION_START, /**< active operation start*/
WS_ROUTING_READY, /**< RPL routing connected to BR*/
WS_FAST_DISCONNECT, /**< Do fast timeout after Border router timeout*/
WS_NORMAL_DISCONNECT /**< Border have been rebooted so Slow poison Process*/
WS_NORMAL_DISCONNECT, /**< Border have been rebooted so Slow poison Process*/
WS_TEST_PROC_TRIGGER /**< Trigger test procedure */
} ws_bootsrap_event_type_e;
/* Bootstrap internal test procedures, these must match to ws_test_proc_t
on net_ws_test_ext.h */
typedef enum {
PROCEDURE_DIS,
PROCEDURE_DIO,
PROCEDURE_DAO,
PROCEDURE_PAS,
PROCEDURE_PA,
PROCEDURE_PCS,
PROCEDURE_PC,
PROCEDURE_EAPOL,
PROCEDURE_RPL,
PROCEDURE_AUTO_ON,
PROCEDURE_AUTO_OFF,
/* Above must match to ws_test_proc_t */
PROCEDURE_PAS_TRICKLE_INCON,
PROCEDURE_PCS_TRICKLE_INCON
} ws_bootsrap_procedure_t;
typedef enum {
WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/
WS_PARENT_HARD_SYNCH, /**< Synch FHSS with latest synch information*/
WS_EAPOL_PARENT_SYNCH, /**< Broadcast synch with EAPOL parent*/
} ws_parent_synch_e;
#ifdef HAVE_WS
//#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_common_defines.h"
struct rpl_instance;
struct llc_neighbour_req;
struct ws_us_ie;
struct ws_bs_ie;
struct ws_neighbor_class_entry;
struct ws_stack_info;
struct ws_neighbour_info;
struct mcps_data_ie_list;
struct mcps_data_ind_s;
extern uint16_t test_pan_version;
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
@ -46,25 +82,10 @@ int ws_bootstrap_restart(int8_t interface_id);
int ws_bootstrap_restart_delayed(int8_t interface_id);
int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_channel_configuration_s rf_configs);
int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
/*State machine transactions*/
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_configuration_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_authentication_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_operation_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_routing_ready(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_disconnect(protocol_interface_info_entry_t *cur, ws_bootsrap_event_type_e event_type);
void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *cur);
void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
@ -99,6 +120,84 @@ int ws_bootstrap_neighbor_info_get(protocol_interface_info_entry_t *cur, struct
void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time);
int ws_bootstrap_test_procedure_trigger(protocol_interface_info_entry_t *cur, ws_bootsrap_procedure_t procedure);
/*
* Functions shared with different bootstrap modes
*/
bool ws_bootstrap_network_name_matches(const struct mcps_data_ie_list *ie_ext, const char *network_name_ptr);
/*State machine transactions*/
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_configuration_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_authentication_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_operation_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_routing_ready(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_disconnect(protocol_interface_info_entry_t *cur, ws_bootsrap_event_type_e event_type);
void ws_bootstrap_test_procedure_trigger_exec(protocol_interface_info_entry_t *cur, ws_bootsrap_procedure_t procedure);
void ws_bootstrap_network_down(protocol_interface_info_entry_t *cur);
// Bootstrap functions
void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur);
// Bootstrap state machine state Functions
bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur);
bool ws_bootstrap_state_authenticate(struct protocol_interface_info_entry *cur);
bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *cur);
bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur);
bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur);
void ws_bootstrap_state_disconnect(protocol_interface_info_entry_t *cur, ws_bootsrap_event_type_e event_type);
void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);
void ws_bootstrap_candidate_list_clean(struct protocol_interface_info_entry *cur, uint8_t pan_max, uint32_t current_time, uint16_t pan_id);
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);
void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur);
parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create);
void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry);
parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_info_entry_t *cur);
void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info, ws_parent_synch_e synch_req);
void ws_bootstrap_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance);
bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, struct llc_neighbour_req *neighbor_buffer, bool request_new);
void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface);
int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr, bool clear_list);
void ws_nud_table_reset(protocol_interface_info_entry_t *cur);
void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]);
void ws_bootstrap_configure_csma_ca_backoffs(protocol_interface_info_entry_t *cur, uint8_t max_backoffs, uint8_t min_be, uint8_t max_be);
void ws_bootstrap_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration);
int8_t ws_bootstrap_fhss_set_defaults(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration);
void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur);
uint16_t ws_bootstrap_randomize_fixed_channel(uint16_t configured_fixed_channel, uint8_t number_of_channels, uint32_t *channel_mask);
int ws_bootstrap_set_domain_rf_config(protocol_interface_info_entry_t *cur);
void ws_bootstrap_configure_max_retries(protocol_interface_info_entry_t *cur, uint8_t max_mac_retries);
void ws_bootstrap_configure_data_request_restart(protocol_interface_info_entry_t *cur, uint8_t cca_failure_restart_max, uint8_t tx_failure_restart_max, uint16_t blacklist_min_ms, uint16_t blacklist_max_ms);
void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry *cur, const fhss_ws_configuration_t *fhss_configuration);
void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur);
void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_ip_stack_reset(protocol_interface_info_entry_t *cur);
void ws_bootstrap_ip_stack_activate(protocol_interface_info_entry_t *cur);
void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur);
void ws_bootstrap_asynch_trickle_stop(protocol_interface_info_entry_t *cur);
void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_network_start(protocol_interface_info_entry_t *cur);
#else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
@ -111,6 +210,7 @@ void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_ent
#define ws_bootstrap_secondary_parent_update(interface)
#define ws_bootstrap_stack_info_get(cur, info_ptr)
#define ws_bootstrap_neighbor_info_get(cur, neighbor_ptr, count)
#define ws_bootstrap_test_procedure_trigger(cur, procedure);
#endif //HAVE_WS

View File

@ -0,0 +1,479 @@
/*
* Copyright (c) 2021, Pelion 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"
#if defined(HAVE_WS) && defined(HAVE_WS_BORDER_ROUTER)
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "net_interface.h"
#include "eventOS_event.h"
#include "randLIB.h"
#include "common_functions.h"
#include "mac_common_defines.h"
#include "sw_mac.h"
#include "ccmLIB.h"
#include "Core/include/ns_monitor.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
#include "ipv6_stack/protocol_ipv6.h"
#include "ipv6_stack/ipv6_routing_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/MAC/mac_ie_lib.h"
#include "MPL/mpl.h"
#include "RPL/rpl_protocol.h"
#include "RPL/rpl_control.h"
#include "RPL/rpl_data.h"
#include "RPL/rpl_policy.h"
#include "Common_Protocols/icmpv6.h"
#include "Common_Protocols/icmpv6_radv.h"
#include "Common_Protocols/ipv6_constants.h"
#include "Common_Protocols/ip.h"
#include "Service_Libs/Trickle/trickle.h"
#include "Service_Libs/fhss/channel_list.h"
#include "Service_Libs/utils/ns_time.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_stats.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "platform/topo_trace.h"
#include "dhcp_service_api.h"
#include "libDHCPv6/libDHCPv6.h"
#include "libDHCPv6/libDHCPv6_vendordata.h"
#include "DHCPv6_client/dhcpv6_client_api.h"
#include "ws_management_api.h"
#include "net_rpl.h"
#include "mac_api.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_eapol_pdu.h"
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
#include "6LoWPAN/ws/ws_eapol_relay.h"
#include "libNET/src/net_dns_internal.h"
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
#define TRACE_GROUP "wsbs"
static int8_t ws_bootstrap_6lbr_fhss_configure(protocol_interface_info_entry_t *cur)
{
// Read configuration of existing FHSS and start using the default values for any network
fhss_ws_configuration_t fhss_configuration = ws_common_get_current_fhss_configuration(cur);
//GET BSI from BBR module
fhss_configuration.bsi = ws_bbr_bsi_generate(cur);
ws_bootstrap_fhss_configure_channel_masks(cur, &fhss_configuration);
// Randomize fixed channels. Only used if channel plan is fixed.
cur->ws_info->cfg->fhss.fhss_uc_fixed_channel = ws_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask);
cur->ws_info->cfg->fhss.fhss_bc_fixed_channel = ws_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask);
ws_bootstrap_fhss_set_defaults(cur, &fhss_configuration);
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);
ws_bootstrap_llc_hopping_update(cur, &fhss_configuration);
return 0;
}
static int8_t ws_bootstrap_6lbr_backbone_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address)
{
(void) interface_ptr;
(void) address;
if (ws_bbr_backbone_address_get(address)) {
return 0;
}
return -1;
}
static void ws_bootstrap_6lbr_eapol_congestion_init(protocol_interface_info_entry_t *cur)
{
random_early_detection_free(cur->llc_random_early_detection);
cur->llc_random_early_detection = NULL;
if (cur->llc_random_early_detection == NULL) {
cur->llc_random_early_detection = random_early_detection_create(
cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_min,
cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_max,
100, RED_AVERAGE_WEIGHT_EIGHTH);
}
random_early_detection_free(cur->llc_eapol_random_early_detection);
cur->llc_eapol_random_early_detection = NULL;
if (cur->llc_eapol_random_early_detection == NULL) {
cur->llc_eapol_random_early_detection = random_early_detection_create(
cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_min,
cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_max,
100, RED_AVERAGE_WEIGHT_EIGHTH);
}
}
static void ws_bootstrap_6lbr_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)
{
ws_bs_ie_t ws_bs_ie;
ws_bt_ie_t ws_bt_ie;
llc_neighbour_req_t neighbor_info;
if (data->SrcPANId != cur->ws_info->network_pan_id) {
return;
}
if (!ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt_ie)) {
tr_warn("BT-IE");
return;
}
if (!ws_wp_nested_bs_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_bs_ie)) {
// Corrupted
tr_error("No broadcast schedule");
return;
}
//If we are border router or learned configuration we only update already learned neighbours.
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
//Update Neighbor Broadcast and Unicast Parameters
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
}
}
static void ws_bootstrap_6lbr_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)
{
llc_neighbour_req_t neighbor_info;
if (data->SrcPANId != cur->ws_info->network_pan_id) {
return;
}
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
}
}
void ws_bootstrap_6lbr_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)
{
// Store weakest heard packet RSSI
if (cur->ws_info->weakest_received_rssi > data->signal_dbm) {
cur->ws_info->weakest_received_rssi = data->signal_dbm;
}
if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) {
// Not from long address
return;
}
ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1);
//Validate network name
switch (message_type) {
case WS_FT_PAN_ADVERT:
case WS_FT_PAN_ADVERT_SOL:
case WS_FT_PAN_CONF_SOL:
//Check Network Name
if (!ws_bootstrap_network_name_matches(ie_ext, cur->ws_info->cfg->gen.network_name)) {
// Not in our network
return;
}
break;
case WS_FT_PAN_CONF:
break;
default:
return;
}
//UTT-IE and US-IE are mandatory for all Asynch Messages
ws_utt_ie_t ws_utt;
if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) {
// Corrupted
return;
}
ws_us_ie_t ws_us;
if (!ws_wp_nested_us_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_us)) {
// Corrupted
return;
}
if (!ws_bootstrap_validate_channel_plan(&ws_us, cur) ||
!ws_bootstrap_validate_channel_function(&ws_us, NULL)) {
return;
}
//Handle Message's
switch (message_type) {
case WS_FT_PAN_ADVERT:
// Analyse Advertisement
ws_stats_update(cur, STATS_WS_ASYNCH_RX_PA, 1);
tr_info("received ADVERT Src:%s panid:%x rssi:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm);
// Border routers do not do any analysing on the Advertisements heard from others
// in future if we need PANID conflict detection we could use this
break;
case WS_FT_PAN_ADVERT_SOL:
ws_stats_update(cur, STATS_WS_ASYNCH_RX_PAS, 1);
tr_info("received ADVERT SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery);
break;
case WS_FT_PAN_CONF:
ws_stats_update(cur, STATS_WS_ASYNCH_RX_PC, 1);
tr_info("received CONFIG Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
ws_bootstrap_6lbr_pan_config_analyse(cur, data, ie_ext, &ws_utt, &ws_us);
break;
case WS_FT_PAN_CONF_SOL:
ws_stats_update(cur, STATS_WS_ASYNCH_RX_PCS, 1);
tr_info("received CONFIG SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
ws_bootstrap_6lbr_pan_config_solicit_analyse(cur, data, &ws_utt, &ws_us);
default:
// Unknown message do not process
break;
}
}
void ws_bootstrap_6lbr_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message)
{
ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1);
if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
if (asynch_message == WS_FT_PAN_CONF && interface->ws_info->pending_key_index_info.state == PENDING_KEY_INDEX_ACTIVATE) {
interface->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
tr_info("Activate new default key %u", interface->ws_info->pending_key_index_info.index + 1);
mac_helper_security_auto_request_key_index_set(interface, interface->ws_info->pending_key_index_info.index, interface->ws_info->pending_key_index_info.index + 1);
}
}
}
void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event)
{
ws_bootsrap_event_type_e event_type;
event_type = (ws_bootsrap_event_type_e)event->event_type;
switch (event_type) {
case WS_INIT_EVENT:
tr_debug("tasklet init");
break;
case WS_DISCOVERY_START:
tr_info("Discovery start");
protocol_mac_reset(cur);
ws_llc_reset(cur);
lowpan_adaptation_interface_reset(cur->id);
//Clear Pending Key Index State
cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
cur->mac_parameters->mac_default_key_index = 0;
ipv6_destination_cache_clean(cur->id);
// Clear parent blacklist
blacklist_clear();
// All trickle timers stopped to allow entry from any state
ws_bootstrap_asynch_trickle_stop(cur);
//Init Packet congestion
ws_bootstrap_packet_congestion_init(cur);
tr_info("Border router start network");
if (!ws_bbr_ready_to_start(cur)) {
// Wi-SUN not started yet we wait for Border router permission
ws_bootstrap_state_change(cur, ER_WAIT_RESTART);
cur->nwk_nd_re_scan_count = randLIB_get_random_in_range(40, 100);
return;
}
// Clear Old information from stack
cur->ws_info->network_pan_id = 0xffff;
cur->ws_info->pan_information.pan_version_set = false;
ws_nud_table_reset(cur);
ws_bootstrap_neighbor_list_clean(cur);
ws_bootstrap_ip_stack_reset(cur);
ws_pae_controller_auth_init(cur);
uint16_t pan_id = ws_bbr_pan_id_get(cur);
if (pan_id != 0xffff) {
cur->ws_info->network_pan_id = pan_id;
} else {
if (cur->ws_info->network_pan_id == 0xffff) {
cur->ws_info->network_pan_id = randLIB_get_random_in_range(0, 0xfffd);
}
}
if (!cur->ws_info->pan_information.pan_version_set) {
cur->ws_info->pan_information.pan_version = randLIB_get_random_in_range(0, 0xffff);
cur->ws_info->pan_information.pan_version_set = true;
}
cur->ws_info->pan_information.pan_size = 0;
cur->ws_info->pan_information.routing_cost = 0;
cur->ws_info->pan_information.rpl_routing_method = true;
cur->ws_info->pan_information.use_parent_bs = true;
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
// initialize for FAN 1.1 defaults
if (ws_version_1_1(cur)) {
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_1;
#ifdef HAVE_WS_VERSION_1_1
if (!cur->ws_info->lfngtk.lfn_version_learned) {
//Randomize LFN version
cur->ws_info->lfngtk.lfn_version = randLIB_get_random_in_range(0, 0xffff);
cur->ws_info->lfngtk.lfn_version_learned = true;
}
#endif
}
uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur);
ws_llc_set_gtkhash(cur, gtkhash);
ws_bbr_pan_version_increase(cur);
// Set default parameters for FHSS when starting a discovery
ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule);
ws_bootstrap_6lbr_fhss_configure(cur);
ws_bootstrap_set_domain_rf_config(cur);
ws_bootstrap_fhss_activate(cur);
ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0);
uint8_t ll_addr[16];
addr_interface_get_ll_address(cur, ll_addr, 1);
//SET EAPOL authenticator EUI64
ws_pae_controller_border_router_addr_write(cur, cur->mac);
// Set EAPOL relay to port 10255 and authenticator relay to 10253 (and to own ll address)
ws_eapol_relay_start(cur, BR_EAPOL_RELAY_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT);
// Set authenticator relay to port 10253 and PAE to 10254 (and to own ll address)
ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT);
// Set PAN ID and network name to controller
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name);
// Set backbone IP address get callback
ws_pae_controller_auth_cb_register(cur, ws_bootstrap_6lbr_backbone_ip_addr_get);
// Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address)
ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT);
// Initialize eapol congestion tracking
ws_bootstrap_6lbr_eapol_congestion_init(cur);
// Set retry configuration for bootstrap ready state
ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES);
// Set TX failure request restart configuration
ws_bootstrap_configure_data_request_restart(cur, WS_CCA_REQUEST_RESTART_MAX, WS_TX_REQUEST_RESTART_MAX, WS_REQUEST_RESTART_BLACKLIST_MIN, WS_REQUEST_RESTART_BLACKLIST_MAX);
// Set CSMA-CA backoff configuration
ws_bootstrap_configure_csma_ca_backoffs(cur, WS_MAX_CSMA_BACKOFFS, WS_MAC_MIN_BE, WS_MAC_MAX_BE);
ws_bootstrap_event_operation_start(cur);
break;
case WS_CONFIGURATION_START:
tr_info("6LBR Configuration start");
break;
case WS_OPERATION_START:
tr_info("operation start");
// Advertisements stopped during the RPL scan
ws_bootstrap_asynch_trickle_stop(cur);
// Activate RPL
// Activate IPv6 stack
ws_bootstrap_ip_stack_activate(cur);
ws_bootstrap_rpl_activate(cur);
ws_bootstrap_network_start(cur);
// Wait for RPL start
ws_bootstrap_event_routing_ready(cur);
break;
case WS_ROUTING_READY:
tr_info("Routing ready");
// stopped all to make sure we can enter here from any state
ws_bootstrap_asynch_trickle_stop(cur);
// Indicate PAE controller that bootstrap is ready
ws_pae_controller_bootstrap_done(cur);
ws_bootstrap_advertise_start(cur);
ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE);
break;
case WS_FAST_DISCONNECT:
ws_bootstrap_state_disconnect(cur, WS_FAST_DISCONNECT);
break;
case WS_NORMAL_DISCONNECT:
ws_bootstrap_state_disconnect(cur, WS_NORMAL_DISCONNECT);
break;
case WS_TEST_PROC_TRIGGER:
ws_bootstrap_test_procedure_trigger_exec(cur, (ws_bootsrap_procedure_t) event->data_ptr);
break;
default:
tr_err("Invalid event received");
break;
}
}
void ws_bootstrap_6lbr_state_machine(protocol_interface_info_entry_t *cur)
{
switch (cur->nwk_bootstrap_state) {
case ER_WAIT_RESTART:
tr_debug("WS SM:Wait for startup");
ws_bootstrap_event_discovery_start(cur);
break;
case ER_ACTIVE_SCAN:
tr_debug("WS SM:Active Scan");
break;
case ER_SCAN:
tr_debug("WS SM:configuration Scan");
break;
case ER_PANA_AUTH:
tr_info("authentication start");
break;
case ER_RPL_SCAN:
tr_debug("WS SM:Wait RPL to contact DODAG root");
break;
case ER_BOOTSRAP_DONE:
tr_info("WS SM:Bootstrap Done");
// Bootstrap_done event to application
nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
break;
case ER_RPL_NETWORK_LEAVING:
tr_debug("WS SM:RPL Leaving ready trigger discovery");
ws_bootstrap_event_discovery_start(cur);
break;
default:
tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state);
}
}
void ws_bootstrap_6lbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
{
(void)cur;
(void)seconds;
}
#endif //HAVE_WS_BORDER_ROUTER && HAVE_WS

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef WS_BOOTSTRAP_6LBR_H_
#define WS_BOOTSTRAP_6LBR_H_
#if defined(HAVE_WS) && defined(HAVE_WS_BORDER_ROUTER)
void ws_bootstrap_6lbr_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);
void ws_bootstrap_6lbr_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message);
void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event);
void ws_bootstrap_6lbr_state_machine(protocol_interface_info_entry_t *cur);
void ws_bootstrap_6lbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
#define wisun_mode_border_router(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER)
#else
#define ws_bootstrap_6lbr_asynch_ind(cur, data, ie_ext, message_type) ((void) 0)
#define ws_bootstrap_6lbr_asynch_confirm(interface, asynch_message) ((void) 0)
#define ws_bootstrap_6lbr_event_handler(cur, event) ((void) 0)
#define ws_bootstrap_6lbr_state_machine(cur) ((void) 0)
#define ws_bootstrap_6lbr_seconds_timer(cur, seconds) ((void) 0)
#define wisun_mode_border_router(cur) (false)
#endif //HAVE_WS
#endif /* WS_BOOTSTRAP_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef WS_BOOTSTRAP_FFN_H_
#define WS_BOOTSTRAP_FFN_H_
#if defined(HAVE_WS) && defined(HAVE_WS_ROUTER)
void ws_bootstrap_ffn_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);
void ws_bootstrap_ffn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message);
void ws_bootstrap_ffn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event);
void ws_bootstrap_ffn_state_machine(protocol_interface_info_entry_t *cur);
void ws_bootstrap_ffn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
#define wisun_mode_router(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER)
#else
#define ws_bootstrap_ffn_asynch_ind(cur, data, ie_ext, message_type) ((void) 0)
#define ws_bootstrap_ffn_asynch_confirm(interface, asynch_message) ((void) 0)
#define ws_bootstrap_ffn_event_handler(cur, event) ((void) 0)
#define ws_bootstrap_ffn_state_machine(cur) ((void) 0)
#define ws_bootstrap_ffn_seconds_timer(cur, seconds) ((void) 0)
#define wisun_mode_router(cur) (false)
#endif //HAVE_WS
#endif /* WS_BOOTSTRAP_H_ */

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2021, Pelion 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"
#if defined(HAVE_WS) && defined(HAVE_WS_HOST)
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "net_interface.h"
#include "eventOS_event.h"
#include "randLIB.h"
#include "common_functions.h"
#include "mac_common_defines.h"
#include "sw_mac.h"
#include "ccmLIB.h"
#include "Core/include/ns_monitor.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
#include "ipv6_stack/protocol_ipv6.h"
#include "ipv6_stack/ipv6_routing_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/MAC/mac_ie_lib.h"
#include "MPL/mpl.h"
#include "RPL/rpl_protocol.h"
#include "RPL/rpl_control.h"
#include "RPL/rpl_data.h"
#include "RPL/rpl_policy.h"
#include "Common_Protocols/icmpv6.h"
#include "Common_Protocols/icmpv6_radv.h"
#include "Common_Protocols/ipv6_constants.h"
#include "Common_Protocols/ip.h"
#include "Service_Libs/Trickle/trickle.h"
#include "Service_Libs/fhss/channel_list.h"
#include "Service_Libs/utils/ns_time.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_stats.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "platform/topo_trace.h"
#include "dhcp_service_api.h"
#include "libDHCPv6/libDHCPv6.h"
#include "libDHCPv6/libDHCPv6_vendordata.h"
#include "DHCPv6_client/dhcpv6_client_api.h"
#include "ws_management_api.h"
#include "net_rpl.h"
#include "mac_api.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_eapol_pdu.h"
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
#include "6LoWPAN/ws/ws_eapol_relay.h"
#include "libNET/src/net_dns_internal.h"
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
#define TRACE_GROUP "wsbs"
void ws_bootstrap_lfn_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)
{
(void)ie_ext;
// Store weakest heard packet RSSI
if (cur->ws_info->weakest_received_rssi > data->signal_dbm) {
cur->ws_info->weakest_received_rssi = data->signal_dbm;
}
if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) {
// Not from long address
return;
}
ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1);
tr_warn("Wi-SUN LFN Mode received message id: %x", message_type);
}
void ws_bootstrap_lfn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message)
{
(void)asynch_message;
ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1);
}
void ws_bootstrap_lfn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event)
{
(void)cur;
ws_bootsrap_event_type_e event_type;
event_type = (ws_bootsrap_event_type_e)event->event_type;
switch (event_type) {
case WS_INIT_EVENT:
tr_debug("tasklet init");
break;
/* case WS_DISCOVERY_START:
case WS_CONFIGURATION_START:
case WS_OPERATION_START:
case WS_ROUTING_READY:
case WS_FAST_DISCONNECT:
case WS_NORMAL_DISCONNECT:
*/
default:
tr_err("Invalid event received");
break;
}
}
void ws_bootstrap_lfn_state_machine(protocol_interface_info_entry_t *cur)
{
switch (cur->nwk_bootstrap_state) {
case ER_WAIT_RESTART:
tr_debug("WS SM:Wait for startup");
break;
case ER_ACTIVE_SCAN:
tr_debug("WS SM:Active Scan");
break;
case ER_SCAN:
tr_debug("WS SM:configuration Scan");
break;
case ER_PANA_AUTH:
tr_info("authentication start");
// Advertisements stopped during the EAPOL
break;
case ER_RPL_SCAN:
tr_debug("WS SM:Wait RPL to contact DODAG root");
break;
case ER_BOOTSRAP_DONE:
tr_info("WS SM:Bootstrap Done");
// Bootstrap_done event to application
break;
case ER_RPL_NETWORK_LEAVING:
tr_debug("WS SM:RPL Leaving ready trigger discovery");
break;
default:
tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state);
}
}
void ws_bootstrap_lfn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
{
(void)cur;
(void)seconds;
}
#endif //HAVE_WS_BORDER_ROUTER && HAVE_WS

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef WS_BOOTSTRAP_LFN_H_
#define WS_BOOTSTRAP_LFN_H_
#if defined(HAVE_WS) && defined(HAVE_WS_HOST)
void ws_bootstrap_lfn_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);
void ws_bootstrap_lfn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message);
void ws_bootstrap_lfn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event);
void ws_bootstrap_lfn_state_machine(protocol_interface_info_entry_t *cur);
void ws_bootstrap_lfn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
#define wisun_mode_host(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST)
#else
#define ws_bootstrap_ffn_asynch_ind(cur, data, ie_ext, message_type) ((void) 0)
#define ws_bootstrap_ffn_asynch_confirm(interface, asynch_message) ((void) 0)
#define ws_bootstrap_ffn_event_handler(cur, event) ((void) 0)
#define ws_bootstrap_lfn_state_machine(cur) ((void) 0)
#define ws_bootstrap_lfn_seconds_timer(cur, seconds) ((void) 0)
#define wisun_mode_host(cur) (false)
#endif //HAVE_WS
#endif /* WS_BOOTSTRAP_H_ */

View File

@ -39,10 +39,8 @@
#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 CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE 0x01
#define CFG_FLAGS_BOOTSTRAP_SET_VALUES 0x02
#define TRICKLE_IMIN_60_SECS 60
#define TRICKLE_IMIN_30_SECS 30
@ -58,8 +56,8 @@ typedef struct ws_cfg_nw_size_s {
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 int8_t (*ws_cfg_validate)(void *new_cfg);
typedef int8_t (*ws_cfg_set)(protocol_interface_info_entry_t *cur, void *new_cfg, uint8_t flags);
typedef struct {
ws_cfg_default_set default_set;
@ -104,9 +102,6 @@ const cfg_devices_in_config_t devices_by_datarate[] = {
{ 2, 20, 50, 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);
@ -146,55 +141,6 @@ static const ws_cfg_cb_t cfg_cb[] = {
// 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)
{
@ -236,19 +182,15 @@ static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg)
{
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;
*cfg = ws_cfg.gen;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
int8_t ws_cfg_network_size_validate(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);
ws_gen_cfg_t *cfg = &ws_cfg.gen;
if (cfg->network_size != new_cfg->network_size) {
return CFG_SETTINGS_CHANGED;
}
@ -258,29 +200,24 @@ int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
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)
int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, 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;
}
(void) flags;
uint8_t old_network_size = cfg->network_size;
// If network size configuration has not changed, returns
if (cfg->network_size == new_cfg->network_size) {
if (ws_cfg_network_size_validate(new_cfg) != CFG_SETTINGS_CHANGED) {
return CFG_SETTINGS_OK;
}
ws_gen_cfg_t *cfg = &ws_cfg.gen;
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_gen_get(&nw_size_cfg.gen);
ws_cfg_timing_get(&nw_size_cfg.timing);
ws_cfg_bbr_get(&nw_size_cfg.bbr);
ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot);
ws_cfg_mpl_get(&nw_size_cfg.mpl);
ws_cfg_network_size_config_set_size set_function = NULL;
@ -301,46 +238,13 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
set_function(&nw_size_cfg);
}
uint8_t cfg_network_size = cfg->network_size;
/* Sets values if changed */
ws_cfg_gen_set(cur, &nw_size_cfg.gen, 0x00);
ws_cfg_timing_set(cur, &nw_size_cfg.timing, 0x00);
ws_cfg_bbr_set(cur, &nw_size_cfg.bbr, 0x00);
ws_cfg_sec_prot_set(cur, &nw_size_cfg.sec_prot, 0x00);
ws_cfg_mpl_set(cur, &nw_size_cfg.mpl, 0x00);
/* 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;
}
@ -349,7 +253,7 @@ static uint8_t ws_cfg_config_get_by_size(protocol_interface_info_entry_t *cur, u
(void)cur;
ws_phy_cfg_t phy_cfg;
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
if (ws_cfg_phy_get(&phy_cfg) < 0) {
return CONFIG_SMALL;
}
uint32_t data_rate = ws_common_datarate_get_from_phy_mode(phy_cfg.phy_mode_id, phy_cfg.operating_mode);
@ -377,50 +281,6 @@ static uint8_t ws_cfg_config_get_by_size(protocol_interface_info_entry_t *cur, u
return CONFIG_XLARGE;
}
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));
}
network_size = network_size / 100;
if (network_size == 0) {
network_size = 1;
}
if (ws_cfg_config_get_by_size(cur, network_size) == CONFIG_SMALL) {
ws_cfg_network_size_config_set_small(&new_nw_size_cfg);
} else if (ws_cfg_config_get_by_size(cur, network_size) == CONFIG_MEDIUM) {
ws_cfg_network_size_config_set_medium(&new_nw_size_cfg);
} else if (ws_cfg_config_get_by_size(cur, network_size) == CONFIG_LARGE) {
ws_cfg_network_size_config_set_large(&new_nw_size_cfg);
} else {
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
@ -430,7 +290,7 @@ cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_
(void)cur;
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
if (ws_cfg_gen_get(&cfg) < 0) {
return CONFIG_SMALL;
}
@ -563,7 +423,6 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
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)
@ -653,25 +512,21 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg)
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)
int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg)
{
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;
*cfg = ws_cfg.gen;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
int8_t ws_cfg_gen_validate(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);
ws_gen_cfg_t *cfg = &ws_cfg.gen;
if (strlen(new_cfg->network_name) > 32) {
return CFG_SETTINGS_ERROR_GEN_CONF;
@ -679,7 +534,6 @@ int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
// 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;
@ -688,30 +542,29 @@ int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg)
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)
int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, 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) {
int8_t ret = ws_cfg_gen_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_gen_cfg_t *cfg = &ws_cfg.gen;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_gen_cfg_t), "gen");
cfg->network_size = new_cfg->network_size;
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)) {
if (cur && !(flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
ws_bootstrap_restart_delayed(cur->id);
}
@ -730,18 +583,15 @@ int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg)
{
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;
*cfg = ws_cfg.phy;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg)
int8_t ws_cfg_phy_validate(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);
ws_phy_cfg_t *cfg = &ws_cfg.phy;
// Regulator domain, operating mode or class has changed
if (cfg->regulatory_domain != new_cfg->regulatory_domain ||
@ -770,15 +620,14 @@ int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg)
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)
int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, 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) {
int8_t ret = ws_cfg_phy_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
// Check settings and configure interface
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
// 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;
@ -809,15 +658,17 @@ int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, w
}
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_phy_cfg_t *cfg = &ws_cfg.phy;
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)) {
if (cur && !(flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
ws_bootstrap_restart_delayed(cur->id);
}
@ -837,18 +688,15 @@ int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg)
{
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;
*cfg = ws_cfg.timing;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg)
int8_t ws_cfg_timing_validate(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);
ws_timing_cfg_t *cfg = &ws_cfg.timing;
if (cfg->disc_trickle_imin != new_cfg->disc_trickle_imin ||
cfg->disc_trickle_imax != new_cfg->disc_trickle_imax ||
@ -876,15 +724,16 @@ int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg)
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)
int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, 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) {
(void) flags;
int8_t ret = ws_cfg_timing_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
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;
@ -892,10 +741,12 @@ int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *
ws_pae_controller_configure(cur, NULL, NULL, new_cfg);
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_timing_cfg_t *cfg = &ws_cfg.timing;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_timing_cfg_t), "timing");
*cfg = *new_cfg;
@ -922,19 +773,15 @@ static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg)
{
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;
*cfg = ws_cfg.bbr;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg)
int8_t ws_cfg_bbr_validate(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);
ws_bbr_cfg_t *cfg = &ws_cfg.bbr;
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 ||
@ -948,18 +795,16 @@ int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg)
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)
int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, 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) {
int8_t ret = ws_cfg_bbr_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (!(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
// 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,
@ -967,10 +812,12 @@ int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, w
ws_bbr_dhcp_address_lifetime_set(cur, new_cfg->dhcp_address_lifetime);
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_bbr_cfg_t *cfg = &ws_cfg.bbr;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_bbr_cfg_t), "rpl");
*cfg = *new_cfg;
@ -990,18 +837,15 @@ static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg)
{
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;
*cfg = ws_cfg.mpl;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg)
int8_t ws_cfg_mpl_validate(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);
ws_mpl_cfg_t *cfg = &ws_cfg.mpl;
// MPL configuration has changed
if (cfg->mpl_trickle_imin != new_cfg->mpl_trickle_imin ||
@ -1015,9 +859,9 @@ int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg)
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)
int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *new_cfg, uint8_t flags)
{
uint8_t cfg_flags;
(void) 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) {
@ -1033,12 +877,12 @@ int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, w
}
}
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) {
int8_t ret = ws_cfg_mpl_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
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;
@ -1051,10 +895,12 @@ int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, w
}
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_mpl_cfg_t *cfg = &ws_cfg.mpl;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_mpl_cfg_t), "mpl");
*cfg = *new_cfg;
@ -1080,18 +926,15 @@ int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg)
{
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;
*cfg = ws_cfg.fhss;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg)
int8_t ws_cfg_fhss_validate(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);
ws_fhss_cfg_t *cfg = &ws_cfg.fhss;
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 ||
@ -1123,20 +966,21 @@ int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg)
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)
int8_t ws_cfg_fhss_set(protocol_interface_info_entry_t *cur, 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) {
int8_t ret = ws_cfg_fhss_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_fhss_cfg_t *cfg = &ws_cfg.fhss;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_fhss_cfg_t), "fhss");
*cfg = *new_cfg;
@ -1159,7 +1003,7 @@ int8_t ws_cfg_fhss_set(protocol_interface_info_entry_t *cur, ws_fhss_cfg_t *cfg,
cfg->fhss_bc_fixed_channel = 0xffff;
}
if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
if (cur && !(flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) {
ws_bootstrap_restart_delayed(cur->id);
}
@ -1181,18 +1025,15 @@ static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg)
{
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;
*cfg = ws_cfg.sec_timer;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg)
int8_t ws_cfg_sec_timer_validate(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);
ws_sec_timer_cfg_t *cfg = &ws_cfg.sec_timer;
if (cfg->gtk_expire_offset != new_cfg->gtk_expire_offset ||
cfg->pmk_lifetime != new_cfg->pmk_lifetime ||
@ -1210,22 +1051,25 @@ int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *ne
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)
int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, 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) {
(void) flags;
int8_t ret = ws_cfg_sec_timer_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
ws_pae_controller_configure(cur, new_cfg, NULL, NULL);
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_sec_timer_cfg_t *cfg = &ws_cfg.sec_timer;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_timer_cfg_t), "sec_timer");
*cfg = *new_cfg;
@ -1249,18 +1093,15 @@ static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg)
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags)
int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg)
{
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;
*cfg = ws_cfg.sec_prot;
return CFG_SETTINGS_OK;
}
int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg)
int8_t ws_cfg_sec_prot_validate(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);
ws_sec_prot_cfg_t *cfg = &ws_cfg.sec_prot;
if (cfg->sec_prot_trickle_imin != new_cfg->sec_prot_trickle_imin ||
cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax ||
@ -1279,22 +1120,25 @@ int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_c
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)
int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, 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) {
(void) flags;
int8_t ret = ws_cfg_sec_prot_validate(new_cfg);
if (!(flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) && ret != CFG_SETTINGS_CHANGED) {
return ret;
}
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
if (cur) {
ws_pae_controller_configure(cur, NULL, new_cfg, NULL);
}
if (cfg == new_cfg) {
if (flags & CFG_FLAGS_BOOTSTRAP_SET_VALUES) {
return CFG_SETTINGS_OK;
}
ws_sec_prot_cfg_t *cfg = &ws_cfg.sec_prot;
ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_prot_cfg_t), "sec_prot");
*cfg = *new_cfg;
@ -1324,11 +1168,9 @@ int8_t ws_cfg_settings_default_set(void)
// 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) {
0x00) < 0) {
tr_info("FATAL CONFIG FAILURE");
ret_value = CFG_SETTINGS_OTHER_ERROR;
}
@ -1345,13 +1187,11 @@ int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur)
// 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) {
CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE | CFG_FLAGS_BOOTSTRAP_SET_VALUES) < 0) {
tr_info("FATAL CONFIG FAILURE");
ret_value = CFG_SETTINGS_OTHER_ERROR;
}
@ -1361,30 +1201,19 @@ int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur)
return ret_value;
}
int8_t ws_cfg_settings_get(protocol_interface_info_entry_t *cur, ws_cfg_t *cfg)
int8_t ws_cfg_settings_get(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)
int8_t ws_cfg_settings_validate(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
@ -1406,7 +1235,6 @@ int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_c
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) {
@ -1425,12 +1253,10 @@ int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_c
// 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) {
((uint8_t *)new_cfg) + cfg_cb[index].setting_offset, 0x00) < 0) {
tr_info("FATAL CONFIG FAILURE");
ret_value = CFG_SETTINGS_OTHER_ERROR;
}

View File

@ -26,7 +26,6 @@ typedef struct ws_gen_cfg_s {
default values */
uint8_t network_size; /**< Network size selection; default medium (= 8) */
char network_name[33]; /**< Network name; max 32 octets + terminating 0 */
uint16_t network_pan_id; /**< PAN identifier; PAN_ID; default 0xffff */
uint16_t rpl_parent_candidate_max; /**< RPL parent candidate maximum value; default 5 */
uint16_t rpl_selected_parent_max; /**< RPL selected parent maximum value; default 2 */
} ws_gen_cfg_t;
@ -163,48 +162,50 @@ typedef enum {
int8_t ws_cfg_settings_init(void);
int8_t ws_cfg_settings_default_set(void);
int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur);
int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size);
int8_t ws_cfg_settings_get(ws_cfg_t *cfg);
int8_t ws_cfg_settings_validate(struct ws_cfg_s *new_cfg);
int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_cfg);
cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur);
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_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);
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg);
int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *new_cfg);
int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg);
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);
int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg);
int8_t ws_cfg_gen_validate(ws_gen_cfg_t *new_cfg);
int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg);
int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg);
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);
int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg);
int8_t ws_cfg_phy_validate(ws_phy_cfg_t *new_cfg);
int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg);
int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg);
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);
int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg);
int8_t ws_cfg_timing_validate(ws_timing_cfg_t *new_cfg);
int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg);
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);
int8_t ws_cfg_bbr_get(ws_bbr_cfg_t *cfg);
int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *new_cfg);
int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg);
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);
int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg);
int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *new_cfg);
int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg);
int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg);
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);
int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg);
int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *new_cfg);
int8_t ws_cfg_fhss_set(protocol_interface_info_entry_t *cur, ws_fhss_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg);
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);
int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg);
int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *new_cfg);
int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_cfg_t *new_cfg, uint8_t flags);
int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags);
int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg);
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);
int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg);
int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *new_cfg);
int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg_t *new_cfg, uint8_t flags);
uint32_t ws_cfg_neighbour_temporary_lifetime_get(void);
void ws_cfg_neighbour_temporary_lifetime_set(uint32_t lifetime);

View File

@ -20,21 +20,28 @@
#include "ns_types.h"
#include "ns_trace.h"
#include "randLIB.h"
#include "common_functions.h"
#include <ns_list.h>
#include <nsdynmemLIB.h>
#include "Common_Protocols/icmpv6.h"
#include "mac_common_defines.h"
#include "net_interface.h"
#include "eventOS_event.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_bootstrap_6lbr.h"
#include "6LoWPAN/ws/ws_bootstrap_ffn.h"
#include "6LoWPAN/ws/ws_bootstrap_lfn.h"
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/ws/ws_stats.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_phy.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "Service_Libs/blacklist/blacklist.h"
@ -58,13 +65,13 @@ static int8_t ws_disable_channels_in_range(uint32_t *channel_mask, uint16_t numb
{
for (uint16_t i = 0; i < number_of_channels; i++) {
if (i >= range_start && i <= range_stop) {
channel_mask[0 + (i / 32)] &= ~(1 << (i % 32));
channel_mask[i / 32] &= ~(1U << (i % 32));
}
}
return 0;
}
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id)
int8_t ws_common_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id)
{
// Clear channel mask
for (uint8_t i = 0; i < 8; i++) {
@ -72,7 +79,7 @@ int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_chann
}
// Enable all channels
for (uint16_t i = 0; i < number_of_channels; i++) {
channel_mask[0 + (i / 32)] |= (1 << (i % 32));
channel_mask[i / 32] |= 1U << (i % 32);
}
// Disable unsupported channels per regional frequency bands
if (regulatory_domain == REG_DOMAIN_BZ) {
@ -93,121 +100,38 @@ int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_chann
ws_disable_channels_in_range(channel_mask, number_of_channels, 3, 10);
}
}
} else if (regulatory_domain == REG_DOMAIN_EU) {
if (channel_plan_id == 32) {
ws_disable_channels_in_range(channel_mask, number_of_channels, 55, 56);
ws_disable_channels_in_range(channel_mask, number_of_channels, 61, 63);
ws_disable_channels_in_range(channel_mask, number_of_channels, 65, 66);
} else if (channel_plan_id == 33) {
ws_disable_channels_in_range(channel_mask, number_of_channels, 27, 28);
ws_disable_channels_in_range(channel_mask, number_of_channels, 30, 33);
} else if (channel_plan_id == 36) {
ws_disable_channels_in_range(channel_mask, number_of_channels, 55, 56);
ws_disable_channels_in_range(channel_mask, number_of_channels, 61, 63);
ws_disable_channels_in_range(channel_mask, number_of_channels, 65, 66);
} else if (channel_plan_id == 37) {
ws_disable_channels_in_range(channel_mask, number_of_channels, 27, 28);
ws_disable_channels_in_range(channel_mask, number_of_channels, 30, 33);
}
}
return 0;
}
uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels)
uint16_t ws_common_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels)
{
uint16_t active_channels = 0;
// Set channel maks outside excluded channels
for (uint16_t i = 0; i < number_of_channels; i++) {
if (channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
if (channel_mask[i / 32] & (1U << (i % 32))) {
active_channels++;
}
}
return active_channels;
}
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
{
if (CHANNEL_SPACING_100 == channel_spacing) {
return 100000;
} else if (CHANNEL_SPACING_200 == channel_spacing) {
return 200000;
} else if (CHANNEL_SPACING_250 == channel_spacing) {
return 250000;
} else if (CHANNEL_SPACING_400 == channel_spacing) {
return 400000;
} else if (CHANNEL_SPACING_600 == channel_spacing) {
return 600000;
} else if (CHANNEL_SPACING_800 == channel_spacing) {
return 800000;
} else if (CHANNEL_SPACING_1200 == channel_spacing) {
return 1200000;
}
return 0;
}
uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode)
{
if ((OPERATING_MODE_1a == operating_mode) || (OPERATING_MODE_1b == operating_mode)) {
return 50000;
} else if ((OPERATING_MODE_2a == operating_mode) || (OPERATING_MODE_2b == operating_mode)) {
return 100000;
} else if (OPERATING_MODE_3 == operating_mode) {
return 150000;
} else if ((OPERATING_MODE_4a == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
return 200000;
} else if (OPERATING_MODE_5 == operating_mode) {
return 300000;
}
return 0;
}
uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id)
{
if (84 == phy_mode_id) {
return 150000;
} else if (85 == phy_mode_id) {
return 200000;
} else if ((68 == phy_mode_id) || (86 == phy_mode_id)) {
return 300000;
} else if ((34 == phy_mode_id) || (51 == phy_mode_id) || (69 == phy_mode_id)) {
return 400000;
} else if ((52 == phy_mode_id) || (70 == phy_mode_id)) {
return 600000;
} else if ((35 == phy_mode_id) || (53 == phy_mode_id)) {
return 800000;
} else if ((36 == phy_mode_id) || (54 == phy_mode_id)) {
return 1200000;
} else if (37 == phy_mode_id) {
return 1600000;
} else if (38 == phy_mode_id) {
return 2400000;
}
return 0;
}
uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id)
{
if ((phy_mode_id >= 34) && (phy_mode_id <= 38)) {
return OFDM_OPTION_1;
} else if ((phy_mode_id >= 51) && (phy_mode_id <= 54)) {
return OFDM_OPTION_2;
} else if ((phy_mode_id >= 68) && (phy_mode_id <= 70)) {
return OFDM_OPTION_3;
} else if ((phy_mode_id >= 84) && (phy_mode_id <= 86)) {
return OFDM_OPTION_4;
}
return 0;
}
uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id)
{
if (34 == phy_mode_id) {
return OFDM_MCS_2;
} else if ((35 == phy_mode_id) || (51 == phy_mode_id)) {
return OFDM_MCS_3;
} else if ((36 == phy_mode_id) || (52 == phy_mode_id) || (68 == phy_mode_id) || (84 == phy_mode_id)) {
return OFDM_MCS_4;
} else if ((37 == phy_mode_id) || (53 == phy_mode_id) || (69 == phy_mode_id) || (85 == phy_mode_id)) {
return OFDM_MCS_5;
} else if ((38 == phy_mode_id) || (54 == phy_mode_id) || (70 == phy_mode_id) || (86 == phy_mode_id)) {
return OFDM_MCS_6;
}
return 0;
}
phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode)
{
if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
return MODULATION_INDEX_1_0;
} else {
return MODULATION_INDEX_0_5;
}
}
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule)
{
(void)cur;
@ -229,23 +153,18 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
if (phy_type >= 2 && phy_mode > 6) {
return -1;
}
// Skip if PHY mode is for FSK modulation
if (!phy_mode_id || ((phy_mode_id > 8) && (phy_mode_id < 17)) || phy_mode_id > 24) {
if (M_OFDM == ws_phy_get_modulation_using_phy_mode_id(phy_mode_id)) {
// Validate OFDM configurations
if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) ||
((phy_mode_id >= 51) && (phy_mode_id <= 54)) ||
((phy_mode_id >= 68) && (phy_mode_id <= 70)) ||
((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
if (ws_get_datarate_using_phy_mode_id(phy_mode_id) == 0 ||
ws_get_ofdm_option_using_phy_mode_id(phy_mode_id) == 0 ||
ws_get_ofdm_mcs_using_phy_mode_id(phy_mode_id) == 0) {
//Unsupported PHY mode
return -1;
}
} else {
// Invalid PHY mode ID
if (!ws_phy_get_datarate_using_phy_mode_id(phy_mode_id) ||
!ws_phy_get_ofdm_option_using_phy_mode_id(phy_mode_id) ||
!ws_phy_get_ofdm_mcs_using_phy_mode_id(phy_mode_id)) {
//Unsupported PHY mode
return -1;
}
} else if (M_UNDEFINED == ws_phy_get_modulation_using_phy_mode_id(phy_mode_id)) {
// Invalid PHY mode ID
return -1;
}
}
hopping_schdule->channel_plan = 0;
@ -261,20 +180,44 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
return -1;
}
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_EU) {
if (hopping_schdule->operating_class == 1) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->operating_class == 2) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else if (hopping_schdule->operating_class == 3) {
hopping_schdule->ch0_freq = 8701;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->operating_class == 4) {
hopping_schdule->ch0_freq = 8702;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
if (hopping_schdule->channel_plan_id == 255) {
if (hopping_schdule->operating_class == 1) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->operating_class == 2) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else if (hopping_schdule->operating_class == 3) {
hopping_schdule->ch0_freq = 8701;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->operating_class == 4) {
hopping_schdule->ch0_freq = 8702;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else {
return -1;
}
} else {
return -1;
if (hopping_schdule->channel_plan_id == 32) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->channel_plan_id == 33) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else if (hopping_schdule->channel_plan_id == 34) {
hopping_schdule->ch0_freq = 8701;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->channel_plan_id == 35) {
hopping_schdule->ch0_freq = 8702;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else if (hopping_schdule->channel_plan_id == 36) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_100;
} else if (hopping_schdule->channel_plan_id == 37) {
hopping_schdule->ch0_freq = 8631;
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
} else {
return -1;
}
}
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_IN) {
if (hopping_schdule->operating_class == 1) {
@ -385,15 +328,10 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
return 16;
}
} else if (regulatory_domain == REG_DOMAIN_EU) {
if (operating_class == 1) {
return 69;
} else if (operating_class == 2) {
return 35;
} else if (operating_class == 3) {
return 55;
} else if (operating_class == 4) {
return 27;
if (channel_plan_id == 255) {
channel_plan_id = ws_phy_convert_operating_class_to_channel_plan_id(operating_class, regulatory_domain);
}
return ws_phy_get_number_of_channels_using_channel_plan_id(channel_plan_id);
} else if (regulatory_domain == REG_DOMAIN_IN) {
if (operating_class == 1) {
return 19;
@ -402,22 +340,9 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
}
} else if (regulatory_domain == REG_DOMAIN_NA) {
if (channel_plan_id == 255) {
if (operating_class == 1) {
return 129;
} else if (operating_class == 2) {
return 64;
} else if (operating_class == 3) {
return 42;
}
} else {
if (channel_plan_id == 1) {
return 129;
} else if (channel_plan_id == 2) {
return 64;
} else if (channel_plan_id == 5) {
return 21;
}
channel_plan_id = ws_phy_convert_operating_class_to_channel_plan_id(operating_class, regulatory_domain);
}
return ws_phy_get_number_of_channels_using_channel_plan_id(channel_plan_id);
} else if (regulatory_domain == REG_DOMAIN_JP) {
if (operating_class == 1) {
return 38;
@ -428,22 +353,9 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
}
} else if (regulatory_domain == REG_DOMAIN_BZ) {
if (channel_plan_id == 255) {
if (operating_class == 1) {
return 129;
} else if (operating_class == 2) {
return 64;
} else if (operating_class == 3) {
return 42;
}
} else {
if (channel_plan_id == 1) {
return 129;
} else if (channel_plan_id == 2) {
return 64;
} else if (channel_plan_id == 5) {
return 21;
}
channel_plan_id = ws_phy_convert_operating_class_to_channel_plan_id(operating_class, regulatory_domain);
}
return ws_phy_get_number_of_channels_using_channel_plan_id(channel_plan_id);
} else if (regulatory_domain == REG_DOMAIN_WW) {
if (operating_class == 1) {
// TODO we dont support this yet, but it is used as test value
@ -472,12 +384,13 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
ns_list_init(&cur->ws_info->parent_list_free);
ns_list_init(&cur->ws_info->parent_list_reserved);
cur->ws_info->version = test_pan_version;
cur->ws_info->network_pan_id = 0xffff;
cur->ws_info->pan_information.use_parent_bs = true;
cur->ws_info->pan_information.rpl_routing_method = true;
cur->ws_info->pan_information.pan_version_set = false;
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
cur->ws_info->hopping_schdule.regulatory_domain = REG_DOMAIN_EU;
@ -490,14 +403,40 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule);
cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
// initialize for FAN 1.1 defaults
if (ws_version_1_1(cur)) {
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_1;
}
return 0;
}
int ws_common_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
{
return ws_bootstrap_init(interface_id, bootstrap_mode);
}
void ws_common_state_machine(protocol_interface_info_entry_t *cur)
{
if (wisun_mode_host(cur)) {
// Configure for LFN device
ws_bootstrap_lfn_state_machine(cur);
} else if (wisun_mode_router(cur)) {
// Configure FFN device
ws_bootstrap_ffn_state_machine(cur);
} else if (wisun_mode_border_router(cur)) {
// Configure as Border router
ws_bootstrap_6lbr_state_machine(cur);
}
}
void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
{
ws_bbr_seconds_timer(cur, seconds);
ws_bootstrap_seconds_timer(cur, seconds);
ws_bootstrap_6lbr_seconds_timer(cur, seconds);
ws_bootstrap_ffn_seconds_timer(cur, seconds);
ws_bootstrap_lfn_seconds_timer(cur, seconds);
blacklist_ttl_update(seconds);
}
@ -508,6 +447,12 @@ void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
ws_llc_fast_timer(cur, ticks);
}
void ws_common_create_ll_address(uint8_t *ll_address, const uint8_t *mac64)
{
memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_address + 8, mac64, 8);
ll_address[8] ^= 2;
}
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
{
@ -652,13 +597,10 @@ uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur)
uint32_t ws_common_datarate_get_from_phy_mode(uint8_t phy_mode_id, uint8_t operating_mode)
{
if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) ||
((phy_mode_id >= 51) && (phy_mode_id <= 54)) ||
((phy_mode_id >= 68) && (phy_mode_id <= 70)) ||
((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return ws_get_datarate_using_phy_mode_id(phy_mode_id);
if (phy_mode_id == 255) {
phy_mode_id = ws_phy_convert_operating_mode_to_phy_mode_id(operating_mode);
}
return ws_get_datarate_using_operating_mode(operating_mode);
return ws_phy_get_datarate_using_phy_mode_id(phy_mode_id);
}
uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur)
@ -737,4 +679,16 @@ void ws_common_border_router_alive_update(protocol_interface_info_entry_t *inter
interface->ws_info->pan_timeout_timer = interface->ws_info->cfg->timing.pan_timeout;
}
fhss_ws_configuration_t ws_common_get_current_fhss_configuration(protocol_interface_info_entry_t *cur)
{
fhss_ws_configuration_t fhss_configuration;
memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t));
if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) {
memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t));
} else {
tr_error("FHSS configuration could not be read");
}
return fhss_configuration;
}
#endif // HAVE_WS

View File

@ -37,6 +37,8 @@ struct ws_pan_information_s;
struct ws_neighbor_class_s;
struct ws_excluded_channel_data_s;
struct ws_cfg_s;
struct ws_neighbor_class_entry;
struct mcps_data_ie_list;
typedef struct parent_info_s {
uint16_t pan_id; /**< PAN ID */
@ -79,6 +81,30 @@ typedef struct {
uint16_t old_bsi;
} ws_bsi_block_t;
typedef struct {
uint16_t eapol_trigger_timer;
uint16_t pas_trigger_timer;
uint16_t pcs_trigger_timer;
uint16_t dis_trigger_timer;
uint16_t dis_trigger_timer_val;
uint16_t rpl_trigger_timer;
uint16_t rpl_trigger_timer_val;
uint8_t pas_trigger_count;
uint8_t pcs_trigger_count;
bool auto_trg_enabled;
} ws_test_proc_trg_t;
typedef struct {
uint16_t lfn_version;
bool lfn_version_learned: 1;
bool active_hash_1: 1;
bool active_hash_2: 1;
bool active_hash_3: 1;
unsigned active_key_index: 2;
uint8_t lgtkhash[24];
} ws_lfn_lgtk_t;
typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t;
typedef struct ws_info_s {
@ -87,6 +113,7 @@ typedef struct ws_info_s {
trickle_t trickle_pan_advertisement_solicit;
trickle_t trickle_pan_advertisement;
trickle_params_t trickle_params_pan_discovery;
uint8_t version; // Wi-SUN version information 1 = 1.0 2 = 1.x
uint8_t rpl_state; // state from rpl_event_t
uint8_t pas_requests; // Amount of PAN solicits sent
uint8_t device_min_sens; // Device min sensitivity set by the application
@ -114,6 +141,11 @@ typedef struct ws_info_s {
ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX];
ws_nud_table_list_t active_nud_process;
ws_nud_table_list_t free_nud_entries;
ws_test_proc_trg_t test_proc_trg;
#ifdef HAVE_WS_VERSION_1_1
ws_lfn_lgtk_t lfngtk;
ws_phy_cap_info_t phy_cap_info;
#endif
struct ws_cfg_s *cfg; /**< Wi-SUN configuration */
struct ws_pan_information_s pan_information;
ws_hopping_schedule_t hopping_schdule;
@ -125,21 +157,9 @@ typedef struct ws_info_s {
#ifdef HAVE_WS
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id);
int8_t ws_common_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id);
uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels);
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing);
uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode);
uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id);
uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id);
uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id);
phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode);
uint16_t ws_common_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels);
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule);
@ -151,6 +171,8 @@ void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seco
void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
void ws_common_create_ll_address(uint8_t *ll_address, const uint8_t *mac64);
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
void ws_common_black_list_neighbour(const uint8_t *ll_address, uint8_t nd_status);
@ -184,11 +206,35 @@ void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface,
void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface);
uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size);
void ws_common_border_router_alive_update(protocol_interface_info_entry_t *interface);
int ws_common_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
void ws_common_state_machine(protocol_interface_info_entry_t *cur);
fhss_ws_configuration_t ws_common_get_current_fhss_configuration(protocol_interface_info_entry_t *cur);
#define ws_info(cur) ((cur)->ws_info)
#ifdef HAVE_WS_VERSION_1_1
#define ws_version_1_0(cur) (((cur)->ws_info) && ((cur)->ws_info)->version == 1)
#define ws_version_1_1(cur) (((cur)->ws_info) && ((cur)->ws_info)->version > 1)
#define ws_lfn_version_learned(cur) ((cur)->ws_info->lfngtk.lfn_version_learned == true)
#define ws_neighbour_cap_pointer(neighbour) (&neighbour->pcap_info)
#else
#define ws_version_1_1(cur) (false)
#define ws_version_1_0(cur) ((cur)->ws_info)
#define ws_lfn_version_learned(cur) (false)
#define ws_neighbour_cap_pointer(neighbour) NULL
#endif
#define ws_test_proc_auto_trg(cur) ((cur)->ws_info->test_proc_trg.auto_trg_enabled == true)
#else
#define ws_info(cur) ((ws_info_t *) NULL)
#define ws_version_1_1(cur) (false)
#define ws_version_1_0(cur) (false)
#define ws_lfn_version_learned(cur) (false)
#define ws_neighbour_cap_pointer(neighbour) NULL
#define ws_test_proc_auto_trg(cur) (false)
#define ws_common_seconds_timer(cur, seconds)
#define ws_common_neighbor_update(cur, ll_address) ((void) 0)
#define ws_common_black_list_neighbour(ll_address, nd_status) ((void) 0)
@ -207,6 +253,8 @@ void ws_common_border_router_alive_update(protocol_interface_info_entry_t *inter
#define ws_common_primary_parent_update(interface, neighbor)
#define ws_common_secondary_parent_update(interface)
#define ws_common_border_router_alive_update(interface) ((void) 0)
#define ws_common_init(interface_id, bootstrap_mode) 0
#define ws_common_state_machine(cur)
#endif //HAVE_WS

View File

@ -28,19 +28,40 @@
#define WH_IE_MHDS_TYPE 5 /**< MHDS information for mesh routing */
#define WH_IE_VH_TYPE 6 /**< Vendor header information */
#define WH_IE_EA_TYPE 9 /**< Eapol Auhtenticator EUI-64 header information */
/* Wi-SUN FAN dfinition 1.1 */
#define WH_IE_LUTT_TYPE 10 /**< LFN Unicast Timing and Frame Type information */
#define WH_IE_LBT_TYPE 11 /**< LFN Broadcast Timing information */
#define WH_IE_NR_TYPE 12 /**< Node Role IE information */
#define WH_IE_LUS_TYPE 13 /**< LFN Unicast Schedule information */
#define WH_IE_FLUS_TYPE 14 /**< FFN for LFN unicast Schedule information */
#define WH_IE_LBS_TYPE 15 /**< LFN Broadcast Schedule information */
#define WH_IE_LND_TYPE 16 /**< LFN Network Discovery information */
#define WH_IE_LTO_TYPE 17 /**< LFN Timing information */
#define WH_IE_PANID_TYPE 18 /**< PAN Identifier information */
#define WS_WP_NESTED_IE 4 /**< WS nested Payload IE element'selement could include mltiple sub payload IE */
#define WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH 2
/* Payload IE sub elements in side WS_WP_NESTED_IE */
#define WP_PAYLOAD_IE_US_TYPE 1 /**< Unicast Schedule information */
#define WP_PAYLOAD_IE_BS_TYPE 2 /**< Broadcast Schedule information */
#define WP_PAYLOAD_IE_VP_TYPE 3 /**< Vendor Payload information */
/* Long form subID's */
#define WP_PAYLOAD_IE_US_TYPE 1 /**< Unicast Schedule information */
#define WP_PAYLOAD_IE_BS_TYPE 2 /**< Broadcast Schedule information */
#define WP_PAYLOAD_IE_VP_TYPE 3 /**< Vendor Payload information */
/* Wi-SUN FAN definition 1.1 */
#define WP_PAYLOAD_IE_LFN_CHANNEL_PLAN_TYPE 4 /**< LFN Channel Plan information*/
/* Short form subID's */
#define WP_PAYLOAD_IE_PAN_TYPE 4 /**< PAN Information */
#define WP_PAYLOAD_IE_NETNAME_TYPE 5 /**< Network Name information */
#define WP_PAYLOAD_IE_PAN_VER_TYPE 6 /**< Pan configuration version */
#define WP_PAYLOAD_IE_GTKHASH_TYPE 7 /**< GTK Hash information */
/* Wi-SUN FAN definition 1.1 */
#define WP_PAYLOAD_IE_PCAP_TYPE 8 /**< PHY Capability information */
#define WP_PAYLOAD_IE_LFNVER_TYPE 9 /**< LFN Version information */
#define WP_PAYLOAD_IE_LGTKHASH_TYPE 10 /**< LFN GTK Hash Information */
/* WS frame types to WH_IE_UTT_TYPE */
#define WS_FT_PAN_ADVERT 0 /**< PAN Advert */
@ -50,14 +71,25 @@
#define WS_FT_DATA 4 /**< data type inside MPX */
#define WS_FT_ACK 5 /**< Enhanced ACK */
#define WS_FT_EAPOL 6 /**< EAPOL message inside MPX */
/* Wi-SUN FAN 1.1 */
#define WS_FT_LPA 9 /**< LFN PAN Advert */
#define WS_FT_LPAS 10 /**< LFN PAN Advert Solicit */
#define WS_FT_LPC 11 /**< LFN PAN Config */
#define WS_FT_LPCS 12 /**< LFN PAN Config Solicit */
/* WS exluded channel Control */
#define WS_EXC_CHAN_CTRL_NONE 0 /**< No excluded channels */
#define WS_EXC_CHAN_CTRL_RANGE 1 /**< Excluded channels are in 1 or multiple channel range */
#define WS_EXC_CHAN_CTRL_BITMASK 2 /**< Excluded channels are marked to bitmask which length based on configured channels */
#define WS_EXC_CHAN_CTRL_BITMASK 2 /**< Excluded channels are marked to bitmask which length based on configured channels */
#define WS_EXCLUDED_MAX_RANGE_TO_SEND 3
#define WS_NR_ROLE_BR 0
#define WS_NR_ROLE_ROUTER 1
#define WS_NR_ROLE_LFN 2
/**
* @brief ws_pan_information_t PAN information
*/
@ -68,6 +100,7 @@ typedef struct ws_pan_information_s {
bool use_parent_bs: 1; /**< 1 for force to follow parent broadcast schedule. 0 node may define own schedule. */
bool rpl_routing_method: 1; /**< 1 when RPL routing is selected and 0 when L2 routing. */
bool pan_version_set: 1; /**< 1 PAN version is set. */
bool lfn_window_style: 1; /**< 1 FFN management trasmission. */
unsigned version: 3; /**< Pan version support. */
} ws_pan_information_t;
@ -125,6 +158,101 @@ typedef struct ws_utt_ie {
uint_fast24_t ufsi;
} ws_utt_ie_t;
/**
* @brief ws_utt_ie_t WS LUTT-IE
*/
typedef struct ws_lutt_ie {
uint8_t message_type;
uint16_t slot_number;
uint_fast24_t interval_offset;
} ws_lutt_ie_t;
/**
* @brief ws_lbt_ie_t WS LBT-IE
*/
typedef struct ws_lbt_ie {
uint16_t slot_number;
uint_fast24_t interval_offset;
} ws_lbt_ie_t;
/**
* @brief ws_nr_ie_t WS NR-IE
*/
typedef struct ws_nr_ie {
unsigned node_role: 3;
uint8_t clock_drift;
uint8_t timing_accurancy;
uint_fast24_t listen_interval_min;
uint_fast24_t listen_interval_max;
} ws_nr_ie_t;
/**
* @brief ws_lus_ie_t WS LUS-IE
*/
typedef struct ws_lus_ie {
uint8_t channel_plan_tag;
uint_fast24_t listen_interval;
} ws_lus_ie_t;
/**
* @brief ws_lus_ie_t WS FLUS-IE
*/
typedef struct ws_flus_ie {
uint8_t channel_plan_tag;
uint8_t dwell_interval;
} ws_flus_ie_t;
/**
* @brief ws_lnd_ie_t WS LND-IE
*/
typedef struct ws_lnd_ie {
uint8_t response_threshold;
uint8_t discovery_slot_time;
uint8_t discovery_slots;
uint16_t discovery_first_slot;
uint_fast24_t response_delay;
} ws_lnd_ie_t;
/**
* @brief ws_lto_ie_t WS LTO-IE
*/
typedef struct ws_lto_ie {
uint_fast24_t offset;
uint_fast24_t adjusted_listening_interval;
} ws_lto_ie_t;
/**
* @brief ws_lbs_ie_t WS LBS-IE
*/
typedef struct ws_lbs_ie {
uint8_t channel_plan_tag;
uint16_t broadcast_secheduler_id;
uint_fast24_t broadcast_interval;
} ws_lbs_ie_t;
/**
* @brief ws_panid_ie_t WS PANID-IE
*/
typedef struct ws_panid_ie {
uint16_t panid;
} ws_panid_ie_t;
/**
* @brief ws_pcap_ie_t WS PCAB-IE
*/
typedef struct ws_pcap_ie {
unsigned phy_type: 3;
uint16_t operating_mode;
} ws_pcap_ie_t;
typedef struct ws_phy_cap_info {
unsigned length_of_list: 3;
ws_pcap_ie_t pcap[7];
} ws_phy_cap_info_t;
/**
* @brief ws_bt_ie_t WS BT-IE read
*/
@ -141,6 +269,26 @@ typedef struct ws_fc_ie {
uint8_t rx_flow_ctrl;
} ws_fc_ie_t;
/**
* @brief ws_lfnver_ie_t WS LFNVER-IE element
*/
typedef struct ws_lfnver_ie {
uint16_t lfn_version;
} ws_lfnver_ie_t;
/**
* @brief ws_lgtkhash_ie_t WS LGTKHASH-IE element
*/
typedef struct ws_lgtkhash_ie {
bool lgtk0: 1; /**< 1= LGTK0 in line 0 = elided */
bool lgtk1: 1; /**< 1= LGTK1 in line 0 = elided */
bool lgtk2: 1; /**< 1= LGTK2 in line 0 = elided */
unsigned active_lgtk_index: 2; /**< Indicate Active LGTK index 0-2 */
uint8_t *lgtk0_hash; /**< LGTK0 64-bit Hash if lgtk0=1*/
uint8_t *lgtk1_hash; /**< LGTK1 64-bit Hash if lgtk1=1*/
uint8_t *lgtk2_hash; /**< LGTK2 64-bit Hash if lgtk2=1*/
} ws_lgtkhash_ie_t;
/**
* @brief ws_channel_plan_zero_t WS channel plan 0 define domain and class
*/
@ -158,6 +306,14 @@ typedef struct ws_channel_plan_one {
uint16_t number_of_channel;
} ws_channel_plan_one_t;
/**
* @brief ws_channel_plan_two_t WS channel plan 2 define regulator domain and chanel plan 1
*/
typedef struct ws_channel_plan_two {
uint8_t regulator_domain;
uint8_t channel_plan_id;
} ws_channel_plan_two_t;
/**
* @brief ws_channel_function_zero_t WS function 0 fixed channel
*/
@ -189,6 +345,43 @@ typedef struct ws_excluded_channel_mask {
uint8_t mask_len_inline;
} ws_excluded_channel_mask_t;
typedef struct ws_excluded_channel_range_out {
unsigned excluded_range_length: 3;
ws_excluded_channel_range_data_t *exluded_range;
} ws_excluded_channel_range_out_t;
typedef struct ws_excluded_channel_mask_out {
uint16_t excluded_channel_count;
uint8_t channel_mask_bytes_inline;
uint32_t *channel_mask;
} ws_excluded_channel_mask_out_t;
/**
* @brief ws_generic_channel_info_t Generic Channel Info
*/
typedef struct ws_generic_channel_info {
unsigned channel_plan: 3;
unsigned channel_function: 3;
unsigned excluded_channel_ctrl: 2;
union {
ws_channel_plan_zero_t zero;
ws_channel_plan_one_t one;
ws_channel_plan_two_t two;
} plan;
union {
ws_channel_function_zero_t zero;
ws_channel_function_three_t three;
} function;
union {
ws_excluded_channel_range_out_t range;
ws_excluded_channel_mask_out_t mask;
ws_excluded_channel_range_t range_in;
ws_excluded_channel_mask_t mask_in;
} excluded_channels;
} ws_generic_channel_info_t;
/**
* @brief ws_us_ie_t WS US-IE read
*/
@ -202,6 +395,7 @@ typedef struct ws_us_ie {
union {
ws_channel_plan_zero_t zero;
ws_channel_plan_one_t one;
ws_channel_plan_two_t two;
} plan;
union {
ws_channel_function_zero_t zero;
@ -228,6 +422,7 @@ typedef struct ws_bs_ie {
union {
ws_channel_plan_zero_t zero;
ws_channel_plan_one_t one;
ws_channel_plan_two_t two;
} plan;
union {
ws_channel_function_zero_t zero;
@ -247,6 +442,7 @@ typedef struct ws_bs_ie {
#define WS_MPX_MAX_MTU 1576
#define WS_FAN_VERSION_1_0 1
#define WS_FAN_VERSION_1_1 2
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
@ -381,9 +577,9 @@ typedef struct ws_bs_ie {
/* Default FHSS timing information
*
*/
#define WS_FHSS_UC_DWELL_INTERVAL 255;
#define WS_FHSS_BC_INTERVAL 1020;
#define WS_FHSS_BC_DWELL_INTERVAL 255;
#define WS_FHSS_UC_DWELL_INTERVAL 255
#define WS_FHSS_BC_INTERVAL 1020
#define WS_FHSS_BC_DWELL_INTERVAL 255
/*
* EAPOL relay and PAE authenticator socket settings

View File

@ -97,7 +97,7 @@
#define PAN_VERSION_SMALL_NETWORK_TIMEOUT 30*60
#define PAN_VERSION_MEDIUM_NETWORK_TIMEOUT 60*60
#define PAN_VERSION_MEDIUM_NETWORK_TIMEOUT 30*60
#define PAN_VERSION_LARGE_NETWORK_TIMEOUT 90*60

View File

@ -26,6 +26,7 @@
#include "ws_management_api.h"
#include "ns_time_api.h"
#include "net_ws_test_ext.h"
#ifndef HAVE_WS
int ws_management_node_init(
@ -362,6 +363,12 @@ int ws_management_timing_parameters_validate(
}
/* ### test api ### */
int ws_test_version_set(int8_t interface_id, uint8_t version)
{
(void) interface_id;
(void) version;
return -1;
}
int ws_test_pan_size_set(int8_t interface_id, uint16_t pan_size)
{
(void) interface_id;
@ -488,5 +495,22 @@ int8_t ws_test_drop_edfe_data_frames(int8_t interface_id, uint8_t number_of_dro
return -1;
}
int ws_test_procedure_trigger(int8_t interface_id, ws_test_proc_t procedure, void *parameters)
{
(void) interface_id;
(void) procedure;
(void) parameters;
return -1;
}
int ws_management_phy_capability_set(
int8_t interface_id,
ws_management_pcap_info_t *pcap_list)
{
(void)interface_id;
(void)pcap_list;
return -1;
}
#endif // no HAVE_WS

View File

@ -24,6 +24,8 @@ struct ws_bt_ie;
struct ws_us_ie;
struct ws_hopping_schedule_s;
struct ws_fc_ie;
struct ws_phy_cap_info;
struct ws_pcap_ie;
/**
* @brief ws_wp_network_name_t WS nested payload network name
@ -33,6 +35,16 @@ typedef struct ws_wp_network_name {
uint8_t *network_name;
} ws_wp_network_name_t;
#define ws_wp_nested_lfn_version_length() 2
#define ws_wh_lutt_length() 6
#define ws_wh_lus_length() 4
#define ws_wh_flus_length() 2
#define ws_wh_lbt_length() 5
#define ws_wh_lbs_length() 6
#define ws_wh_lnd_length() 8
#define ws_wh_lto_length() 6
#define ws_wh_panid_length() 2
/* WS_WH HEADER IE */
uint8_t *ws_wh_utt_write(uint8_t *ptr, uint8_t message_type);
uint8_t *ws_wh_bt_write(uint8_t *ptr);
@ -40,12 +52,34 @@ uint8_t *ws_wh_fc_write(uint8_t *ptr, struct ws_fc_ie *fc_ie);
uint8_t *ws_wh_rsl_write(uint8_t *ptr, uint8_t rsl);
uint8_t *ws_wh_vh_write(uint8_t *ptr, uint8_t *vendor_header, uint8_t vendor_header_length);
uint8_t *ws_wh_ea_write(uint8_t *ptr, uint8_t *eui64);
/* Wi-SUN FAN 1.1 */
uint8_t *ws_wh_lutt_write(uint8_t *ptr, uint8_t message_type);
uint8_t *ws_wh_lus_write(uint8_t *ptr, struct ws_lus_ie *lus_ptr);
uint8_t *ws_wh_flus_write(uint8_t *ptr, struct ws_flus_ie *flus_ptr);
uint8_t *ws_wh_lbt_write(uint8_t *ptr);
uint8_t *ws_wh_lbs_write(uint8_t *ptr, struct ws_lbs_ie *lbs_ptr);
uint8_t *ws_wh_nr_write(uint8_t *ptr, struct ws_nr_ie *nr_ptr);
uint16_t ws_wh_nr_length(struct ws_nr_ie *nr_ptr);
uint8_t *ws_wh_lnd_write(uint8_t *ptr, struct ws_lnd_ie *lnd_ptr);
uint8_t *ws_wh_lto_write(uint8_t *ptr, struct ws_lto_ie *lto_ptr);
uint8_t *ws_wh_panid_write(uint8_t *ptr, uint16_t pana_id);
bool ws_wh_utt_read(uint8_t *data, uint16_t length, struct ws_utt_ie *utt_ie);
bool ws_wh_bt_read(uint8_t *data, uint16_t length, struct ws_bt_ie *bt_ie);
bool ws_wh_fc_read(uint8_t *data, uint16_t length, struct ws_fc_ie *fc_ie);
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl);
bool ws_wh_ea_read(uint8_t *data, uint16_t length, uint8_t *eui64);
/*Wi-SUN FAN 1.1 */
bool ws_wh_lutt_read(uint8_t *data, uint16_t length, struct ws_lutt_ie *ws_lutt);
bool ws_wh_lus_read(uint8_t *data, uint16_t length, struct ws_lus_ie *lus_ptr);
bool ws_wh_flus_read(uint8_t *data, uint16_t length, struct ws_flus_ie *flus_ptr);
bool ws_wh_lbt_read(uint8_t *data, uint16_t length, struct ws_lbt_ie *ws_lbt);
bool ws_wh_lbs_read(uint8_t *data, uint16_t length, struct ws_lbs_ie *lbs_ptr);
bool ws_wh_nr_read(uint8_t *data, uint16_t length, struct ws_nr_ie *nr_ptr);
bool ws_wh_lnd_read(uint8_t *data, uint16_t length, struct ws_lnd_ie *lnd_ptr);
bool ws_wh_lto_read(uint8_t *data, uint16_t length, struct ws_lto_ie *lto_ptr);
bool ws_wh_panid_read(uint8_t *data, uint16_t length, struct ws_panid_ie *ws_panid);
/* WS_WP_NESTED PAYLOD IE */
uint8_t *ws_wp_base_write(uint8_t *ptr, uint16_t length);
@ -56,6 +90,22 @@ uint8_t *ws_wp_nested_netname_write(uint8_t *ptr, uint8_t *network_name, uint8_t
uint8_t *ws_wp_nested_pan_ver_write(uint8_t *ptr, struct ws_pan_information_s *pan_congiguration);
uint8_t *ws_wp_nested_gtkhash_write(uint8_t *ptr, uint8_t *gtkhash, uint8_t gtkhash_length);
uint16_t ws_wp_nested_hopping_schedule_length(struct ws_hopping_schedule_s *hopping_schedule, bool unicast_schedule);
/* Wi-SUN FAN 1.1 */
/* WS PCAP */
uint8_t *ws_wp_nested_pcap_write(uint8_t *ptr, struct ws_phy_cap_info *pcap_list);
uint16_t ws_wp_nested_pcap_length(uint8_t list_length);
struct ws_pcap_ie ws_ie_lib_generate_phy_cap_from_phy_mode_id(uint8_t phy_mode_id);
uint8_t ws_ie_lib_phy_mode_id_get_from_phy_cap(struct ws_pcap_ie *phy_cap);
void ws_ie_lib_phy_cap_list_update(struct ws_phy_cap_info *phy_pap, struct ws_pcap_ie *pcap);
/* WS LFN version */
uint8_t *ws_wp_nested_lfn_version_write(uint8_t *ptr, struct ws_lfnver_ie *ws_lfnver);
/* WS LFN GTK HAS */
uint8_t *ws_wp_nested_lgtk_hash_write(uint8_t *ptr, struct ws_lgtkhash_ie *ws_lgtkhash);
uint16_t ws_wp_lgtk_hash_length(struct ws_lgtkhash_ie *ws_lgtkhash);
/* WS LFN Channel plan */
uint8_t *ws_wp_nested_lfn_channel_plan_write(uint8_t *ptr, struct ws_generic_channel_info *ws_lcp, uint8_t plan_tag_id);
uint16_t ws_wp_nested_lfn_channel_plan_length(struct ws_generic_channel_info *ws_lcp);
bool ws_wp_nested_us_read(uint8_t *data, uint16_t length, struct ws_us_ie *us_ie);
bool ws_wp_nested_bs_read(uint8_t *data, uint16_t length, struct ws_bs_ie *bs_ie);
@ -63,6 +113,11 @@ bool ws_wp_nested_pan_read(uint8_t *data, uint16_t length, struct ws_pan_informa
bool ws_wp_nested_pan_version_read(uint8_t *data, uint16_t length, uint16_t *pan_version);
bool ws_wp_nested_network_name_read(uint8_t *data, uint16_t length, ws_wp_network_name_t *network_name);
uint8_t *ws_wp_nested_gtkhash_read(uint8_t *data, uint16_t length);
/* Wi-SUN FAN 1.1 */
bool ws_wp_nested_pcap_read(uint8_t *data, uint16_t length, struct ws_phy_cap_info *ws_pcap_list);
bool ws_wp_nested_lfn_version_read(uint8_t *data, uint16_t length, struct ws_lfnver_ie *ws_lfnver);
bool ws_wp_nested_lgtk_hash_read(uint8_t *data, uint16_t length, struct ws_lgtkhash_ie *ws_lgtkhash);
bool ws_wp_nested_lfn_channel_plan_read(uint8_t *data, uint16_t length, struct ws_generic_channel_info *ws_lcp, uint8_t plan_tag_id);
#endif /* WS_IE_LIB_H_ */

View File

@ -49,13 +49,15 @@ typedef struct wh_ie_sub_list_s {
* @brief wp_nested_ie_sub_list_t ws asynch Nested Payload sub IE element request list
*/
typedef struct wp_nested_ie_sub_list_s {
bool us_ie: 1; /**< Unicast Schedule information */
bool bs_ie: 1; /**< Broadcast Schedule information */
bool vp_ie: 1; /**< Vendor Payload information */
bool pan_ie: 1; /**< PAN Information */
bool net_name_ie: 1; /**< Network Name information */
bool pan_version_ie: 1; /**< Pan configuration version */
bool gtkhash_ie: 1; /**< GTK Hash information */
bool us_ie: 1; /**< Unicast Schedule information */
bool bs_ie: 1; /**< Broadcast Schedule information */
bool vp_ie: 1; /**< Vendor Payload information */
bool pan_ie: 1; /**< PAN Information */
bool net_name_ie: 1; /**< Network Name information */
bool pan_version_ie: 1; /**< Pan configuration version */
bool gtkhash_ie: 1; /**< GTK Hash information */
bool lfn_gtk_version_ie: 1; /**< LFN Version & GTK Hash */
bool phy_cap_ie: 1; /** < Phy Cap information for MDR */
} wp_nested_ie_sub_list_t;
/**
@ -124,7 +126,7 @@ typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface,
* @return true when neighbor info is available
* @return false when no neighbor info
*/
typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new);
typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, struct llc_neighbour_req *neighbor_buffer, bool request_new);
/**
* @brief ws_llc_create ws LLC module create

View File

@ -34,6 +34,8 @@
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_mpx_header.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
@ -42,6 +44,7 @@
#include "Service_Libs/etx/etx.h"
#include "fhss_ws_extension.h"
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
#include "ws_management_api.h"
#ifdef HAVE_WS
@ -158,7 +161,7 @@ typedef struct {
static NS_LIST_DEFINE(llc_data_base_list, llc_data_base_t, link);
static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_ie_params_t *params);
static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_data_base_t *llc_base);
static uint16_t ws_wh_headers_length(wh_ie_sub_list_t requested_list, llc_ie_params_t *params);
/** LLC message local functions */
@ -378,9 +381,10 @@ static uint16_t ws_wh_headers_length(wh_ie_sub_list_t requested_list, llc_ie_par
return length;
}
static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_ie_params_t *params)
static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_data_base_t *llc_base)
{
uint16_t length = 0;
llc_ie_params_t *params = &llc_base->ie_params;
if (requested_list.gtkhash_ie) {
//Static 32 bytes allways
length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + params->gtkhash_length;
@ -411,6 +415,23 @@ static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_li
length += 2;
}
}
#ifdef HAVE_WS_VERSION_1_1
if (ws_version_1_1(llc_base->interface_ptr)) {
if (requested_list.lfn_gtk_version_ie) {
length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_lfn_version_length();
ws_lgtkhash_ie_t ws_lgtkhash;
ws_lgtkhash.lgtk0 = llc_base->interface_ptr->ws_info->lfngtk.active_hash_1;
ws_lgtkhash.lgtk1 = llc_base->interface_ptr->ws_info->lfngtk.active_hash_2;
ws_lgtkhash.lgtk2 = llc_base->interface_ptr->ws_info->lfngtk.active_hash_3;
length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_lgtk_hash_length(&ws_lgtkhash);
}
if (requested_list.phy_cap_ie) {
length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_pcap_length(llc_base->interface_ptr->ws_info->phy_cap_info.length_of_list);
}
}
#endif
if (requested_list.bs_ie) {
///Dynamic length
@ -774,6 +795,11 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_
//SET trusted state
mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), neighbor_info.neighbor, true);
}
//
//Phy CAP info read and store
if (ws_version_1_1(interface)) {
ws_neighbor_class_pcap_ie_store(neighbor_info.ws_neighbor, ie_ext);
}
}
mcps_data_ind_t data_ind = *data;
@ -1010,6 +1036,26 @@ static void ws_llc_lowpan_mpx_header_set(llc_message_t *message, uint16_t user_i
message->ie_vector_list[1].iovLen = ptr - (uint8_t *)message->ie_vector_list[1].ieBase;
}
#ifdef HAVE_WS_VERSION_1_1
uint8_t ws_llc_mdr_phy_mode_get(llc_data_base_t *base, const struct mcps_data_req_s *data)
{
if (!ws_version_1_1(base->interface_ptr) || !data->TxAckReq || data->msduLength < 500) {
return 0;
}
llc_neighbour_req_t neighbor_info;
if (!base->ws_neighbor_info_request_cb(base->interface_ptr, data->DstAddr, &neighbor_info, false)) {
return 0;
}
return neighbor_info.ws_neighbor->phy_mode_id;
}
#else
#define ws_llc_mdr_phy_mode_get(base, data) 0
#endif
static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *user_cb, const struct mcps_data_req_s *data, mac_data_priority_t priority)
{
wh_ie_sub_list_t ie_header_mask;
@ -1038,7 +1084,7 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
nested_wp_id.us_ie = true;
uint16_t ie_header_length = ws_wh_headers_length(ie_header_mask, &base->ie_params);
uint16_t nested_ie_length = ws_wp_nested_message_length(nested_wp_id, &base->ie_params);
uint16_t nested_ie_length = ws_wp_nested_message_length(nested_wp_id, base);
uint16_t over_head_size = ie_header_length;
if (nested_ie_length) {
@ -1066,6 +1112,7 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
ns_list_add_to_end(&base->llc_message_list, message);
mcps_data_req_t data_req;
uint8_t phy_mode_id = ws_llc_mdr_phy_mode_get(base, data);
message->mpx_user_handle = data->msduHandle;
message->ack_requested = data->TxAckReq;
if (data->TxAckReq) {
@ -1140,7 +1187,7 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
message->ie_ext.payloadIovLength = 0; //Set Back 2 at response handler
}
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority);
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority, phy_mode_id);
}
static void ws_llc_eapol_data_req_init(mcps_data_req_t *data_req, llc_message_t *message)
@ -1187,7 +1234,7 @@ static void ws_llc_mpx_eapol_send(llc_data_base_t *base, llc_message_t *message)
ns_list_add_to_end(&base->llc_message_list, message);
ws_llc_eapol_data_req_init(&data_req, message);
base->temp_entries->active_eapol_session = true;
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority);
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority, 0);
}
@ -1207,7 +1254,7 @@ static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb,
nested_wp_id.us_ie = true;
uint16_t ie_header_length = ws_wh_headers_length(ie_header_mask, &base->ie_params);
uint16_t nested_ie_length = ws_wp_nested_message_length(nested_wp_id, &base->ie_params);
uint16_t nested_ie_length = ws_wp_nested_message_length(nested_wp_id, base);
uint16_t over_head_size = ie_header_length;
if (nested_ie_length) {
@ -1764,6 +1811,31 @@ mpx_api_t *ws_llc_mpx_api_get(struct protocol_interface_info_entry *interface)
}
return &base->mpx_data_base.mpx_api;
}
#ifdef HAVE_WS_VERSION_1_1
static void ws_llc_phy_cab_list_generate(struct protocol_interface_info_entry *interface, ws_phy_cap_info_t *phy_cap)
{
memset(phy_cap, 0, sizeof(ws_phy_cap_info_t));
ws_phy_cap_info_t *prefedd_list = &interface->ws_info->phy_cap_info;
if (!prefedd_list->length_of_list) {
return;
}
for (int i = 0; i < prefedd_list->length_of_list; i++) {
ws_ie_lib_phy_cap_list_update(phy_cap, &prefedd_list->pcap[i]);
}
//Add base support
ws_pcap_ie_t base_cap = ws_ie_lib_generate_phy_cap_from_phy_mode_id(interface->ws_info->hopping_schdule.phy_mode_id);
if (base_cap.operating_mode) {
ws_ie_lib_phy_cap_list_update(phy_cap, &base_cap);
}
}
#endif
int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, asynch_request_t *request)
{
@ -1783,7 +1855,7 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
request->wh_requested_ie_list.rsl_ie = false; //Never should not be a part Asynch message
request->wh_requested_ie_list.vh_ie = false;
uint16_t header_buffer_length = ws_wh_headers_length(request->wh_requested_ie_list, &base->ie_params);
uint16_t wp_nested_payload_length = ws_wp_nested_message_length(request->wp_requested_nested_ie_list, &base->ie_params);
uint16_t wp_nested_payload_length = ws_wp_nested_message_length(request->wp_requested_nested_ie_list, base);
//Allocated
uint16_t total_length = header_buffer_length;
@ -1880,9 +1952,37 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
//Write Vendor spesific payload
ptr = ws_wp_nested_vp_write(ptr, base->ie_params.vendor_payload, base->ie_params.vendor_payload_length);
}
#ifdef HAVE_WS_VERSION_1_1
if (ws_version_1_1(interface)) {
if (request->wp_requested_nested_ie_list.lfn_gtk_version_ie) {
ws_lfnver_ie_t lfn_ver;
ws_lgtkhash_ie_t ws_lgtkhash;
//Write LFN Version
lfn_ver.lfn_version = interface->ws_info->lfngtk.lfn_version;
ptr = ws_wp_nested_lfn_version_write(ptr, &lfn_ver);
//Write LFN GTK Hash info
ws_lgtkhash.lgtk0 = base->interface_ptr->ws_info->lfngtk.active_hash_1;
ws_lgtkhash.lgtk1 = base->interface_ptr->ws_info->lfngtk.active_hash_2;
ws_lgtkhash.lgtk2 = base->interface_ptr->ws_info->lfngtk.active_hash_3;
ws_lgtkhash.active_lgtk_index = base->interface_ptr->ws_info->lfngtk.active_key_index;
ws_lgtkhash.lgtk0_hash = base->interface_ptr->ws_info->lfngtk.lgtkhash;
ws_lgtkhash.lgtk1_hash = base->interface_ptr->ws_info->lfngtk.lgtkhash + 8;
ws_lgtkhash.lgtk2_hash = base->interface_ptr->ws_info->lfngtk.lgtkhash + 16;
ptr = ws_wp_nested_lgtk_hash_write(ptr, &ws_lgtkhash);
}
if (request->wp_requested_nested_ie_list.phy_cap_ie) {
ws_phy_cap_info_t phy_cap;
ws_llc_phy_cab_list_generate(base->interface_ptr, &phy_cap);
ptr = ws_wp_nested_pcap_write(ptr, &phy_cap);
}
}
#endif
}
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, &request->channel_list, message->priority);
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, &request->channel_list, message->priority, 0);
return 0;
}

View File

@ -51,24 +51,24 @@ int ws_management_node_init(
}
ws_phy_cfg_t phy_cfg;
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
if (ws_cfg_phy_get(&phy_cfg) < 0) {
return -3;
}
phy_cfg.regulatory_domain = regulatory_domain;
if (ws_cfg_phy_set(cur, NULL, &phy_cfg, 0) < 0) {
if (ws_cfg_phy_set(cur, &phy_cfg, 0) < 0) {
return -4;
}
ws_gen_cfg_t gen_cfg;
if (ws_cfg_gen_get(&gen_cfg, NULL) < 0) {
if (ws_cfg_gen_get(&gen_cfg) < 0) {
return -3;
}
strncpy(gen_cfg.network_name, network_name_ptr, 32);
if (ws_cfg_gen_set(cur, NULL, &gen_cfg, 0) < 0) {
if (ws_cfg_gen_set(cur, &gen_cfg, 0) < 0) {
return -4;
}
@ -93,13 +93,13 @@ int ws_management_network_name_set(
}
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
if (ws_cfg_gen_get(&cfg) < 0) {
return -3;
}
strncpy(cfg.network_name, network_name_ptr, 32);
if (ws_cfg_gen_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_gen_set(cur, &cfg, 0) < 0) {
return -4;
}
@ -120,7 +120,7 @@ int ws_management_network_name_get(
}
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
if (ws_cfg_gen_get(&cfg) < 0) {
return -3;
}
@ -143,13 +143,13 @@ int ws_management_network_name_validate(
}
ws_gen_cfg_t cfg;
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
if (ws_cfg_gen_get(&cfg) < 0) {
return -3;
}
strncpy(cfg.network_name, network_name_ptr, 32);
if (ws_cfg_gen_validate(NULL, &cfg) < 0) {
if (ws_cfg_gen_validate(&cfg) < 0) {
return -4;
}
@ -170,7 +170,7 @@ int ws_management_domain_configuration_set(
ws_phy_cfg_t cfg;
ws_phy_cfg_t cfg_default;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -3;
}
@ -196,7 +196,7 @@ int ws_management_domain_configuration_set(
cfg.channel_plan_id = channel_plan_id;
}
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_phy_set(cur, &cfg, 0) < 0) {
return -4;
}
@ -216,7 +216,7 @@ int ws_management_domain_configuration_get(
}
ws_phy_cfg_t cfg;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -2;
}
@ -246,7 +246,7 @@ int ws_management_domain_configuration_validate(
}
ws_phy_cfg_t cfg;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -3;
}
@ -254,7 +254,7 @@ int ws_management_domain_configuration_validate(
cfg.phy_mode_id = phy_mode_id;
cfg.channel_plan_id = channel_plan_id;
if (ws_cfg_phy_validate(NULL, &cfg) < 0) {
if (ws_cfg_phy_validate(&cfg) < 0) {
return -4;
}
@ -276,7 +276,7 @@ int ws_management_regulatory_domain_set(
ws_phy_cfg_t cfg;
ws_phy_cfg_t cfg_default;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -3;
}
@ -300,7 +300,7 @@ int ws_management_regulatory_domain_set(
cfg.operating_class = cfg_default.operating_class;
}
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_phy_set(cur, &cfg, 0) < 0) {
return -4;
}
@ -323,7 +323,7 @@ int ws_management_regulatory_domain_get(
}
ws_phy_cfg_t cfg;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -3;
}
@ -347,7 +347,7 @@ int ws_management_regulatory_domain_validate(
}
ws_phy_cfg_t cfg;
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
if (ws_cfg_phy_get(&cfg) < 0) {
return -3;
}
@ -355,7 +355,7 @@ int ws_management_regulatory_domain_validate(
cfg.operating_class = operating_class;
cfg.operating_mode = operating_mode;
if (ws_cfg_phy_validate(NULL, &cfg) < 0) {
if (ws_cfg_phy_validate(&cfg) < 0) {
return -4;
}
@ -374,13 +374,13 @@ int ws_management_network_size_set(
}
ws_gen_cfg_t cfg;
if (ws_cfg_network_size_get(&cfg, NULL) < 0) {
if (ws_cfg_network_size_get(&cfg) < 0) {
return -3;
}
cfg.network_size = network_size;
if (ws_cfg_network_size_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_network_size_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -401,7 +401,7 @@ int ws_management_network_size_get(
}
ws_gen_cfg_t cfg;
if (ws_cfg_network_size_get(&cfg, NULL) < 0) {
if (ws_cfg_network_size_get(&cfg) < 0) {
return -3;
}
@ -421,13 +421,13 @@ int ws_management_network_size_validate(
}
ws_gen_cfg_t cfg;
if (ws_cfg_network_size_get(&cfg, NULL) < 0) {
if (ws_cfg_network_size_get(&cfg) < 0) {
return -3;
}
cfg.network_size = network_size;
if (ws_cfg_network_size_validate(NULL, &cfg) < 0) {
if (ws_cfg_network_size_validate(&cfg) < 0) {
return -4;
}
@ -446,7 +446,7 @@ int ws_management_channel_mask_set(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -463,7 +463,7 @@ int ws_management_channel_mask_set(
}
if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_fhss_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -484,7 +484,7 @@ int ws_management_channel_mask_get(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -504,13 +504,13 @@ int ws_management_channel_mask_validate(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
memcpy(cfg.fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8);
if (ws_cfg_fhss_validate(NULL, &cfg) < 0) {
if (ws_cfg_fhss_validate(&cfg) < 0) {
return -4;
}
@ -557,7 +557,7 @@ int ws_management_fhss_timing_configure(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -584,7 +584,7 @@ int ws_management_fhss_timing_configure(
cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval;
}
if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_fhss_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -605,7 +605,7 @@ int ws_management_fhss_unicast_channel_function_configure(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -631,7 +631,7 @@ int ws_management_fhss_unicast_channel_function_configure(
cfg.fhss_uc_fixed_channel = cfg_default.fhss_uc_fixed_channel;
}
if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_fhss_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -654,7 +654,7 @@ int ws_management_fhss_unicast_channel_function_get(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -678,7 +678,7 @@ int ws_management_fhss_unicast_channel_function_validate(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -686,7 +686,7 @@ int ws_management_fhss_unicast_channel_function_validate(
cfg.fhss_uc_channel_function = channel_function;
cfg.fhss_uc_fixed_channel = fixed_channel;
if (ws_cfg_fhss_validate(NULL, &cfg) < 0) {
if (ws_cfg_fhss_validate(&cfg) < 0) {
return -4;
}
@ -708,7 +708,7 @@ int ws_management_fhss_broadcast_channel_function_configure(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
ws_fhss_cfg_t cfg_default;
@ -740,7 +740,7 @@ int ws_management_fhss_broadcast_channel_function_configure(
cfg.fhss_bc_fixed_channel = cfg_default.fhss_bc_fixed_channel;
}
if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_fhss_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -764,7 +764,7 @@ int ws_management_fhss_broadcast_channel_function_get(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -790,7 +790,7 @@ int ws_management_fhss_broadcast_channel_function_validate(
}
ws_fhss_cfg_t cfg;
if (ws_cfg_fhss_get(&cfg, NULL) < 0) {
if (ws_cfg_fhss_get(&cfg) < 0) {
return -2;
}
@ -799,7 +799,7 @@ int ws_management_fhss_broadcast_channel_function_validate(
cfg.fhss_bc_channel_function = channel_function;
cfg.fhss_bc_fixed_channel = fixed_channel;
if (ws_cfg_fhss_validate(NULL, &cfg) < 0) {
if (ws_cfg_fhss_validate(&cfg) < 0) {
return -4;
}
@ -821,7 +821,7 @@ int ws_management_timing_parameters_set(
}
ws_timing_cfg_t cfg;
if (ws_cfg_timing_get(&cfg, NULL) < 0) {
if (ws_cfg_timing_get(&cfg) < 0) {
return -2;
}
@ -854,7 +854,7 @@ int ws_management_timing_parameters_set(
cfg.pan_timeout = cfg_default.pan_timeout;;
}
if (ws_cfg_timing_set(cur, NULL, &cfg, 0) < 0) {
if (ws_cfg_timing_set(cur, &cfg, 0) < 0) {
return -3;
}
@ -878,7 +878,7 @@ int ws_management_timing_parameters_get(
}
ws_timing_cfg_t cfg;
if (ws_cfg_timing_get(&cfg, NULL) < 0) {
if (ws_cfg_timing_get(&cfg) < 0) {
return -2;
}
@ -904,7 +904,7 @@ int ws_management_timing_parameters_validate(
}
ws_timing_cfg_t cfg;
if (ws_cfg_timing_get(&cfg, NULL) < 0) {
if (ws_cfg_timing_get(&cfg) < 0) {
return -2;
}
@ -913,7 +913,7 @@ int ws_management_timing_parameters_validate(
cfg.disc_trickle_k = disc_trickle_k;
cfg.pan_timeout = pan_timeout;
if (ws_cfg_timing_validate(NULL, &cfg) < 0) {
if (ws_cfg_timing_validate(&cfg) < 0) {
return -4;
}
@ -957,4 +957,33 @@ int ws_device_min_sens_set(
return 0;
}
int ws_management_phy_capability_set(
int8_t interface_id,
ws_management_pcap_info_t *pcap_list)
{
#ifdef HAVE_WS_VERSION_1_1
protocol_interface_info_entry_t *cur;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !ws_info(cur) || pcap_list->length_of_list > 7) {
return -1;
}
//Set supported configure for MDR
//TODO add validation for Phy_type and operation modes
cur->ws_info->phy_cap_info.length_of_list = pcap_list->length_of_list;
for (int i = 0; i < pcap_list->length_of_list; i++) {
cur->ws_info->phy_cap_info.pcap[i].phy_type = pcap_list->pcap[i].phy_type;
cur->ws_info->phy_cap_info.pcap[i].operating_mode = pcap_list->pcap[i].operating_mode;
}
return 0;
#else
(void)interface_id;
(void)pcap_list;
return -1;
#endif
}
#endif // HAVE_WS

View File

@ -26,7 +26,9 @@
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
#include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "ws_management_api.h"
#include "mac_api.h"
#ifdef HAVE_WS
@ -168,7 +170,7 @@ static void ws_neighbour_excluded_mask_by_range(ws_channel_mask_t *channel_info,
if (channel >= range_start && channel <= range_stop) {
//Cut channel
compare_mask_bit = 1 << (channel % 32);
compare_mask_bit = 1U << (channel % 32);
mask_index = 0 + (channel / 32);
if (channel_info->channel_mask[mask_index] & compare_mask_bit) {
@ -187,7 +189,7 @@ static uint32_t ws_reserve_order_32_bit(uint32_t value)
uint32_t ret_val = 0;
for (uint8_t i = 0; i < 32; i++) {
if ((value & (1 << i))) {
ret_val |= 1 << ((32 - 1) - i);
ret_val |= 1U << ((32 - 1) - i);
}
}
return ret_val;
@ -258,21 +260,23 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *
} else if (ws_us->channel_plan == 1) {
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel;
} else if (ws_us->channel_plan == 2) {
//TODO add Channel plan 2 channel count function call here
}
//Handle excluded channel and generate activate channel list
if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) {
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
ws_common_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_common_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) {
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
ws_common_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_common_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) {
if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) {
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
ws_common_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_common_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
}
}
@ -391,6 +395,13 @@ bool ws_neighbor_class_neighbor_duplicate_packet_check(ws_neighbor_class_entry_t
return true;
}
#ifdef HAVE_WS_VERSION_1_1
void ws_neighbor_class_pcap_ie_store(struct ws_neighbor_class_entry *ws_neighbor, const struct mcps_data_ie_list *ie_ext)
{
ws_wp_nested_pcap_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_neighbor->pcap_info);
}
#endif
#endif /* HAVE_WS */

View File

@ -21,6 +21,8 @@
#include "fhss_ws_extension.h"
#include "6LoWPAN/ws/ws_common_defines.h"
struct mcps_data_ie_list;
#define RSL_UNITITIALIZED 0x7fff
typedef struct ws_neighbor_class_entry {
@ -34,6 +36,10 @@ typedef struct ws_neighbor_class_entry {
bool broadcast_shedule_info_stored: 1;
bool synch_done : 1;
bool unicast_data_rx : 1;
#ifdef HAVE_WS_VERSION_1_1
uint8_t phy_mode_id; /*!< Bootstrap configured Preference Phy mode for MDR */
ws_phy_cap_info_t pcap_info;
#endif
} ws_neighbor_class_entry_t;
/**
@ -182,5 +188,10 @@ void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor,
void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported);
bool ws_neighbor_class_neighbor_duplicate_packet_check(ws_neighbor_class_entry_t *ws_neighbor, uint8_t mac_dsn, uint32_t rx_timestamp);
#ifdef HAVE_WS_VERSION_1_1
void ws_neighbor_class_pcap_ie_store(ws_neighbor_class_entry_t *ws_neighbor, const struct mcps_data_ie_list *ie_ext);
#else
#define ws_neighbor_class_pcap_ie_store(ws_neighbor, ie_ext) ((void)0)
#endif
#endif /* WS_NEIGHBOR_CLASS_H_ */

View File

@ -80,6 +80,13 @@
// Short GTK lifetime value, for GTK install check
#define SHORT_GTK_LIFETIME 10 * 3600 // 10 hours
// Frame counter exhaust check timer
#define FRAME_CNT_TIMER 3600
#define SECONDS_IN_DAY (3600 * 24)
#define TIME_MINIMUM_DIFFERENCE 5
#define TIME_DIFFERENCE_THRESHOLD 3600
typedef struct {
ns_list_link_t link; /**< Link */
uint16_t pan_id; /**< PAN ID */
@ -93,6 +100,7 @@ typedef struct {
ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */
ws_pae_auth_congestion_get *congestion_get; /**< Congestion get callback */
ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read; /**< Network frame counter read callback */
supp_list_t active_supp_list; /**< List of active supplicants */
supp_list_t waiting_supp_list; /**< List of waiting supplicants */
shared_comp_list_t shared_comp_list; /**< Shared component list */
@ -101,13 +109,20 @@ typedef struct {
const sec_prot_certs_t *certs; /**< Certificates */
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
sec_cfg_t *sec_cfg; /**< Security configuration */
frame_counters_t *frame_counters; /**< Frame counters */
uint64_t prev_system_time; /**< Previous system time */
uint64_t system_time_diff; /**< System time diffence */
uint32_t prev_frame_cnt; /**< Previous frame counter */
uint16_t prev_frame_cnt_timer; /**< Previous frame counter timer */
uint16_t supp_max_number; /**< Max number of stored supplicants */
uint16_t waiting_supp_list_size; /**< Waiting supplicants list size */
uint8_t relay_socked_msg_if_instance_id; /**< Relay socket message interface instance identifier */
uint8_t radius_socked_msg_if_instance_id; /**< Radius socket message interface instance identifier */
bool timer_running : 1; /**< Timer is running */
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */
bool gtk_new_act_time_exp : 1; /**< GTK new activation time expired */
bool prev_system_time_set : 1; /**< Previous system time set */
bool prev_frame_cnt_set : 1; /**< Previous frame counter set */
} pae_auth_t;
static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth, bool force_install);
@ -118,6 +133,8 @@ static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_pt
static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service);
static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data);
static void ws_pae_auth_tasklet_handler(arm_event_s *event);
static uint32_t ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth_t *pae_auth, uint8_t gtk_index, uint16_t seconds);
static uint32_t ws_pae_auth_lifetime_system_time_check(pae_auth_t *pae_auth, int8_t gtk_index, uint16_t seconds, uint32_t dec_extra_seconds);
static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth);
static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth);
static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp);
@ -145,9 +162,9 @@ static void ws_pae_auth_waiting_supp_deleted(void *pae_auth);
static int8_t tasklet_id = -1;
static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link);
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info, frame_counters_t *frame_counters)
{
if (!interface_ptr || !next_gtks || !certs || !sec_cfg || !sec_keys_nw_info) {
if (!interface_ptr || !next_gtks || !certs || !sec_cfg || !sec_keys_nw_info || !frame_counters) {
return -1;
}
@ -175,16 +192,24 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
pae_auth->nw_info_updated = NULL;
pae_auth->ip_addr_get = NULL;
pae_auth->congestion_get = NULL;
pae_auth->nw_frame_cnt_read = NULL;
pae_auth->next_gtks = next_gtks;
pae_auth->certs = certs;
pae_auth->sec_keys_nw_info = sec_keys_nw_info;
pae_auth->sec_cfg = sec_cfg;
pae_auth->frame_counters = frame_counters;
pae_auth->prev_system_time = 0;
pae_auth->system_time_diff = 0;
pae_auth->prev_frame_cnt = 0;
pae_auth->prev_frame_cnt_timer = FRAME_CNT_TIMER;
pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER;
pae_auth->waiting_supp_list_size = 0;
pae_auth->gtk_new_inst_req_exp = false;
pae_auth->gtk_new_act_time_exp = false;
pae_auth->prev_frame_cnt_set = false;
pae_auth->prev_system_time_set = false;
pae_auth->relay_socked_msg_if_instance_id = 0;
pae_auth->radius_socked_msg_if_instance_id = 0;
@ -316,7 +341,7 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr)
return 0;
}
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get)
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get, ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read)
{
if (!interface_ptr) {
return;
@ -333,6 +358,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
pae_auth->nw_info_updated = nw_info_updated;
pae_auth->ip_addr_get = ip_addr_get;
pae_auth->congestion_get = congestion_get;
pae_auth->nw_frame_cnt_read = nw_frame_cnt_read;
}
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
@ -364,6 +390,9 @@ void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
// Sets active key index
ws_pae_auth_network_key_index_set(pae_auth, index);
pae_auth->prev_system_time = ws_pae_current_time_get();
pae_auth->prev_system_time_set = true;
}
void ws_pae_auth_gtks_updated(protocol_interface_info_entry_t *interface_ptr)
@ -734,7 +763,12 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
if (!sec_prot_keys_gtk_is_set(pae_auth->sec_keys_nw_info->gtks, i)) {
continue;
}
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds, true);
uint32_t gtk_lifetime_dec_extra_seconds = 0;
if (active_index == i) {
gtk_lifetime_dec_extra_seconds = ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth, i, seconds);
gtk_lifetime_dec_extra_seconds = ws_pae_auth_lifetime_system_time_check(pae_auth, i, seconds, gtk_lifetime_dec_extra_seconds);
}
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds + gtk_lifetime_dec_extra_seconds, true);
if (active_index == i) {
if (!pae_auth->gtk_new_inst_req_exp) {
pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_cfg, timer_seconds);
@ -766,6 +800,10 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
pae_auth->nw_info_updated(pae_auth->interface_ptr);
}
}
if (gtk_lifetime_dec_extra_seconds != 0) {
// Update keys to NVM as needed
pae_auth->nw_info_updated(pae_auth->interface_ptr);
}
}
if (timer_seconds == 0) {
@ -786,6 +824,159 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
ws_pae_key_storage_timer(seconds);
}
static uint32_t ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth_t *pae_auth, uint8_t gtk_index, uint16_t seconds)
{
uint32_t decrement_seconds = 0;
if (pae_auth->prev_frame_cnt_timer > seconds) {
pae_auth->prev_frame_cnt_timer -= seconds;
return 0;
}
pae_auth->prev_frame_cnt_timer = FRAME_CNT_TIMER;
uint32_t frame_cnt = 0;
if (pae_auth->nw_frame_cnt_read(pae_auth->interface_ptr, &frame_cnt, gtk_index) < 0) {
return 0;
}
sec_timer_cfg_t *timer_cfg = &pae_auth->sec_cfg->timer_cfg;
// For GTK lifetime and frame counter space calculate the percent that has been used
uint32_t gtk_lifetime_left = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, gtk_index);
uint32_t gtk_lifetime = timer_cfg->gtk_expire_offset;
uint32_t gtk_lifetime_left_percent = gtk_lifetime_left * 100 / gtk_lifetime;
uint32_t frame_cnt_left_percent = ((uint64_t)((UINT32_MAX - frame_cnt))) * 100 / UINT32_MAX;
tr_info("Active GTK lifetime %"PRIu32", frame counter %"PRIu32" percent, counter %"PRIu32, gtk_lifetime_left_percent, frame_cnt_left_percent, frame_cnt);
/* If frame counter space has been exhausted faster than should be based on GTK lifetime
* decrements GTK lifetime. Do not check until 20% of the frame counter space has been used
* so that we have data from longer time period. As sanity check, validate that GTK lifetime
* is not more than 105% of the GTK lifetime.
*/
uint32_t gtk_new_install_req_seconds = timer_cfg->gtk_expire_offset - timer_cfg->gtk_new_install_req * timer_cfg->gtk_expire_offset / 100;
if ((frame_cnt_left_percent < gtk_lifetime_left_percent && frame_cnt_left_percent < 80) ||
gtk_lifetime_left_percent > 105) {
// If not yet on GTK update period
if (gtk_lifetime_left > (gtk_new_install_req_seconds + SECONDS_IN_DAY)) {
uint32_t diff = gtk_lifetime_left_percent - frame_cnt_left_percent;
decrement_seconds = gtk_lifetime * diff / 100 + SECONDS_IN_DAY;
if (decrement_seconds > gtk_lifetime_left - gtk_new_install_req_seconds) {
decrement_seconds = gtk_lifetime_left - gtk_new_install_req_seconds;
}
tr_info("Decrement GTK lifetime percent, seconds %"PRIu32, decrement_seconds);
}
}
// Calculate how much frame counters have changed and store maximum if larger than previous maximum
uint32_t frame_cnt_diff = 0;
if (pae_auth->prev_frame_cnt_set && frame_cnt > pae_auth->prev_frame_cnt) {
frame_cnt_diff = frame_cnt - pae_auth->prev_frame_cnt;
if (frame_cnt_diff > pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg) {
pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg = frame_cnt_diff;
}
}
tr_info("Frame counter change %"PRIu32", max %"PRIu32, frame_cnt_diff, pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg);
/* Calculates an estimate for how much free frame counter space is needed for the GTK update and
* initiates it faster if needed (default length of GTK update is 6 days).
*/
uint32_t max_needed_frame_counters =
pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg * gtk_new_install_req_seconds / 3600;
// Adds 20% to calculated value
max_needed_frame_counters = max_needed_frame_counters * 120 / 100;
// If estimated value is more than is left starts GTK update right away (if not already started)
if (max_needed_frame_counters >= (UINT32_MAX - frame_cnt)) {
if (gtk_lifetime_left > gtk_new_install_req_seconds) {
decrement_seconds = gtk_lifetime_left - gtk_new_install_req_seconds;
tr_info("Decrement GTK lifetime update, seconds %"PRIu32, decrement_seconds);
}
}
/* Calculates an estimate for how much free frame counter space is needed for the GTK activation and
* initiates it faster if needed (default length of GTK activation is 60 minutes).
*/
uint32_t gtk_new_activation_time_seconds = timer_cfg->gtk_expire_offset / timer_cfg->gtk_new_act_time;
// Calculates the estimated maximum value for frame counter during GTK update
max_needed_frame_counters =
pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg * gtk_new_activation_time_seconds / 3600;
// Adds 200% to calculated value
max_needed_frame_counters = max_needed_frame_counters * 300 / 100;
// If estimated value is more than is left starts GTK update right away (if not already started)
if (max_needed_frame_counters >= (UINT32_MAX - frame_cnt)) {
if (gtk_lifetime_left > gtk_new_activation_time_seconds) {
decrement_seconds = gtk_lifetime_left - gtk_new_activation_time_seconds;
tr_info("Decrement GTK lifetime activation, seconds %"PRIu32, decrement_seconds);
}
}
pae_auth->prev_frame_cnt = frame_cnt;
pae_auth->prev_frame_cnt_set = true;
return decrement_seconds;
}
static uint32_t ws_pae_auth_lifetime_system_time_check(pae_auth_t *pae_auth, int8_t gtk_index, uint16_t seconds, uint32_t dec_extra_seconds)
{
// Read current system time and compare it to previous time
uint64_t current_time = ws_pae_current_time_get();
if (pae_auth->prev_system_time_set) {
if (current_time > pae_auth->prev_system_time + TIME_MINIMUM_DIFFERENCE) {
pae_auth->system_time_diff += current_time - pae_auth->prev_system_time;
}
}
pae_auth->prev_system_time = current_time;
pae_auth->prev_system_time_set = true;
uint64_t time_diff = 0;
// Update lifetimes only if time difference is more than hour
if (pae_auth->system_time_diff > TIME_DIFFERENCE_THRESHOLD + seconds + dec_extra_seconds) {
time_diff = pae_auth->system_time_diff - seconds - dec_extra_seconds;
} else {
return dec_extra_seconds;
}
pae_auth->system_time_diff = 0;
uint32_t new_dec_extra_seconds = dec_extra_seconds;
if (time_diff > 0) {
/* If the system time has made a large jump then use the stored time to calculate the lifetime
(this implies e.g. that new time has been received from NTP and old time was not valid) */
if (!ws_pae_time_old_and_new_validate(current_time, current_time + time_diff)) {
// Allow one jump without invalidating active GTK
if (pae_auth->sec_keys_nw_info->system_time_changed == SYSTEM_TIME_NOT_CHANGED) {
pae_auth->sec_keys_nw_info->system_time_changed = SYSTEM_TIME_CHANGED;
tr_info("System time large change ignored; difference: %"PRIu64, time_diff);
time_diff = 0;
}
}
uint32_t gtk_lifetime_left = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, gtk_index);
sec_timer_cfg_t *timer_cfg = &pae_auth->sec_cfg->timer_cfg;
uint32_t gtk_new_activation_time_seconds = timer_cfg->gtk_expire_offset / timer_cfg->gtk_new_act_time;
// If there is GTK lifetime left
if (gtk_lifetime_left > (seconds + dec_extra_seconds + time_diff)) {
// If GTK lifetime would be less than new activation time sets decrements time to activation time
if (gtk_lifetime_left - seconds - dec_extra_seconds - time_diff < gtk_new_activation_time_seconds) {
new_dec_extra_seconds = gtk_lifetime_left - gtk_new_activation_time_seconds;
} else {
// Decrements GTK lifetime
new_dec_extra_seconds = dec_extra_seconds + time_diff;
}
} else {
// If there is no GTK lifetime left decrements time to activation time
new_dec_extra_seconds = gtk_lifetime_left - gtk_new_activation_time_seconds;
}
tr_info("System change difference: %"PRIu64" decrement extra: %"PRIu32" (seconds: %"PRIu16" previous extra %"PRIu32")", time_diff, new_dec_extra_seconds, seconds, dec_extra_seconds);
}
return new_dec_extra_seconds;
}
static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth)
{
// Gets index to install the key
@ -962,27 +1153,36 @@ static bool ws_pae_auth_active_limit_reached(uint16_t active_supp, pae_auth_t *p
return pae_auth->congestion_get(pae_auth->interface_ptr, active_supp);
}
static void ws_pae_auth_waiting_supp_remove_oldest(pae_auth_t *pae_auth, const kmp_addr_t *addr)
{
supp_entry_t *delete_supp = ns_list_get_last(&pae_auth->waiting_supp_list);
if (!delete_supp) {
return;
}
tr_info("PAE: waiting list full, eui-64: %s, deleted eui-64: %s", trace_array(addr->eui_64, 8), trace_array(delete_supp->addr.eui_64, 8));
// Create new instance
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, MSG_PROT, pae_auth->relay_socked_msg_if_instance_id, delete_supp, pae_auth->sec_cfg);
if (!new_kmp) {
return;
}
kmp_api_create_request(new_kmp, MSG_PROT, &delete_supp->addr, &delete_supp->sec_keys);
(void) ws_pae_lib_supp_list_remove(pae_auth, &pae_auth->waiting_supp_list, delete_supp, ws_pae_auth_waiting_supp_deleted);
}
static supp_entry_t *ws_pae_auth_waiting_supp_list_add(pae_auth_t *pae_auth, supp_entry_t *supp_entry, const kmp_addr_t *addr)
{
// Entry is already allocated
if (supp_entry) {
// If the waiting list if full removes the oldest entry from the list
if (pae_auth->waiting_supp_list_size >= WAITING_SUPPLICANT_LIST_MAX_SIZE) {
ws_pae_auth_waiting_supp_remove_oldest(pae_auth, addr);
}
ns_list_add_to_start(&pae_auth->waiting_supp_list, supp_entry);
pae_auth->waiting_supp_list_size++;
} else {
// If the waiting list if full removes the oldest entry from the list
if (pae_auth->waiting_supp_list_size >= WAITING_SUPPLICANT_LIST_MAX_SIZE) {
supp_entry_t *delete_supp = ns_list_get_last(&pae_auth->waiting_supp_list);
if (!delete_supp) {
return NULL;
}
tr_info("PAE: waiting list full, eui-64: %s, deleted eui-64: %s", trace_array(addr->eui_64, 8), trace_array(delete_supp->addr.eui_64, 8));
// Create new instance
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, MSG_PROT, pae_auth->relay_socked_msg_if_instance_id, delete_supp, pae_auth->sec_cfg);
if (!new_kmp) {
return NULL;
}
kmp_api_create_request(new_kmp, MSG_PROT, &delete_supp->addr, &delete_supp->sec_keys);
(void) ws_pae_lib_supp_list_remove(pae_auth, &pae_auth->waiting_supp_list, delete_supp, ws_pae_auth_waiting_supp_deleted);
ws_pae_auth_waiting_supp_remove_oldest(pae_auth, addr);
}
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->waiting_supp_list, addr);
if (!supp_entry) {

View File

@ -48,12 +48,13 @@
* \param timer_settings timer settings
* \param sec_cfg security configuration
* \param sec_keys_nw_info security keys network information
* \param frame_counters frame counters
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info, frame_counters_t *frame_counters);
/**
* ws_pae_auth_addresses_set set relay addresses
@ -260,6 +261,19 @@ typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_
*/
typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp);
/**
* ws_pae_auth_nw_frame_counter_read network frame counter read callback
*
* \param interface_ptr interface
* \param counter frame counter
* \param gtk_index GTK index
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t ws_pae_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index);
/**
* ws_pae_auth_cb_register register PAE authenticator callbacks
*
@ -270,17 +284,18 @@ typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interfa
* \param nw_info_updated network keys updated callback
* \param ip_addr_get IP addressing information callback
* \param congestion_get congestion get callback
* \param nw_frame_cnt_read network frame counter read callback
*
*/
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get);
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get, ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read);
#else
#define ws_pae_auth_init(interface_ptr, next_gtks, certs, sec_cfg, sec_keys_nw_info) 1
#define ws_pae_auth_init(interface_ptr, next_gtks, certs, sec_cfg, sec_keys_nw_info, frame_counters) 1
#define ws_pae_auth_timing_adjust(timing)
#define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1
#define ws_pae_auth_delete NULL
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get) {(void) hash_set;}
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get, nw_frame_cnt_read) {(void) hash_set;}
#define ws_pae_auth_start(interface_ptr)
#define ws_pae_auth_gtks_updated NULL
#define ws_pae_auth_nw_key_index_update NULL

View File

@ -26,6 +26,7 @@
#include "ws_management_api.h"
#include "ws_bbr_api.h"
#include "Service_Libs/utils/ns_file.h"
#include "Service_Libs/utils/ns_time.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_config.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
@ -51,7 +52,7 @@ typedef void ws_pae_timer(uint16_t ticks);
typedef int8_t ws_pae_br_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch);
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
typedef int8_t ws_pae_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated);
@ -119,6 +120,7 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr
#ifdef HAVE_PAE_AUTH
static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address);
static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp);
static int8_t ws_pae_controller_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index);
#endif
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
@ -140,8 +142,8 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters);
static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_counters, uint8_t index);
static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks);
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks);
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks);
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t stored_time, uint8_t time_changed);
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t current_time, uint8_t *time_changed);
static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
@ -196,7 +198,7 @@ int8_t ws_pae_controller_bootstrap_done(protocol_interface_info_entry_t *interfa
/* Trigger GTK hash update to supplicant, so it can check whether keys have been updated
during bootstrap. Does nothing if GTKs are up to date. */
ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash);
ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash, false);
#endif
return 0;
@ -239,7 +241,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
}
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get, ws_pae_controller_auth_congestion_get);
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get, ws_pae_controller_auth_congestion_get, ws_pae_controller_auth_nw_frame_counter_read);
controller->auth_started = true;
@ -376,7 +378,8 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr
if (arm_nwk_mac_address_read(interface_ptr->id, &mac_params) >= 0) {
memcpy(gtk_eui64, mac_params.mac_long, 8);
}
ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, controller->sec_keys_nw_info.gtks);
uint64_t system_time = ws_pae_current_time_get();
ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, controller->sec_keys_nw_info.gtks, system_time, controller->sec_keys_nw_info.system_time_changed);
controller->sec_keys_nw_info.updated = false;
sec_prot_keys_gtks_updated_reset(controller->sec_keys_nw_info.gtks);
}
@ -410,6 +413,21 @@ static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_
return controller->congestion_get(interface_ptr, active_supp);
}
static int8_t ws_pae_controller_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index)
{
if (!interface_ptr) {
return -1;
}
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
if (!controller) {
return -1;
}
controller->nw_frame_counter_read(interface_ptr, counter, gtk_index);
return 0;
}
#endif
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
@ -546,19 +564,31 @@ static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *n
mbedtls_sha256_init(&ctx);
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_starts(&ctx, 0) != 0) {
#else
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
#endif
ret_val = -1;
goto error;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_update(&ctx, input, network_name_len + GTK_LEN) != 0) {
#else
if (mbedtls_sha256_update_ret(&ctx, input, network_name_len + GTK_LEN) != 0) {
#endif
ret_val = -1;
goto error;
}
uint8_t output[32];
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_finish(&ctx, output) != 0) {
#else
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
#endif
ret_val = -1;
goto error;
}
@ -792,8 +822,8 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
// Read frame counters
if (ws_pae_controller_nvm_frame_counter_read(&controller->restart_cnt, &stored_time, &controller->sec_keys_nw_info.pan_version, &controller->frame_counters) >= 0) {
// Current time is not valid
if (ws_pae_current_time_set(stored_time) < 0) {
// Check if stored time is not valid
if (ws_pae_stored_time_check_and_set(stored_time) < 0) {
ret_value = -1;
}
// This is used to ensure that PMK replay counters are fresh after each re-start.
@ -837,16 +867,23 @@ static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_
memset(frame_counters->counter[index].gtk, 0, GTK_LEN);
frame_counters->counter[index].frame_counter = 0;
frame_counters->counter[index].stored_frame_counter = 0;
frame_counters->counter[index].max_frame_counter_chg = 0;
frame_counters->counter[index].set = false;
}
static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks)
{
uint8_t nvm_gtk_eui64[8];
if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, nvm_gtk_eui64, gtks) < 0) {
uint64_t system_time = ws_pae_current_time_get();
uint8_t system_time_changed = controller->sec_keys_nw_info.system_time_changed;
if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, nvm_gtk_eui64, gtks, system_time, &controller->sec_keys_nw_info.system_time_changed) < 0) {
// If no stored GTKs and network info (pan_id and network name) exits
return -1;
}
if (system_time_changed != controller->sec_keys_nw_info.system_time_changed) {
controller->sec_keys_nw_info.updated = true;
}
/* Get own EUI-64 and compare to the one read from the NVM. In case of mismatch delete GTKs and make
full authentication to update keys with new EUI-64 and in case of authenticator to update new
@ -867,21 +904,21 @@ static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_p
return 0;
}
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks)
static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t stored_time, uint8_t time_changed)
{
nw_info_nvm_tlv_t *tlv = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr);
if (!tlv) {
return -1;
}
ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtk_eui64, gtks);
ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtk_eui64, gtks, stored_time, time_changed);
ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, (nvm_tlv_t *) tlv);
return 0;
}
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks)
static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t current_time, uint8_t *time_changed)
{
nw_info_nvm_tlv_t *tlv_entry = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr);
if (!tlv_entry) {
@ -894,7 +931,7 @@ static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t
return -1;
}
if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtk_eui64, gtks) < 0) {
if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtk_eui64, gtks, current_time, time_changed) < 0) {
return -1;
}
@ -939,10 +976,13 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
return -1;
}
if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info) < 0) {
if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info, &controller->frame_counters) < 0) {
return -1;
}
// For Border Router enable the time acquired as default
ns_time_system_time_acquired_set();
controller->pae_delete = ws_pae_auth_delete;
controller->pae_fast_timer = ws_pae_auth_fast_timer;
controller->pae_slow_timer = ws_pae_auth_slow_timer;
@ -967,21 +1007,21 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
sec_prot_keys_gtks_updated_reset(&controller->gtks);
}
#endif
if (ws_pae_controller_nw_info_read(controller, read_gtks_to) >= 0) {
if (read_gtks_to && ws_pae_controller_nw_info_read(controller, read_gtks_to) >= 0) {
/* If network information i.e pan_id and network name exists updates bootstrap with it,
(in case already configured by application then no changes are made) */
if (controller->nw_info_updated) {
controller->nw_info_updated(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.pan_version, controller->sec_keys_nw_info.network_name);
}
if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) {
if (sec_prot_keys_gtk_count(read_gtks_to) == 0) {
// Key material invalid or GTKs are expired, delete GTKs from NVM
uint8_t gtk_eui64[8] = {0}; // Set GTK EUI-64 to zero
ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, NULL);
uint64_t system_time = ws_pae_current_time_get();
ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, NULL, system_time, controller->sec_keys_nw_info.system_time_changed);
}
}
ws_pae_key_storage_init();
if (read_gtks_to) {
ws_pae_key_storage_read(controller->restart_cnt);
} else {
@ -1662,7 +1702,7 @@ int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interf
memcpy(controller->gtkhash, gtkhash, 32);
if (controller->pae_gtk_hash_update) {
return controller->pae_gtk_hash_update(interface_ptr, controller->gtkhash);
return controller->pae_gtk_hash_update(interface_ptr, controller->gtkhash, true);
}
return 0;
@ -1731,9 +1771,12 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool
}
uint32_t frame_counter = entry->frame_counters.counter[i].frame_counter;
// If threshold check is disabled or frame counter has advanced for the threshold value, stores the new value
if (!use_threshold ||
frame_counter > entry->frame_counters.counter[i].stored_frame_counter + FRAME_COUNTER_STORE_THRESHOLD) {
/* If threshold check is disabled or frame counter has advanced for the threshold value, stores the new value.
If frame counter is at maximum at storage, do not initiate storing */
if (!use_threshold || (
(frame_counter > entry->frame_counters.counter[i].stored_frame_counter + FRAME_COUNTER_STORE_THRESHOLD) &&
!(entry->frame_counters.counter[i].stored_frame_counter == UINT32_MAX &&
frame_counter >= UINT32_MAX - FRAME_COUNTER_STORE_THRESHOLD))) {
entry->frame_counters.counter[i].stored_frame_counter = frame_counter;
update_needed = true;
tr_debug("Stored updated frame counter: index %i value %"PRIu32"", i, frame_counter);
@ -1761,8 +1804,9 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool
if (update_needed || entry->frame_cnt_store_force_timer == 0) {
tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
uint64_t system_time = ws_pae_current_time_get();
// Writes modified frame counters
ws_pae_nvm_store_frame_counter_tlv_create((frame_cnt_nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, entry->sec_keys_nw_info.pan_version, &entry->frame_counters);
ws_pae_nvm_store_frame_counter_tlv_create((frame_cnt_nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, entry->sec_keys_nw_info.pan_version, &entry->frame_counters, system_time);
ws_pae_controller_nvm_frame_counter_write((frame_cnt_nvm_tlv_t *) &entry->pae_nvm_buffer);
// Reset force interval when ever values are stored

View File

@ -944,7 +944,7 @@ static int8_t ws_pae_key_storage_array_time_update_entry(uint64_t time_differenc
#endif
}
if (storage_array_entry->pmk_lifetime_set) {
if (storage_array_entry->ptk_lifetime_set) {
#ifdef EXTRA_DEBUG_INFO
tr_debug("KeyS time update diff: %"PRIi64" PTK OLD t: %i %i eui64: %s", time_difference, STIME_TIME_GET(storage_array_entry->ptk_lifetime), STIME_FORMAT_GET(storage_array_entry->ptk_lifetime), tr_array(storage_array_entry->ptk_eui_64, 8));
#endif

View File

@ -40,34 +40,7 @@
#define PAE_NVM_FIELD_NOT_SET 0 // Field is not present
#define PAE_NVM_FIELD_SET 1 // Field is present
void ws_pae_nvm_store_generic_tlv_create(nvm_tlv_t *tlv_entry, uint16_t tag, uint16_t length)
{
tlv_entry->tag = tag;
tlv_entry->len = length;
}
nvm_tlv_t *ws_pae_nvm_store_generic_tlv_allocate_and_create(uint16_t tag, uint16_t length)
{
nvm_tlv_t *tlv_entry = ns_dyn_mem_alloc(length + sizeof(nvm_tlv_t));
if (!tlv_entry) {
return NULL;
}
tlv_entry->tag = tag;
tlv_entry->len = length;
return tlv_entry;
}
void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry)
{
if (!tlv_entry) {
return;
}
ns_dyn_mem_free(tlv_entry);
}
void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks)
void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t stored_time, uint8_t time_changed)
{
int len;
tlv_entry->tag = PAE_NVM_NW_INFO_TAG;
@ -90,13 +63,14 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
memcpy((char *)tlv, gtk_eui64, 8);
tlv += 8;
uint64_t current_time = ws_pae_current_time_get();
*tlv++ = time_changed;
tlv = common_write_64_bit(stored_time, tlv);
for (uint8_t i = 0; i < GTK_NUM; i++) {
if (gtks && sec_prot_keys_gtk_is_set(gtks, i)) {
*tlv++ = PAE_NVM_FIELD_SET; // GTK is set
uint64_t expirytime = sec_prot_keys_gtk_exptime_from_lifetime_get(gtks, i, current_time);
uint64_t expirytime = sec_prot_keys_gtk_exptime_from_lifetime_get(gtks, i, stored_time);
// Sets stored expiration time to GTKs; no need to update anymore to NVM if not changed
sec_prot_keys_gtk_expirytime_set(gtks, i, expirytime);
@ -118,11 +92,11 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
}
}
tr_debug("NVM NW_INFO write PAN ID %i name: %s", pan_id, nw_name);
tr_info("NVM NW_INFO write PAN ID: %i name: %s stored time: %"PRIu64, pan_id, nw_name, stored_time);
}
int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks)
int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t current_time, uint8_t *time_changed)
{
if (!tlv_entry || !pan_id || !nw_name) {
return -1;
@ -150,9 +124,20 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t
memcpy(gtk_eui64, (char *)tlv, 8);
tlv += 8;
uint64_t current_time = ws_pae_current_time_get();
*time_changed = *tlv++;
uint64_t stored_time = common_read_64_bit(tlv);
tlv += 8;
// Use either stored time or current time as reference when calculating lifetimes
current_time = ws_pae_time_old_or_new_select(stored_time, current_time);
/* If the selected time has made a large jump then use the stored time to calculate the lifetime
(this implies e.g. that new time has been received from NTP and old time was not valid) */
if (*time_changed == SYSTEM_TIME_NOT_CHANGED && !ws_pae_time_old_and_new_validate(stored_time, current_time)) {
*time_changed = SYSTEM_TIME_CHANGED;
current_time = stored_time;
tr_info("NVM NW_INFO system time change");
}
tr_debug("NVM NW_INFO current time: %"PRIi64, current_time);
tr_info("NVM NW_INFO current time: %"PRIi64" stored time: %"PRIi64, current_time, stored_time);
if (gtks && sec_prot_keys_gtk_count(gtks) == 0) {
// If application has not set GTKs read them from NVM
@ -160,9 +145,10 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t
if (*tlv++ == PAE_NVM_FIELD_SET) { /* GTK is set */
uint64_t expirytime = common_read_64_bit(tlv);
uint32_t lifetime = 0;
// Calculate lifetime
if (ws_pae_time_diff_calc(current_time, expirytime, &lifetime, true) < 0) {
tlv += 8 + 1 + 1 + GTK_LEN;
tr_debug("GTK index %i, expired expiry time: %"PRIi64", lifetime: %"PRIi32, i, expirytime, lifetime);
tr_info("GTK index %i, expired expiry time: %"PRIi64", lifetime: %"PRIi32, i, expirytime, lifetime);
continue;
}
tlv += 8;
@ -171,7 +157,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t
uint8_t install_order = *tlv++;
tr_debug("GTK index: %i, status: %i, install order %i, expiry time: %"PRIi64", lifetime: %"PRIi32, i, status, install_order, expirytime, lifetime);
tr_info("GTK index: %i, status: %i, install order %i, expiry time: %"PRIi64", lifetime: %"PRIi32, i, status, install_order, expirytime, lifetime);
sec_prot_keys_gtk_set(gtks, i, tlv, lifetime);
sec_prot_keys_gtk_expirytime_set(gtks, i, expirytime);
@ -185,7 +171,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t
sec_prot_keys_gtks_updated_reset(gtks);
}
tr_debug("NVM NW_INFO read PAN ID %i name: %s", *pan_id, nw_name);
tr_info("NVM NW_INFO read PAN ID %i name: %s", *pan_id, nw_name);
return 0;
}
@ -234,7 +220,7 @@ void ws_pae_nvm_store_keys_tlv_create(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t
}
tlv += PTK_LEN;
tr_debug("NVM KEYS write");
tr_info("NVM KEYS write");
}
int8_t ws_pae_nvm_store_keys_tlv_read(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys)
@ -282,12 +268,12 @@ int8_t ws_pae_nvm_store_keys_tlv_read(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t
sec_prot_keys_updated_reset(sec_keys);
tr_debug("NVM KEYS read");
tr_info("NVM KEYS read");
return 0;
}
void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters)
void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters, uint64_t stored_time)
{
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
@ -296,7 +282,6 @@ void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, u
tlv = common_write_32_bit(restart_cnt, tlv);
uint64_t stored_time = ws_pae_current_time_get();
tlv = common_write_64_bit(stored_time, tlv);
tlv = common_write_16_bit(pan_version, tlv);
@ -304,17 +289,18 @@ void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, u
for (uint8_t index = 0; index < GTK_NUM; index++) {
if (!counters->counter[index].set) {
*tlv++ = PAE_NVM_FIELD_NOT_SET;
memset(tlv, 0, GTK_LEN + 4);
tlv += GTK_LEN + 4;
memset(tlv, 0, GTK_LEN + 4 + 4);
tlv += GTK_LEN + 4 + 4;
continue;
}
*tlv++ = PAE_NVM_FIELD_SET;
memcpy(tlv, counters->counter[index].gtk, GTK_LEN);
tlv += GTK_LEN;
tlv = common_write_32_bit(counters->counter[index].frame_counter, tlv);
tlv = common_write_32_bit(counters->counter[index].max_frame_counter_chg, tlv);
}
tr_debug("NVM FRAME COUNTER write");
tr_info("NVM FRAME COUNTER write; stored time: %"PRIu64, stored_time);
}
int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters)
@ -342,7 +328,7 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, u
// Frame counter not set
if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
counters->counter[index].set = false;
tlv += GTK_LEN + 4;
tlv += GTK_LEN + 4 + 4;
continue;
}
// Frame counter is set, read GTK key and counter values
@ -351,9 +337,11 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, u
tlv += GTK_LEN;
counters->counter[index].frame_counter = common_read_32_bit(tlv);
tlv += 4;
counters->counter[index].max_frame_counter_chg = common_read_32_bit(tlv);
tlv += 4;
}
tr_debug("NVM FRAME COUNTER read");
tr_info("NVM FRAME COUNTER read; stored time: %"PRIu64, *stored_time);
return 0;
}
@ -367,7 +355,7 @@ void ws_pae_nvm_store_key_storage_index_tlv_create(nvm_tlv_t *tlv_entry, uint64_
tlv = common_write_64_bit(bitfield, tlv);
tr_debug("NVM KEY STORAGE INDEX write");
tr_info("NVM KEY STORAGE INDEX write");
}
int8_t ws_pae_nvm_store_key_storage_index_tlv_read(nvm_tlv_t *tlv_entry, uint64_t *bitfield)
@ -384,7 +372,7 @@ int8_t ws_pae_nvm_store_key_storage_index_tlv_read(nvm_tlv_t *tlv_entry, uint64_
*bitfield = common_read_64_bit(tlv);
tlv += 8;
tr_debug("NVM KEY STORAGE INDEX read");
tr_info("NVM KEY STORAGE INDEX read");
return 0;
}

View File

@ -35,16 +35,24 @@
#define PAE_NVM_KEY_STORAGE_INDEX_TAG 4
#define PAE_NVM_KEY_STORAGE_TAG 5
// pan_id (2) + network name (33) + GTK EUI-64 (own EUI-64) (8) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4
#define PAE_NVM_NW_INFO_LEN 2 + 33 + 8 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM
// pan_id (2) + network name (33) + GTK EUI-64 (own EUI-64) (8) + stored time (8) + time changed (1) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4
#define PAE_NVM_NW_INFO_LEN 2 + 33 + 8 + 8 + 1 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK lifetime (4) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK lifetime (4) + PTK (48)
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + 4 + PMK_LEN + 8 + 1 + 4 + PTK_LEN
// restart counter + stored time + pan version + (frame counter set (1) + GTK (16) + frame counter (4)) * 4
#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + 2 + (1 + GTK_LEN + 4) * GTK_NUM
// restart counter + stored time + pan version + (frame counter set (1) + GTK (16) + frame counter (4) + max frame counter change (4)) * 4
#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + 2 + (1 + GTK_LEN + 4 + 4) * GTK_NUM
#define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_NW_INFO_LEN
#if (PAE_NVM_NW_INFO_LEN >= PAE_NVM_KEYS_LEN) && (PAE_NVM_NW_INFO_LEN >= PAE_NVM_FRAME_COUNTER_LEN)
#define PAE_NVM_LARGEST_FILE PAE_NVM_NW_INFO_LEN
#elif (PAE_NVM_KEYS_LEN >= PAE_NVM_NW_INFO_LEN) && (PAE_NVM_KEYS_LEN >= PAE_NVM_FRAME_COUNTER_LEN)
#define PAE_NVM_LARGEST_FILE PAE_NVM_KEYS_LEN
#else
#define PAE_NVM_LARGEST_FILE PAE_NVM_FRAME_COUNTER_LEN
#endif
#define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_LARGEST_FILE
// key storage index bitfield (8)
#define PAE_NVM_KEY_STORAGE_INDEX_LEN 8
@ -91,11 +99,13 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry);
* \param pan_id PAN ID
* \param nw_name network name
* \param gtks GTK keys
* \param stored_time stored timestampt
* \param time_changed stored time has changed
*
* \return TLV entry or NULL
*
*/
void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks);
void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t stored_time, uint8_t time_changed);
/**
* ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV
@ -104,12 +114,14 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
* \param pan_id PAN ID
* \param nw_name network name
* \param gtks GTK keys
* \param current_time current timestampt
* \param time_changed stored time has changed
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks);
int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks, uint64_t current_time, uint8_t *time_changed);
/**
* ws_pae_nvm_store_keys_tlv_create create NVM keys TLV
@ -139,9 +151,10 @@ int8_t ws_pae_nvm_store_keys_tlv_read(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t
* \param restart_cnt re-start counter
* \param pan_version PAN version
* \param counters frame counters
* \param stored_time stored timestampt
*
*/
void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters);
void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters, uint64_t stored_time);
/**
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV

View File

@ -43,6 +43,33 @@ static int8_t ws_pae_nvm_store_create_path(char *fast_data_path, const char *fil
static int8_t ws_pae_nvm_store_write(const char *file_name, nvm_tlv_t *tlv);
static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_t *tlv);
void ws_pae_nvm_store_generic_tlv_create(nvm_tlv_t *tlv_entry, uint16_t tag, uint16_t length)
{
tlv_entry->tag = tag;
tlv_entry->len = length;
}
nvm_tlv_t *ws_pae_nvm_store_generic_tlv_allocate_and_create(uint16_t tag, uint16_t length)
{
nvm_tlv_t *tlv_entry = ns_dyn_mem_alloc(length + sizeof(nvm_tlv_t));
if (!tlv_entry) {
return NULL;
}
tlv_entry->tag = tag;
tlv_entry->len = length;
return tlv_entry;
}
void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry)
{
if (!tlv_entry) {
return;
}
ns_dyn_mem_free(tlv_entry);
}
int8_t ws_pae_nvm_store_tlv_file_write(const char *file, nvm_tlv_t *tlv)
{
if (!ws_pae_nvm_store_root_path_valid()) {

View File

@ -47,6 +47,38 @@ typedef struct {
// tag + length
#define NVM_TLV_FIXED_LEN sizeof(nvm_tlv_t)
/**
* ws_pae_nvm_store_generic_tlv_create create NVM generic storage TLV
*
* \param tlv_entry TLV entry
* \param tag tag
* \param length length of the (whole) entry
*
* \return < 0 failure
* \return >= 0 success
*
*/
void ws_pae_nvm_store_generic_tlv_create(nvm_tlv_t *tlv_entry, uint16_t tag, uint16_t length);
/**
* ws_pae_nvm_store_generic_tlv_allocate_and_create allocate and create NVM generic storage TLV
*
* \param tag tag
* \param length length of the (whole) entry
*
* \return TLV entry or NULL
*
*/
nvm_tlv_t *ws_pae_nvm_store_generic_tlv_allocate_and_create(uint16_t tag, uint16_t length);
/**
* ws_pae_nvm_store_generic_tlv_free free NVM generic storage TLV
*
* \param tlv_entry TLV entry
*
*/
void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry);
/**
* ws_pae_nvm_store_tlv_file_write write a list of TLVs to file
*

View File

@ -294,7 +294,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp)
}
// Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash);
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash, false);
if (mismatch != GTK_NO_MISMATCH) {
return -1;
}
@ -303,7 +303,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp)
return 0;
}
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch)
{
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) {
@ -311,7 +311,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
}
// Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash);
gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash, del_gtk_on_mismatch);
if (mismatch > GTK_NO_MISMATCH) {
tr_info("GTK hash update %s %s %s %s",
trace_array(&gtkhash[0], 8),

View File

@ -130,12 +130,13 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr,
*
* \param interface_ptr interface
* \param gtkhash GTK hash, 32 bytes
* \param del_gtk_on_mismatch Delete GTK in case of mismatch
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch);
/**
* ws_pae_supp_nw_key_index_update key index been updated (on PAN configuration)

View File

@ -34,7 +34,9 @@
// Wednesday, January 1, 2020 0:00:00 GMT
#define CURRENT_TIME_INIT_VALUE 1577836800
static uint64_t current_time = CURRENT_TIME_INIT_VALUE;
#define SECONDS_IN_WEEK (7 * 24 * 60 * 60)
static uint64_t ws_pae_current_time = CURRENT_TIME_INIT_VALUE;
uint16_t ws_pae_time_to_short_convert(uint32_t time)
{
@ -146,36 +148,76 @@ int8_t ws_pae_time_diff_calc(uint64_t curr_time, uint64_t comp_time, uint32_t *t
return 0;
}
uint64_t ws_pae_time_old_or_new_select(uint64_t old_time, uint64_t new_time)
{
// If current time is more than one week in the past use the stored time
if (old_time > SECONDS_IN_WEEK && new_time < old_time - SECONDS_IN_WEEK) {
return old_time;
}
return new_time;
}
bool ws_pae_time_old_and_new_validate(uint64_t old_time, uint64_t new_time)
{
/* If new time is more than one week in the past or more than a month in the
future the old time is not valid */
if ((old_time > SECONDS_IN_WEEK && new_time < old_time - SECONDS_IN_WEEK) ||
new_time > (old_time + SYSTEM_TIME_MAXIMUM_DIFF)) {
return false;
}
return true;
}
uint64_t ws_pae_current_time_get(void)
{
if (!ns_time_system_time_acquired_get()) {
return ws_pae_current_time;
}
uint64_t new_time;
if (ns_time_system_time_read(&new_time) == 0) {
new_time = ws_pae_time_old_or_new_select(ws_pae_current_time, new_time);
return new_time;
}
return current_time;
return ws_pae_current_time;
}
void ws_pae_current_time_update(uint16_t seconds)
{
current_time += seconds;
ws_pae_current_time += seconds;
}
int8_t ws_pae_current_time_set(uint64_t time)
int8_t ws_pae_stored_time_check_and_set(uint64_t stored_time)
{
uint64_t new_system_time;
current_time = time;
tr_debug("Current time set: %"PRIi64, time);
tr_debug("Stored time check and set: %"PRIi64, stored_time);
if (ns_time_system_time_read(&new_system_time) == 0) {
// System time has gone backwards
if (new_system_time < current_time || new_system_time > current_time + SYSTEM_TIME_MAXIMUM_DIFF) {
tr_error("FATAL: system time less than reference time or more than 12 months in future: %"PRIi64" reference time: %"PRIi64, new_system_time, current_time);
return -1;
}
if (!ns_time_system_time_acquired_get()) {
ws_pae_current_time = stored_time;
return stored_time;
}
if (ns_time_system_time_read(&new_system_time) == 0) {
// Use either stored time or current time as reference when calculating lifetimes
ws_pae_current_time = ws_pae_time_old_or_new_select(stored_time, new_system_time);
}
return 0;
}
int8_t ws_pae_current_time_check_and_set(uint64_t current_time)
{
uint64_t new_system_time;
tr_debug("Current time check and set: %"PRIi64, current_time);
if (ns_time_system_time_read(&new_system_time) == 0) {
// Use either stored time or current time as reference when calculating lifetimes
ws_pae_current_time = ws_pae_time_old_or_new_select(current_time, new_system_time);
}
return 0;
}

View File

@ -38,7 +38,7 @@ typedef enum {
#define STIME_TIME_GET(stime) (stime & STIME_TIME_MASK)
// Maximum difference in stored and indicated system time
#define SYSTEM_TIME_MAXIMUM_DIFF (60 * 60 * 24 * 30 * 12)
#define SYSTEM_TIME_MAXIMUM_DIFF (60 * 60 * 24 * 30) // One month
/**
* ws_pae_time_to_short_convert convert time to short format
@ -87,6 +87,28 @@ bool ws_pae_time_from_short_time_compare(uint16_t short_time1, uint16_t short_ti
*/
int8_t ws_pae_time_diff_calc(uint64_t curr_time, uint64_t comp_time, uint32_t *time_diff, bool future);
/**
* ws_pae_time_old_or_new_select selected old or new time (based on difference)
*
* \param old_time old time
* \param new_time new time
*
* \return old or new time
*
*/
uint64_t ws_pae_time_old_or_new_select(uint64_t old_time, uint64_t new_time);
/**
* ws_pae_time_old_and_new_validate validate old and new time (based on difference)
*
* \param old_time old time
* \param new_time new time
*
* \return TRUE old time is valid, FALSE old time is not valid
*
*/
bool ws_pae_time_old_and_new_validate(uint64_t old_time, uint64_t new_time);
/**
* ws_pae_current_time_get gets current time
*
@ -96,7 +118,7 @@ int8_t ws_pae_time_diff_calc(uint64_t curr_time, uint64_t comp_time, uint32_t *t
uint64_t ws_pae_current_time_get(void);
/**
* ws_pae_current_time_get updates current time
* ws_pae_current_time_update updates current time
*
* \param seconds seconds to be added to current time
*
@ -104,13 +126,13 @@ uint64_t ws_pae_current_time_get(void);
void ws_pae_current_time_update(uint16_t seconds);
/**
* ws_pae_current_time_set sets current time
* ws_pae_stored_time_check_and_set stored time check and set current time
*
* \param time new time
* \param stored_time stored time
*
* \return < 0 failure
* \return >= 0 success
*/
int8_t ws_pae_current_time_set(uint64_t time);
int8_t ws_pae_stored_time_check_and_set(uint64_t stored_time);
#endif /* WS_PAE_KEY_STORAGE_H_ */

View File

@ -0,0 +1,353 @@
/*
* Copyright (c) 2021, Pelion 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_trace.h"
#include "ws_management_api.h"
#ifdef HAVE_WS
#define TRACE_GROUP "wsph"
uint32_t ws_phy_decode_channel_spacing(uint8_t channel_spacing)
{
if (CHANNEL_SPACING_100 == channel_spacing) {
return 100000;
} else if (CHANNEL_SPACING_200 == channel_spacing) {
return 200000;
} else if (CHANNEL_SPACING_250 == channel_spacing) {
return 250000;
} else if (CHANNEL_SPACING_400 == channel_spacing) {
return 400000;
} else if (CHANNEL_SPACING_600 == channel_spacing) {
return 600000;
} else if (CHANNEL_SPACING_800 == channel_spacing) {
return 800000;
} else if (CHANNEL_SPACING_1200 == channel_spacing) {
return 1200000;
}
return 0;
}
uint32_t ws_phy_get_datarate_using_operating_mode(uint8_t operating_mode)
{
if ((OPERATING_MODE_1a == operating_mode) || (OPERATING_MODE_1b == operating_mode)) {
return 50000;
} else if ((OPERATING_MODE_2a == operating_mode) || (OPERATING_MODE_2b == operating_mode)) {
return 100000;
} else if (OPERATING_MODE_3 == operating_mode) {
return 150000;
} else if ((OPERATING_MODE_4a == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
return 200000;
} else if (OPERATING_MODE_5 == operating_mode) {
return 300000;
}
return 0;
}
uint8_t ws_phy_convert_operating_class_to_channel_plan_id(uint8_t operating_class, uint8_t regulatory_domain)
{
if (regulatory_domain == REG_DOMAIN_KR) {
} else if (regulatory_domain == REG_DOMAIN_EU) {
if ((operating_class == 1) || (operating_class == 2) || (operating_class == 3) || (operating_class == 4)) {
return operating_class + 31;
}
} else if (regulatory_domain == REG_DOMAIN_IN) {
} else if ((regulatory_domain == REG_DOMAIN_NA) || (regulatory_domain == REG_DOMAIN_BZ)) {
if ((operating_class == 1) || (operating_class == 2) || (operating_class == 3)) {
return operating_class;
}
} else if (regulatory_domain == REG_DOMAIN_JP) {
} else if (regulatory_domain == REG_DOMAIN_WW) {
}
return 0;
}
uint8_t ws_phy_convert_operating_mode_to_phy_mode_id(uint8_t operating_mode)
{
if (OPERATING_MODE_1a == operating_mode) {
return 1;
} else if (OPERATING_MODE_1b == operating_mode) {
return 2;
} else if (OPERATING_MODE_2a == operating_mode) {
return 3;
} else if (OPERATING_MODE_2b == operating_mode) {
return 4;
} else if (OPERATING_MODE_3 == operating_mode) {
return 5;
} else if (OPERATING_MODE_4a == operating_mode) {
return 6;
} else if (OPERATING_MODE_4b == operating_mode) {
return 7;
} else if (OPERATING_MODE_5 == operating_mode) {
return 8;
}
return 0;
}
uint32_t ws_phy_get_datarate_using_phy_mode_id(uint8_t phy_mode_id)
{
if (84 == phy_mode_id) {
return 150000;
} else if (85 == phy_mode_id) {
return 200000;
} else if ((68 == phy_mode_id) || (86 == phy_mode_id)) {
return 300000;
} else if ((34 == phy_mode_id) || (51 == phy_mode_id) || (69 == phy_mode_id)) {
return 400000;
} else if ((52 == phy_mode_id) || (70 == phy_mode_id)) {
return 600000;
} else if ((35 == phy_mode_id) || (53 == phy_mode_id)) {
return 800000;
} else if ((36 == phy_mode_id) || (54 == phy_mode_id)) {
return 1200000;
} else if (37 == phy_mode_id) {
return 1600000;
} else if (38 == phy_mode_id) {
return 2400000;
} else if ((1 == phy_mode_id) || (2 == phy_mode_id) || (17 == phy_mode_id) || (18 == phy_mode_id)) {
return 50000;
} else if ((3 == phy_mode_id) || (4 == phy_mode_id) || (19 == phy_mode_id) || (20 == phy_mode_id)) {
return 100000;
} else if ((5 == phy_mode_id) || (21 == phy_mode_id)) {
return 150000;
} else if ((6 == phy_mode_id) || (7 == phy_mode_id) || (22 == phy_mode_id) || (23 == phy_mode_id)) {
return 200000;
} else if ((8 == phy_mode_id) || (24 == phy_mode_id)) {
return 300000;
}
return 0;
}
uint8_t ws_phy_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id)
{
if ((phy_mode_id >= 34) && (phy_mode_id <= 38)) {
return OFDM_OPTION_1;
} else if ((phy_mode_id >= 51) && (phy_mode_id <= 54)) {
return OFDM_OPTION_2;
} else if ((phy_mode_id >= 68) && (phy_mode_id <= 70)) {
return OFDM_OPTION_3;
} else if ((phy_mode_id >= 84) && (phy_mode_id <= 86)) {
return OFDM_OPTION_4;
}
return 0;
}
uint8_t ws_phy_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id)
{
if (34 == phy_mode_id) {
return OFDM_MCS_2;
} else if ((35 == phy_mode_id) || (51 == phy_mode_id)) {
return OFDM_MCS_3;
} else if ((36 == phy_mode_id) || (52 == phy_mode_id) || (68 == phy_mode_id) || (84 == phy_mode_id)) {
return OFDM_MCS_4;
} else if ((37 == phy_mode_id) || (53 == phy_mode_id) || (69 == phy_mode_id) || (85 == phy_mode_id)) {
return OFDM_MCS_5;
} else if ((38 == phy_mode_id) || (54 == phy_mode_id) || (70 == phy_mode_id) || (86 == phy_mode_id)) {
return OFDM_MCS_6;
}
return 0;
}
uint8_t ws_phy_get_channel_plan_id_using_phy_mode_id(uint8_t phy_mode_id, uint8_t regulatory_domain, uint8_t base_channel_plan_id)
{
if (regulatory_domain == REG_DOMAIN_KR) {
} else if (regulatory_domain == REG_DOMAIN_EU) {
// As on EU domain the PHY mode ID cannot unambiguously define the used channel plan id, use the one which best matches to the base channel plan id
if ((base_channel_plan_id == 32) || (base_channel_plan_id == 33)) {
if ((phy_mode_id == 1) || (phy_mode_id == 17)) {
return 32;
} else if ((phy_mode_id == 3) || (phy_mode_id == 5) || (phy_mode_id == 19) || (phy_mode_id == 21) || ((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return 33;
}
} else if ((base_channel_plan_id == 36) || (base_channel_plan_id == 37)) {
if ((phy_mode_id == 1) || (phy_mode_id == 17)) {
return 36;
} else if ((phy_mode_id == 3) || (phy_mode_id == 5) || (phy_mode_id == 19) || (phy_mode_id == 21) || ((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return 37;
}
} else if ((base_channel_plan_id == 34) || (base_channel_plan_id == 35)) {
if ((phy_mode_id == 1) || (phy_mode_id == 17)) {
return 34;
} else if ((phy_mode_id == 3) || (phy_mode_id == 5) || (phy_mode_id == 19) || (phy_mode_id == 21) || ((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return 35;
}
}
} else if (regulatory_domain == REG_DOMAIN_IN) {
} else if ((regulatory_domain == REG_DOMAIN_NA) || (regulatory_domain == REG_DOMAIN_BZ)) {
if ((phy_mode_id == 2) || (phy_mode_id == 3) || (phy_mode_id == 18) || (phy_mode_id == 19) || ((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return 1;
} else if ((phy_mode_id == 5) || (phy_mode_id == 6) || (phy_mode_id == 21) || (phy_mode_id == 22) || ((phy_mode_id >= 68) && (phy_mode_id <= 70))) {
return 2;
} else if ((phy_mode_id == 8) || (phy_mode_id == 24)) {
return 3;
} else if ((phy_mode_id >= 51) && (phy_mode_id <= 54)) {
return 4;
} else if ((phy_mode_id >= 34) && (phy_mode_id <= 38)) {
return 5;
}
} else if (regulatory_domain == REG_DOMAIN_JP) {
} else if (regulatory_domain == REG_DOMAIN_WW) {
}
return 0;
}
uint16_t ws_phy_get_number_of_channels_using_channel_plan_id(uint8_t channel_plan_id)
{
if (channel_plan_id == 1) {
return 129;
} else if (channel_plan_id == 2) {
return 64;
} else if (channel_plan_id == 3) {
return 42;
} else if (channel_plan_id == 4) {
return 32;
} else if (channel_plan_id == 5) {
return 21;
} else if (channel_plan_id == 32) {
return 69;
} else if (channel_plan_id == 33) {
return 35;
} else if (channel_plan_id == 34) {
return 55;
} else if (channel_plan_id == 35) {
return 27;
} else if (channel_plan_id == 36) {
return 125;
} else if (channel_plan_id == 37) {
return 62;
}
return 0;
}
uint32_t ws_phy_get_channel_spacing_using_channel_plan_id(uint8_t channel_plan_id)
{
if (channel_plan_id == 1) {
return 200000;
} else if (channel_plan_id == 2) {
return 400000;
} else if (channel_plan_id == 3) {
return 600000;
} else if (channel_plan_id == 4) {
return 800000;
} else if (channel_plan_id == 5) {
return 1200000;
} else if (channel_plan_id == 32) {
return 100000;
} else if (channel_plan_id == 33) {
return 200000;
} else if (channel_plan_id == 34) {
return 100000;
} else if (channel_plan_id == 35) {
return 200000;
} else if (channel_plan_id == 36) {
return 100000;
} else if (channel_plan_id == 37) {
return 200000;
}
return 0;
}
uint32_t ws_phy_get_channel_0_frequency_using_channel_plan_id(uint8_t channel_plan_id)
{
if (channel_plan_id == 1) {
return 902200000;
} else if (channel_plan_id == 2) {
return 902400000;
} else if (channel_plan_id == 3) {
return 902600000;
} else if (channel_plan_id == 4) {
return 902800000;
} else if (channel_plan_id == 5) {
return 903200000;
} else if (channel_plan_id == 32) {
return 863100000;
} else if (channel_plan_id == 33) {
return 863100000;
} else if (channel_plan_id == 34) {
return 870100000;
} else if (channel_plan_id == 35) {
return 870200000;
} else if (channel_plan_id == 36) {
return 863100000;
} else if (channel_plan_id == 37) {
return 863100000;
}
return 0;
}
bool ws_phy_get_fsk_fec_enabled_using_phy_mode_id(uint8_t phy_mode_id)
{
if ((phy_mode_id >= 17) && (phy_mode_id <= 24)) {
return true;
}
return false;
}
phy_modulation_e ws_phy_get_modulation_using_phy_mode_id(uint8_t phy_mode_id)
{
if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) ||
((phy_mode_id >= 51) && (phy_mode_id <= 54)) ||
((phy_mode_id >= 68) && (phy_mode_id <= 70)) ||
((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
return M_OFDM;
} else if (((phy_mode_id >= 1) && (phy_mode_id <= 8)) || ((phy_mode_id >= 17) && (phy_mode_id <= 24))) {
return M_2FSK;
} else {
return M_UNDEFINED;
}
}
phy_modulation_index_e ws_phy_get_modulation_index_using_phy_mode_id(uint8_t phy_mode_id)
{
if (ws_phy_get_modulation_using_phy_mode_id(phy_mode_id) != M_2FSK) {
return MODULATION_INDEX_UNDEFINED;
}
if ((2 == phy_mode_id) || (18 == phy_mode_id) ||
(4 == phy_mode_id) || (20 == phy_mode_id) ||
(7 == phy_mode_id) || (23 == phy_mode_id)) {
return MODULATION_INDEX_1_0;
}
return MODULATION_INDEX_0_5;
}
phy_modulation_index_e ws_phy_get_modulation_index_using_operating_mode(uint8_t operating_mode)
{
if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
return MODULATION_INDEX_1_0;
} else {
return MODULATION_INDEX_0_5;
}
}
#endif //HAVE_WS

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef WS_PHY_H_
#define WS_PHY_H_
uint32_t ws_phy_decode_channel_spacing(uint8_t channel_spacing);
uint32_t ws_phy_get_datarate_using_operating_mode(uint8_t operating_mode);
uint8_t ws_phy_convert_operating_class_to_channel_plan_id(uint8_t operating_class, uint8_t regulatory_domain);
uint8_t ws_phy_convert_operating_mode_to_phy_mode_id(uint8_t operating_mode);
uint8_t ws_phy_get_channel_plan_id_using_phy_mode_id(uint8_t phy_mode_id, uint8_t regulatory_domain, uint8_t base_channel_plan_id);
uint32_t ws_phy_get_datarate_using_phy_mode_id(uint8_t phy_mode_id);
uint8_t ws_phy_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id);
uint8_t ws_phy_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id);
uint16_t ws_phy_get_number_of_channels_using_channel_plan_id(uint8_t channel_plan_id);
uint32_t ws_phy_get_channel_spacing_using_channel_plan_id(uint8_t channel_plan_id);
uint32_t ws_phy_get_channel_0_frequency_using_channel_plan_id(uint8_t channel_plan_id);
bool ws_phy_get_fsk_fec_enabled_using_phy_mode_id(uint8_t phy_mode_id);
phy_modulation_e ws_phy_get_modulation_using_phy_mode_id(uint8_t phy_mode_id);
phy_modulation_index_e ws_phy_get_modulation_index_using_phy_mode_id(uint8_t phy_mode_id);
phy_modulation_index_e ws_phy_get_modulation_index_using_operating_mode(uint8_t operating_mode);
#endif //WS_PHY_H_

View File

@ -21,6 +21,7 @@
#include "ns_list.h"
#include "nsdynmemLIB.h"
#include "net_ws_test.h"
#include "net_ws_test_ext.h"
#include "fhss_config.h"
#include "ws_management_api.h"
#include "mac_api.h"
@ -32,6 +33,7 @@
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/ws/ws_cfg_settings.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "randLIB.h"
#include "ns_trace.h"
@ -41,6 +43,25 @@
#ifdef HAVE_WS
int ws_test_version_set(int8_t interface_id, uint8_t version)
{
test_pan_version = version;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur) {
if (!ws_info(cur)) {
return -1;
}
cur->ws_info->version = version;
if (ws_version_1_0(cur)) {
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
} else if (ws_version_1_1(cur)) {
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_1;
}
}
return 0;
}
int ws_test_pan_size_set(int8_t interface_id, uint16_t pan_size)
{
@ -88,7 +109,7 @@ int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_
}
ws_sec_timer_cfg_t cfg;
if (ws_cfg_sec_timer_get(&cfg, NULL) < 0) {
if (ws_cfg_sec_timer_get(&cfg) < 0) {
return -2;
}
@ -102,7 +123,7 @@ int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_
cfg.ptk_lifetime = ptk_lifetime;
}
if (ws_cfg_sec_timer_set(cur, NULL, &cfg, NULL) < 0) {
if (ws_cfg_sec_timer_set(cur, &cfg, 0x00) < 0) {
return -3;
}
@ -119,7 +140,7 @@ int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_
}
ws_sec_timer_cfg_t cfg;
if (ws_cfg_sec_timer_get(&cfg, NULL) < 0) {
if (ws_cfg_sec_timer_get(&cfg) < 0) {
return -2;
}
@ -136,7 +157,7 @@ int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_
cfg.gtk_max_mismatch = max_mismatch;
}
if (ws_cfg_sec_timer_set(cur, NULL, &cfg, NULL) < 0) {
if (ws_cfg_sec_timer_set(cur, &cfg, 0x00) < 0) {
return -3;
}
@ -177,4 +198,27 @@ int ws_test_neighbour_temporary_lifetime_set(int8_t interface_id, uint32_t tempo
return 0;
}
int ws_test_procedure_trigger(int8_t interface_id, ws_test_proc_t procedure, void *parameters)
{
(void) parameters;
protocol_interface_info_entry_t *cur = NULL;;
if (interface_id > 0) {
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !ws_info(cur)) {
return -1;
}
} else {
cur = protocol_stack_interface_info_get_wisun_mesh();
if (!cur) {
if (procedure != PROC_AUTO_ON && procedure != PROC_AUTO_OFF) {
return -1;
}
}
}
return ws_bootstrap_test_procedure_trigger(cur, procedure);
}
#endif // HAVE_WS

View File

@ -114,7 +114,7 @@ void nd_border_router_setup_refresh(nwk_interface_id id, bool fresh_abro)
nd_router_object->life_time = nd_configure->life_time;
if (!ns_list_is_empty(&nd_router_object->prefix_list)) {
tr_debug("Release Prefix\n");
tr_debug("Release Prefix");
icmpv6_prefix_list_free(&nd_router_object->prefix_list);
}

View File

@ -371,7 +371,7 @@ void addr_policy_table_print(void)
ns_list_foreach(addr_policy_table_entry_t, entry, &addr_policy_table) {
char addr[40];
ip6tos(entry->prefix, addr);
tr_debug("%3d %3d %s/%u\n", entry->precedence, entry->label, addr, entry->prefix_len);
tr_debug("%3d %3d %s/%u", entry->precedence, entry->label, addr, entry->prefix_len);
}
}

View File

@ -834,12 +834,12 @@ void socket_list_print(route_print_fn_t *print_fn, char sep)
/* Chuck in a consistency check */
for (int i = 0; i < SOCKETS_MAX; i++) {
if (socket_instance[i] && socket_instance[i]->id != i) {
tr_err("ID %d points to %p with id %d\n", i, (void *)socket_instance[i], socket_instance[i]->id);
tr_err("ID %d points to %p with id %d", i, (void *)socket_instance[i], socket_instance[i]->id);
}
}
ns_list_foreach(socket_t, socket, &socket_list) {
if (socket->id != -1 && socket_pointer_get(socket->id) != socket) {
tr_err("Socket %p has invalid ID %d\n", (void *)socket, socket->id);
tr_err("Socket %p has invalid ID %d", (void *)socket, socket->id);
}
sockbuf_check(&socket->rcvq);
sockbuf_check(&socket->sndq);

View File

@ -212,7 +212,7 @@ void dhcp_client_delete(int8_t interface)
do {
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
if (srv_data_ptr != NULL) {
tr_debug("Free DHCPv6 Client\n");
tr_debug("Free DHCPv6 Client");
memcpy(temporary_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, 16);
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);

View File

@ -137,7 +137,7 @@ int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8
return -1;
}
}
tr_debug("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
tr_info("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
return 0;
}

View File

@ -96,6 +96,7 @@ typedef struct mac_pre_build_frame {
uint8_t cca_request_restart_cnt;
uint8_t tx_request_restart_cnt;
uint8_t priority;
uint8_t phy_mode_id;
uint32_t blacklist_start_time_us;
uint16_t blacklist_period_ms;
uint16_t initial_tx_channel;

View File

@ -43,7 +43,8 @@ typedef enum mac_event_t {
MAC_ACK_SECURITY_FAIL,
MAC_UNKNOWN_DESTINATION,
MAC_TX_PRECOND_FAIL,
MAC_RETURN_TO_QUEUE
MAC_RETURN_TO_QUEUE,
MAC_MODE_SWITCH_TIMEOUT
} mac_event_t;
typedef enum mac_tx_status_type_t {
@ -95,11 +96,21 @@ typedef enum arm_nwk_mlme_event_type {
ARM_NWK_MAC_MLME_INDIRECT_DATA_POLL_AFTER_DATA = 5,
} arm_nwk_mlme_event_type_e;
typedef enum mac_mode_switch_states {
MAC_MS_IDLE = 0,
MAC_MS_PHR_SEND_READY,
MAC_MS_DATA_SEND_READY,
MAC_MS_PHR_RECEIVED,
MAC_MS_DATA_RECEIVED,
MAC_MS_TIMEOUT
} mac_mode_switch_states_e;
#define ENHANCED_ACK_MAX_LENGTH 255
typedef struct dev_driver_tx_buffer {
uint8_t *buf;
uint8_t *enhanced_ack_buf;
uint8_t mode_switch_phr_buf[2];
uint16_t ack_len;
uint16_t len;
unsigned priority: 2;
@ -180,6 +191,7 @@ typedef struct protocol_interface_rf_mac_setup {
bool mac_ack_tx_active: 1;
bool mac_edfe_tx_active: 1;
bool mac_edfe_response_tx_active: 1;
bool mac_mode_switch_phr_tx_active: 1;
bool mac_frame_pending: 1;
/* MAC Capability Information */
bool macCapRxOnIdle: 1;
@ -228,6 +240,8 @@ typedef struct protocol_interface_rf_mac_setup {
uint8_t mac_channel;
uint8_t mac_tx_start_channel;
uint8_t base_phy_mode;
mac_mode_switch_states_e mode_switch_state;
//uint8_t cca_failure;
/* MAC TX Queue */

View File

@ -48,6 +48,7 @@
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
#include "MAC/IEEE802_15_4/mac_indirect_data.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#include "MAC/IEEE802_15_4/mac_mode_switch.h"
#include "MAC/rf_driver_storage.h"
#include "sw_mac.h"
@ -156,7 +157,7 @@ void mcps_sap_data_req_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup,
{
mcps_data_req_ie_list_t ie_list;
memset(&ie_list, 0, sizeof(mcps_data_req_ie_list_t));
mcps_sap_data_req_handler_ext(rf_mac_setup, data_req, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY);
mcps_sap_data_req_handler_ext(rf_mac_setup, data_req, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY, 0);
}
static bool mac_ie_vector_length_validate(ns_ie_iovec_t *ie_vector, uint16_t iov_length, uint16_t *length_out)
@ -195,8 +196,9 @@ static bool mac_ie_vector_length_validate(ns_ie_iovec_t *ie_vector, uint16_t iov
}
void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_data_req_t *data_req, const mcps_data_req_ie_list_t *ie_list, const channel_list_s *asynch_channel_list, mac_data_priority_t priority)
void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_data_req_t *data_req, const mcps_data_req_ie_list_t *ie_list, const channel_list_s *asynch_channel_list, mac_data_priority_t priority, uint8_t phy_mode_id)
{
(void) phy_mode_id;
uint8_t status = MLME_SUCCESS;
mac_pre_build_frame_t *buffer = NULL;
@ -292,6 +294,7 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
buffer->fcf_dsn.frametype = FC_DATA_FRAME;
buffer->ExtendedFrameExchange = data_req->ExtendedFrameExchange;
buffer->WaitResponse = data_req->TxAckReq;
buffer->phy_mode_id = phy_mode_id;
if (data_req->ExtendedFrameExchange) {
buffer->fcf_dsn.ackRequested = false;
} else {
@ -1106,6 +1109,10 @@ static void mac_mcps_asynch_finish(protocol_interface_rf_mac_setup_s *rf_mac_set
static bool mcps_sap_check_buffer_timeout(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{
// Timestamp is not implemented by virtual RF driver. Do not check buffer age.
if (rf_mac_setup->dev_driver->phy_driver->arm_net_virtual_tx_cb) {
return false;
}
// Convert from 1us slots to seconds
uint32_t buffer_age_s = (mac_mcps_sap_get_phy_timestamp(rf_mac_setup) - buffer->request_start_time_us) / 1000000;
// Do not timeout broadcast frames. Broadcast interval could be very long.
@ -1834,6 +1841,12 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
mac_security_authentication_data_params_set(&ccm_ptr, mhr_start, (buffer->mac_header_length_with_security + open_payload));
ccm_process_run(&ccm_ptr);
}
// Packet is sent using mode switch. Build mode switch PHR
if (buffer->phy_mode_id) {
if (mac_build_mode_switch_phr(rf_ptr, tx_buf->mode_switch_phr_buf, buffer->phy_mode_id)) {
return -1;
}
}
return 0;
}
@ -2083,6 +2096,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
phy_csma_params_t csma_params;
csma_params.backoff_time = 0;
csma_params.cca_enabled = false;
csma_params.mode_switch_phr = false;
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
if (rf_ptr->active_pd_data_request) {
timer_mac_stop(rf_ptr);
@ -2197,8 +2211,10 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
rf_ptr->mac_edfe_tx_active = true;
}
} else if (buffer->phy_mode_id) {
rf_ptr->mac_mode_switch_phr_tx_active = true;
cca_enabled = true;
} else {
if (rf_ptr->mac_ack_tx_active) {
mac_csma_backoff_start(rf_ptr);
platform_exit_critical();
@ -2209,13 +2225,13 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
}
// Use double CCA check with FHSS for data packets only
if (rf_ptr->fhss_api && !rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active && !rf_ptr->active_pd_data_request->asynch_request) {
if (rf_ptr->fhss_api && !rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active && !rf_ptr->active_pd_data_request->asynch_request && !rf_ptr->mac_mode_switch_phr_tx_active) {
if ((buffer->tx_time - (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1))) > mac_mcps_sap_get_phy_timestamp(rf_ptr)) {
buffer->csma_periods_left = rf_ptr->number_of_csma_ca_periods - 1;
buffer->tx_time -= (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1));
}
}
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled);
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled, rf_ptr->mac_mode_switch_phr_tx_active);
if (mac_plme_cca_req(rf_ptr) != 0) {
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK || (buffer->ExtendedFrameExchange && rf_ptr->mac_edfe_response_tx_active)) {
//ACK or EFDE Response

View File

@ -123,7 +123,7 @@ int8_t mac_virtual_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *messa
void mcps_sap_data_req_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_data_req_s *data_req);
void mcps_sap_data_req_handler_ext(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_data_req_s *data_req, const struct mcps_data_req_ie_list *ie_list, const channel_list_s *asynch_channel_list, mac_data_priority_t priority);
void mcps_sap_data_req_handler_ext(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_data_req_s *data_req, const struct mcps_data_req_ie_list *ie_list, const channel_list_s *asynch_channel_list, mac_data_priority_t priority, uint8_t phy_mode_id);
void mac_mcps_trig_buffer_from_queue(struct protocol_interface_rf_mac_setup *rf_mac_setup);

View File

@ -826,7 +826,7 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
case macCCAThreshold:
pu8 = (uint8_t *) set_req->value_pointer;
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CCA_THRESHOLD, pu8);
tr_debug("Set CCA threshold to %u%%", *pu8);
tr_info("Set CCA threshold to %u%%", *pu8);
return 0;
case macMultiCSMAParameters:
return mac_mlme_set_multi_csma_parameters(rf_mac_setup, set_req);

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2021, Pelion 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_trace.h"
#include "common_functions.h"
#include "mac_api.h"
#include "MAC/IEEE802_15_4/sw_mac_internal.h"
#include "MAC/IEEE802_15_4/mac_defines.h"
#include "MAC/IEEE802_15_4/mac_mode_switch.h"
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_timer.h"
#include "MAC/rf_driver_storage.h"
#define TRACE_GROUP "mswc"
static uint8_t mac_calculate_mode_switch_parity(uint16_t mode_switch_phr)
{
uint8_t counter = 0;
// Calculate number of 1-bits in (15-bit) input and return modulo-2 of the sum
for (int i = 0; i < 15; i++) {
if (mode_switch_phr & (1 << i)) {
counter++;
}
}
return counter % 2;
}
/*
* 11-bit input must be padded with 4 leading zeroes.
* Reverse the 15-bit result and divide with polynomial X + X + 1 -> 10011
* Return remainder as checksum
*
* Example:
* Input: xxxxx01000000001
* Padded input: x000001000000001
* Reversed and padded input: 100000000100000x
* Calculated checksum: 0x0f (00001111)
*
* Division:
*
* 10011010101 <- Result
* -----------------
* 10011 | 100000000100000 <- Highest bit (10000) is 1, add 1 in result
* 10011 <- 10011 * 1
* -----
* 00110 <- Highest bit (00110) is 0, add 0 in result
* 00000 <- 10011 * 0
* -----
* .
* .
* .
* -----
* 11100
* 10011
* ----
* 1111 <- Remainder
*
*/
static uint8_t mac_calculate_mode_switch_checksum(uint16_t mode_switch_phr)
{
// X⁴ + X + 1 -> 0b10011 -> 0x13
uint8_t polynomial = 0x13;
// Pad input with four leading zeroes
mode_switch_phr &= ~0x7800;
// Reverse input
uint16_t phr_reversed = 0;
for (int i = 0; i < 16; i++) {
if (mode_switch_phr & (1 << i)) {
phr_reversed |= 1 << (15 - i);
}
}
// Divide 15-bit padded and reversed input, use polynomial 10011 as the divider
uint8_t shift = 11;
uint8_t remainder = phr_reversed >> shift;
for (int i = 0; i < 11; i++) {
// Check highest bit
if (remainder & (1 << 4)) {
remainder ^= polynomial;
} else {
remainder ^= 0;
}
// Division ready, return remainder as checksum
if (!(--shift)) {
return remainder;
}
remainder <<= 1;
if (phr_reversed & (1 << shift)) {
remainder |= 1;
}
}
// Shouldn't go here
return 0;
}
/*
* Mode switch PHR format:
*
* | 0 | 1-2 | 3-10 | 11-14 | 15 |
* |Mode Switch|Reserved|New Phy Mode ID|Checksum|Parity|
*
*/
int8_t mac_build_mode_switch_phr(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t *data_ptr, uint8_t phy_mode_id)
{
(void) rf_ptr;
if (!data_ptr) {
return -1;
}
// - Write mode switch and PHY mode id fields
uint16_t mode_switch_phr = 1 << SHIFT_MODE_SWITCH;
mode_switch_phr |= phy_mode_id << SHIFT_MODE_SWITCH_PHY_MODE;
// - Calculate checksum
mode_switch_phr |= mac_calculate_mode_switch_checksum(mode_switch_phr) << SHIFT_MODE_SWITCH_CHECKSUM;
// - Calculate parity
mode_switch_phr |= mac_calculate_mode_switch_parity(mode_switch_phr) << SHIFT_MODE_SWITCH_PARITY;
common_write_16_bit_inverse(mode_switch_phr, data_ptr);
// - With successful return value, MAC should start CSMA-CA for a mode switch PHR
return 0;
}
static int8_t mac_change_mode_switch_configuration(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t phy_mode_id, mac_mode_switch_states_e new_state)
{
mac_api_t *mac_api = get_sw_mac_api(rf_ptr);
if (mac_api->mode_resolver_cb) {
phy_rf_channel_configuration_s rf_config;
memset(&rf_config, 0, sizeof(phy_rf_channel_configuration_s));
if (!mac_api->mode_resolver_cb(mac_api, phy_mode_id, &rf_config)) {
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) &rf_config);
rf_ptr->mode_switch_state = new_state;
return 0;
} else {
tr_error("Mode switch could not resolve PHY mode ID %u", phy_mode_id);
}
}
return -1;
}
static uint32_t mac_calculate_timeout(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t phy_mode_id)
{
mac_api_t *mac_api = get_sw_mac_api(rf_ptr);
if (mac_api->mode_resolver_cb) {
phy_rf_channel_configuration_s rf_config;
memset(&rf_config, 0, sizeof(phy_rf_channel_configuration_s));
if (!mac_api->mode_resolver_cb(mac_api, phy_mode_id, &rf_config)) {
// Calculate transmission time of max size packet + Ack size + max settling time + Tack
return ((uint64_t)(1200 + 100) * 8000000 / rf_config.datarate + 1500 + 5000);
}
}
// If could not resolve configuration, use 300ms as default timeout
return 300000;
}
int8_t mac_parse_mode_switch_phr(protocol_interface_rf_mac_setup_s *rf_ptr, const uint8_t *data_ptr, uint16_t data_len)
{
if (data_len != PHR_LEN) {
return -1;
}
if (!data_ptr) {
return -1;
}
uint16_t mode_switch_phr = common_read_16_bit_inverse(data_ptr);
if (!(mode_switch_phr & MASK_MODE_SWITCH)) {
// Mode switch not enabled
return -1;
}
// - Validate checksum
if (mac_calculate_mode_switch_checksum(mode_switch_phr) != ((mode_switch_phr & MASK_MODE_SWITCH_CHECKSUM) >> SHIFT_MODE_SWITCH_CHECKSUM)) {
// Invalid checksum, TODO: error correction
return -1;
}
// - Validate parity
if (mac_calculate_mode_switch_parity(mode_switch_phr) != (mode_switch_phr & MASK_MODE_SWITCH_PARITY) >> SHIFT_MODE_SWITCH_PARITY) {
// Invalid parity
return -1;
}
// - Read PHY mode id
uint8_t phy_mode_id = (mode_switch_phr & MASK_MODE_SWITCH_PHY_MODE) >> SHIFT_MODE_SWITCH_PHY_MODE;
// When mode switch PHR was received, change new configuration here to wait data packet and set mode switch state machine to 'PHR received'
if (mac_change_mode_switch_configuration(rf_ptr, phy_mode_id, MAC_MS_PHR_RECEIVED)) {
return -1;
}
// Backup timer, if reception of data packet fails
timer_mac_start(rf_ptr, MAC_MODE_SWITCH_TIMEOUT, mac_calculate_timeout(rf_ptr, phy_mode_id) / 50);
return 0;
}
int8_t mac_update_mode_switch_state(protocol_interface_rf_mac_setup_s *rf_ptr, mac_mode_switch_states_e state, uint8_t phy_mode_id)
{
switch (state) {
case MAC_MS_PHR_SEND_READY:
// When mode switch PHR was sent, change new configuration here before transmitting data packet and set mode switch state machine to 'PHR send ready'
if (!mac_change_mode_switch_configuration(rf_ptr, phy_mode_id, MAC_MS_PHR_SEND_READY)) {
return 0;
}
break;
case MAC_MS_DATA_SEND_READY:
// When data packet was sent, switch back to base configuration and set mode switch state machine to 'idle'
if ((rf_ptr->mode_switch_state == MAC_MS_PHR_SEND_READY) && !mac_change_mode_switch_configuration(rf_ptr, phy_mode_id, MAC_MS_IDLE)) {
return 0;
}
break;
case MAC_MS_DATA_RECEIVED:
// When packet was received in new configuration, switch back to base configuration and set mode switch state machine to 'idle'
if ((rf_ptr->mode_switch_state == MAC_MS_PHR_RECEIVED) && !mac_change_mode_switch_configuration(rf_ptr, phy_mode_id, MAC_MS_IDLE)) {
// Packet was received, stop backup timer to not cause timeout event
timer_mac_stop(rf_ptr);
return 0;
}
break;
case MAC_MS_TIMEOUT:
// When reception timeout occurs, switch back to base configuration and set mode switch state machine to 'idle'
if ((rf_ptr->mode_switch_state == MAC_MS_PHR_RECEIVED) && !mac_change_mode_switch_configuration(rf_ptr, phy_mode_id, MAC_MS_IDLE)) {
return 0;
}
break;
default:
break;
}
return -1;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#ifndef MAC_MODE_SWITCH_H_
#define MAC_MODE_SWITCH_H_
#define PHR_LEN 2
#define SHIFT_MODE_SWITCH_PARITY (15)
#define SHIFT_MODE_SWITCH_CHECKSUM (11)
#define SHIFT_MODE_SWITCH_PHY_MODE (3)
#define SHIFT_MODE_SWITCH (0)
#define MASK_MODE_SWITCH_PARITY (0x8000)
#define MASK_MODE_SWITCH_CHECKSUM (0x7800)
#define MASK_MODE_SWITCH_PHY_MODE (0x07F8)
#define MASK_MODE_SWITCH (0x0001)
/**
* @brief Build mode switch PHR.
* @param rf_ptr Pointer to MAC instance.
* @param data_ptr Pointer to data buffer.
* @param phy_mode_id Used PHY mode id.
* @return 0 - success, -1 - failure.
*/
int8_t mac_build_mode_switch_phr(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t *data_ptr, uint8_t phy_mode_id);
/**
* @brief Parse mode switch PHR.
* @param rf_ptr Pointer to MAC instance.
* @param data_ptr Pointer to data buffer.
* @param data_len Data length.
* @return 0 - mode switch PHR found, -1 - mode switch PHR not found.
*/
int8_t mac_parse_mode_switch_phr(protocol_interface_rf_mac_setup_s *rf_ptr, const uint8_t *data_ptr, uint16_t data_len);
/**
* @brief Update mode switch state.
* @param rf_ptr Pointer to MAC instance.
*/
int8_t mac_update_mode_switch_state(protocol_interface_rf_mac_setup_s *rf_ptr, mac_mode_switch_states_e state, uint8_t phy_mode_id);
#endif /* MAC_MODE_SWITCH_H_ */

View File

@ -35,6 +35,7 @@
#include "MAC/IEEE802_15_4/mac_filter.h"
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
#include "MAC/IEEE802_15_4/mac_mode_switch.h"
#include "MAC/rf_driver_storage.h"
#include "Core/include/ns_monitor.h"
#include "ns_trace.h"
@ -49,6 +50,10 @@
// MAC should learn and make this dynamic by sending first few packets with predefined CSMA period.
#define MIN_FHSS_CSMA_PERIOD_US 5000
// Add extra CSMA-CA delay for packets using mode switch. The delay between mode switch PHR and data packet equals to MDR_SETTLING_TIME_US
// Must be between 510 and 1500 us
#define MDR_SETTLING_TIME_US 510
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr, uint16_t failed_channel);
@ -106,6 +111,9 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
backoff_in_us = 1;
}
if (rf_mac_setup->fhss_api) {
if (rf_mac_setup->active_pd_data_request->phy_mode_id) {
backoff_in_us += MDR_SETTLING_TIME_US;
}
// Synchronization error when backoff time is shorter than allowed.
// TODO: Make this dynamic.
if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) {
@ -184,6 +192,9 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
if (rf_mac_setup->mac_ack_tx_active || (rf_mac_setup->mac_edfe_tx_active && rf_mac_setup->mac_edfe_response_tx_active)) {
buffer = tx_buf->enhanced_ack_buf;
length = tx_buf->ack_len;
} else if (rf_mac_setup->mac_mode_switch_phr_tx_active) {
buffer = tx_buf->mode_switch_phr_buf;
length = sizeof(tx_buf->mode_switch_phr_buf);
} else {
buffer = tx_buf->buf;
length = tx_buf->len;
@ -232,6 +243,7 @@ void mac_pd_abort_active_tx(protocol_interface_rf_mac_setup_s *rf_mac_setup)
phy_csma_params_t csma_params;
// Set TX time to 0 to abort current transmission
csma_params.backoff_time = 0;
csma_params.mode_switch_phr = false;
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
}
@ -242,8 +254,12 @@ void mac_pd_abort_active_tx(protocol_interface_rf_mac_setup_s *rf_mac_setup)
* \param tx_time TX timestamp to be set.
*
*/
void mac_pd_sap_set_phy_tx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint32_t tx_time, bool cca_enabled)
void mac_pd_sap_set_phy_tx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint32_t tx_time, bool cca_enabled, bool mode_switch)
{
// Given tx_time is for the actual data packet. Mode switch PHR must be sent with the offset of MDR settling time.
if (mode_switch) {
tx_time -= MDR_SETTLING_TIME_US;
}
// With TX time set to zero, PHY sends immediately
if (!tx_time) {
tx_time++;
@ -251,6 +267,7 @@ void mac_pd_sap_set_phy_tx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup,
phy_csma_params_t csma_params;
csma_params.backoff_time = tx_time;
csma_params.cca_enabled = cca_enabled;
csma_params.mode_switch_phr = mode_switch;
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
}
@ -300,7 +317,7 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
cca_enabled = true;
}
mac_pd_sap_set_phy_tx_time(rf_mac_setup, active_buf->tx_time, cca_enabled);
mac_pd_sap_set_phy_tx_time(rf_mac_setup, active_buf->tx_time, cca_enabled, rf_mac_setup->mac_mode_switch_phr_tx_active);
if (active_buf->fcf_dsn.frametype == FC_BEACON_FRAME) {
// FHSS synchronization info is written in the end of transmitted (Beacon) buffer
dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer;
@ -335,6 +352,10 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
} else if (rf_mac_setup->mac_tx_result == MAC_TIMER_ACK) {
mac_data_interface_tx_done_cb(rf_mac_setup, PHY_LINK_TX_FAIL, 0, 0);
}
} else {
if (rf_mac_setup->mac_tx_result == MAC_MODE_SWITCH_TIMEOUT) {
mac_update_mode_switch_state(rf_mac_setup, MAC_MS_TIMEOUT, rf_mac_setup->base_phy_mode);
}
}
}
@ -424,6 +445,7 @@ static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf
static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
{
rf_ptr->mac_ack_tx_active = false;
mac_update_mode_switch_state(rf_ptr, MAC_MS_DATA_RECEIVED, rf_ptr->base_phy_mode);
if (rf_ptr->fhss_api) {
//SET tx completed false because ack isnot never queued
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff);
@ -449,7 +471,6 @@ int8_t mac_data_edfe_force_stop(protocol_interface_rf_mac_setup_s *rf_ptr)
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
{
if (!rf_ptr->macRfRadioTxActive) {
return -1;
}
@ -513,7 +534,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
if (active_buf->csma_periods_left > 0) {
active_buf->csma_periods_left--;
active_buf->tx_time += rf_ptr->multi_cca_interval;
mac_pd_sap_set_phy_tx_time(rf_ptr, active_buf->tx_time, true);
mac_pd_sap_set_phy_tx_time(rf_ptr, active_buf->tx_time, true, false);
#ifdef TIMING_TOOL_TRACES
tr_info("%u CSMA_start", mac_mcps_sap_get_phy_timestamp(rf_ptr));
#endif
@ -555,6 +576,23 @@ VALIDATE_TX_TIME:
mac_data_ack_tx_finish(rf_ptr);
return 0;
}
} else if (rf_ptr->mac_mode_switch_phr_tx_active) {
#ifdef TIMING_TOOL_TRACES
tr_info("%u TX_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
#endif
rf_ptr->mac_mode_switch_phr_tx_active = false;
if (rf_ptr->fhss_api) {
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle);
}
if (!mac_update_mode_switch_state(rf_ptr, MAC_MS_PHR_SEND_READY, rf_ptr->active_pd_data_request->phy_mode_id)) {
mac_pd_sap_set_phy_tx_time(rf_ptr, rf_ptr->active_pd_data_request->tx_time, true, rf_ptr->mac_mode_switch_phr_tx_active);
if (mac_plme_cca_req(rf_ptr) != 0) {
mac_sap_no_ack_cb(rf_ptr);
}
return 0;
}
// Failed to start data transmission after mode switch PHR was sent
status = PHY_LINK_TX_FAIL;
}
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
@ -580,7 +618,7 @@ VALIDATE_TX_TIME:
timer_mac_stop(rf_ptr);
}
uint16_t failed_channel = rf_ptr->mac_channel;
if (rf_ptr->fhss_api && rf_ptr->active_pd_data_request->asynch_request == false) {
if (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request == false) {
/* waiting_ack == false allows FHSS to change back to RX channel after transmission
* tx_completed == true allows FHSS to delete stored failure handles
*/
@ -610,7 +648,12 @@ VALIDATE_TX_TIME:
waiting_ack = false;
tx_completed = true;
}
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, waiting_ack, tx_completed, rf_ptr->active_pd_data_request->msduHandle);
if (waiting_ack == false) {
mac_update_mode_switch_state(rf_ptr, MAC_MS_DATA_SEND_READY, rf_ptr->base_phy_mode);
}
if (rf_ptr->fhss_api) {
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, waiting_ack, tx_completed, rf_ptr->active_pd_data_request->msduHandle);
}
}
switch (status) {
@ -674,7 +717,7 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set
if (mcps_sap_pd_ack(rf_ptr, buf) != 0) {
mcps_sap_pre_parsed_frame_buffer_free(buf);
}
mac_update_mode_switch_state(rf_ptr, MAC_MS_DATA_SEND_READY, rf_ptr->base_phy_mode);
if (rf_ptr->fhss_api) {
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle);
}
@ -1040,19 +1083,27 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
goto ERROR_HANDLER;
}
if (pd_data_ind->data_len < 3) {
return -1;
}
#ifdef TIMING_TOOL_TRACES
tr_info("%u RX_start", mac_pd_sap_get_phy_rx_time(rf_ptr));
tr_info("%u RX_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
#endif
if (!mac_parse_mode_switch_phr(rf_ptr, pd_data_ind->data_ptr, pd_data_ind->data_len)) {
// TODO: mode switch returned 0, needs some logic to wait frame with new mode
goto ERROR_HANDLER;
}
if (pd_data_ind->data_len < 3) {
return -1;
}
mac_cca_threshold_event_send(rf_ptr, rf_ptr->mac_channel, pd_data_ind->dbm);
mac_fcf_sequence_t fcf_read;
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
// No need to send Ack - Check if RX channel needs to be updated
if (fcf_read.ackRequested == false) {
mac_update_mode_switch_state(rf_ptr, MAC_MS_DATA_RECEIVED, rf_ptr->base_phy_mode);
if (rf_ptr->fhss_api) {
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0);
}

View File

@ -43,7 +43,7 @@ int8_t mac_plme_cca_req(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mac_pd_abort_active_tx(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mac_pd_sap_set_phy_tx_time(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint32_t tx_time, bool cca_enabled);
void mac_pd_sap_set_phy_tx_time(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint32_t tx_time, bool cca_enabled, bool mode_switch);
void mac_pd_sap_rf_low_level_function_set(void *mac_ptr, void *driver);

View File

@ -23,7 +23,7 @@
#include "MAC/IEEE802_15_4/mac_pd_sap.h"
#include "MAC/IEEE802_15_4/mac_timer.h"
#include "sw_mac.h"
#define TRACE_GROUP "mTim"
/*-------------------MAC TIMER FUNCTIONS--------------------------*/

View File

@ -55,10 +55,11 @@ static int8_t ns_sw_mac_initialize(mac_api_t *api, mcps_data_confirm *mcps_data_
mlme_confirm *mlme_conf_callback, mlme_indication *mlme_ind_callback, int8_t parent_id);
static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication_ext *data_ind_cb, mcps_data_confirm_ext *data_cnf_cb, mcps_ack_data_req_ext *ack_data_req_cb);
static int8_t ns_sw_mac_api_enable_edfe_ext(mac_api_t *api, mcps_edfe_handler *edfe_ind_cb);
static int8_t ns_sw_mac_api_mode_switch_resolver_set(mac_api_t *api, mode_switch_resolver *mode_resolver_cb, uint8_t base_phy_mode);
static void mlme_req(const mac_api_t *api, mlme_primitive id, const void *data);
static void mcps_req(const mac_api_t *api, const mcps_data_req_t *data);
static void mcps_req_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list, mac_data_priority_t priority);
static void mcps_req_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list, mac_data_priority_t priority, uint8_t phy_mode_id);
static uint8_t purge_req(const mac_api_t *api, const mcps_purge_t *data);
static int8_t macext_mac64_address_set(const mac_api_t *api, const uint8_t *mac64);
static int8_t macext_mac64_address_get(const mac_api_t *api, mac_extended_address_type type, uint8_t *mac64_buf);
@ -130,6 +131,7 @@ mac_api_t *ns_sw_mac_create(int8_t rf_driver_id, mac_description_storage_size_t
this->mac_initialize = &ns_sw_mac_initialize;
this->mac_mcps_extension_enable = &ns_sw_mac_api_enable_mcps_ext;
this->mac_mcps_edfe_enable = &ns_sw_mac_api_enable_edfe_ext;
this->mac_mode_switch_resolver_set = &ns_sw_mac_api_mode_switch_resolver_set;
this->mlme_req = &mlme_req;
this->mcps_data_req = &mcps_req;
this->mcps_data_req_ext = &mcps_req_ext;
@ -344,6 +346,19 @@ static int8_t ns_sw_mac_api_enable_edfe_ext(mac_api_t *api, mcps_edfe_handler *e
return 0;
}
static int8_t ns_sw_mac_api_mode_switch_resolver_set(mac_api_t *api, mode_switch_resolver *mode_resolver_cb, uint8_t base_phy_mode)
{
if (api != mac_store.mac_api) {
return -1;
}
if (!mac_store.setup->mac_extension_enabled) {
return -1;
}
mac_store.setup->base_phy_mode = base_phy_mode;
mac_store.mac_api->mode_resolver_cb = mode_resolver_cb;
return 0;
}
mac_api_t *get_sw_mac_api(protocol_interface_rf_mac_setup_s *setup)
{
if (!mac_store.mac_api || mac_store.mac_api->parent_id == -1 || mac_store.setup != setup) {
@ -582,15 +597,15 @@ static void mcps_req(const mac_api_t *api, const mcps_data_req_t *data)
/* Call direct new API but without IE extensions */
mcps_data_req_ie_list_t ie_list;
memset(&ie_list, 0, sizeof(mcps_data_req_ie_list_t));
mcps_sap_data_req_handler_ext(mac_store.setup, data, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY);
mcps_sap_data_req_handler_ext(mac_store.setup, data, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY, 0);
}
}
static void mcps_req_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list, mac_data_priority_t priority)
static void mcps_req_ext(const mac_api_t *api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list, mac_data_priority_t priority, uint8_t phy_mode_id)
{
//TODO: Populate linked list when present
if (mac_store.mac_api == api) {
mcps_sap_data_req_handler_ext(mac_store.setup, data, ie_ext, asynch_channel_list, priority);
mcps_sap_data_req_handler_ext(mac_store.setup, data, ie_ext, asynch_channel_list, priority, phy_mode_id);
}
}

View File

@ -501,7 +501,7 @@ static void mpl_buffer_transmit(mpl_domain_t *domain, mpl_buffered_message_t *me
memcpy(buf->src_sa.address, message->message + IPV6_HDROFF_SRC_ADDR, 16);
ipv6_transmit_multicast_on_interface(buf, domain->interface);
tr_debug("MPL transmit %u", mpl_buffer_sequence(message));
tr_info("MPL transmit %u", mpl_buffer_sequence(message));
}
static void mpl_buffer_inconsistent(const mpl_domain_t *domain, mpl_buffered_message_t *message)

View File

@ -45,5 +45,6 @@ protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_id(int8_t
protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_bootstrap_id(int8_t id);
protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_rpl_domain(const struct rpl_domain *domain, int8_t last_id);
protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_fhss_api(const struct fhss_api *fhss_api);
protocol_interface_info_entry_t *protocol_stack_interface_info_get_wisun_mesh(void);
#endif /* NWK_INTERFACE_INCLUDE_PROTOCOL_ABSTRACT_H_ */

View File

@ -65,7 +65,6 @@
#include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_routing.h"
#include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_common.h"
#ifdef HAVE_WS
#include "6LoWPAN/ws/ws_pae_controller.h"
@ -806,6 +805,18 @@ protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_fhss_api(c
return NULL;
}
protocol_interface_info_entry_t *protocol_stack_interface_info_get_wisun_mesh(void)
{
#ifdef HAVE_WS
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
if (cur->ws_info) {
return cur;
}
}
#endif //HAVE_WS
return NULL;
}
protocol_interface_info_entry_t *protocol_stack_interface_sleep_possibility(void)
{
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
@ -1148,7 +1159,7 @@ void net_bootsrap_cb_run(uint8_t event)
if (thread_info(cur)) {
thread_bootstrap_state_machine(cur);
} else if (ws_info(cur)) {
ws_bootstrap_state_machine(cur);
ws_common_state_machine(cur);
} else {
protocol_6lowpan_bootstrap(cur);
}

View File

@ -70,7 +70,7 @@ void protocol_timer_start(protocol_timer_id_t id, void (*passed_fptr)(uint16_t),
protocol_timer[id].fptr = passed_fptr;
platform_exit_critical();
} else {
tr_debug("Do Not use Null pointer for fptr!!!\n");
tr_debug("Do Not use Null pointer for fptr!!!");
}
}

View File

@ -1549,6 +1549,20 @@ static buffer_t *rpl_control_dis_handler(protocol_interface_info_entry_t *cur, r
return buffer_free(buf);
}
void rpl_control_transmit_dio_trigger(protocol_interface_info_entry_t *cur, struct rpl_domain *domain)
{
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
rpl_instance_dio_trigger(instance, cur, NULL);
}
}
void rpl_control_parent_selection_trigger(struct rpl_domain *domain)
{
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
rpl_instance_run_parent_selection(instance);
}
}
void rpl_control_transmit_dis(rpl_domain_t *domain, protocol_interface_info_entry_t *cur, uint8_t pred, uint8_t instance_id, const uint8_t *dodagid, const uint8_t version, const uint8_t *dst)
{
uint16_t length = 2;

View File

@ -133,6 +133,11 @@ struct buffer *rpl_control_source_route_error_handler(struct buffer *buf, struct
/* Manually send DIS packets for bootstrap */
void rpl_control_transmit_dis(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, uint8_t pred, uint8_t instance_id, const uint8_t *dodagid, const uint8_t version, const uint8_t *dst);
/* Manually send DIO packets for bootstrap */
void rpl_control_transmit_dio_trigger(struct protocol_interface_info_entry *cur, struct rpl_domain *domain);
/* Manually trigger RPL parent selection */
void rpl_control_parent_selection_trigger(struct rpl_domain *domain);
bool rpl_control_have_dodag(struct rpl_domain *domain);
/* APIs used to manipulate configuration at the root */

View File

@ -786,19 +786,31 @@ static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8
mbedtls_sha256_init(&ctx);
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_starts(&ctx, 0) != 0) {
#else
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
#endif
ret_val = -1;
goto error;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_update(&ctx, hashed_string, 24) != 0) {
#else
if (mbedtls_sha256_update_ret(&ctx, hashed_string, 24) != 0) {
#endif
ret_val = -1;
goto error;
}
uint8_t output[32];
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_finish(&ctx, output) != 0) {
#else
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
#endif
ret_val = -1;
goto error;
}
@ -872,19 +884,35 @@ static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *pro
mbedtls_md5_init(&ctx);
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_starts(&ctx) != 0) {
#else
if (mbedtls_md5_starts_ret(&ctx) != 0) {
#endif
goto end;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, msg_ptr, msg_len) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, msg_ptr, msg_len) != 0) {
#endif
goto end;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, key, key_len) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, key, key_len) != 0) {
#endif
goto end;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_finish(&ctx, auth_ptr) != 0) {
#else
if (mbedtls_md5_finish_ret(&ctx, auth_ptr) != 0) {
#endif
goto end;
}
@ -940,35 +968,59 @@ static int8_t radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(sec_prot_t *pr
while (cipher_text_len >= MS_MPPE_RECV_KEY_BLOCK_LEN) {
mbedtls_md5_init(&ctx);
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_starts(&ctx) != 0) {
#else
if (mbedtls_md5_starts_ret(&ctx) != 0) {
#endif
md5_failed = true;
break;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, key, key_len) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, key, key_len) != 0) {
#endif
md5_failed = true;
break;
}
if (first_interm_b_value) {
// b(1) = MD5(secret + request-authenticator + salt)
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, request_authenticator, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, request_authenticator, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
#endif
md5_failed = true;
break;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, salt_ptr, MS_MPPE_RECV_KEY_SALT_LEN) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, salt_ptr, MS_MPPE_RECV_KEY_SALT_LEN) != 0) {
#endif
md5_failed = true;
break;
}
} else {
// b(i) = MD5(secret + cipher_text(i - 1))
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_update(&ctx, cipher_text_ptr - MS_MPPE_RECV_KEY_BLOCK_LEN, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
#else
if (mbedtls_md5_update_ret(&ctx, cipher_text_ptr - MS_MPPE_RECV_KEY_BLOCK_LEN, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
#endif
md5_failed = true;
break;
}
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_md5_finish(&ctx, interm_b_val) != 0) {
#else
if (mbedtls_md5_finish_ret(&ctx, interm_b_val) != 0) {
#endif
md5_failed = true;
break;
}

View File

@ -507,7 +507,7 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index
return gtks->gtk[index].lifetime;
}
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable)
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint32_t seconds, bool gtk_update_enable)
{
if (gtks->gtk[index].lifetime > seconds) {
gtks->gtk[index].lifetime -= seconds;
@ -527,6 +527,7 @@ uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t
// If timestamps differ for more than 5 minutes marks field as updated (and stores to NVM)
if (diff > 300 && gtk_update_enable) {
gtks->updated = true;
sec_prot_keys_gtk_expirytime_set(gtks, index, expirytime);
}
return gtks->gtk[index].lifetime;
@ -716,7 +717,7 @@ int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk)
return 0;
}
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash, bool del_gtk_on_mismatch)
{
uint8_t *gtk_hash_ptr = gtkhash;
@ -729,11 +730,15 @@ gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t
uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
if (lifetime > GTK_EXPIRE_MISMATCH_TIME) {
tr_info("GTK mismatch %i expired time, lifetime: %"PRIu32"", i, lifetime);
if (mismatch < GTK_LIFETIME_MISMATCH) {
// Only indicate mismatch in case fresh hash is received
if (mismatch < GTK_LIFETIME_MISMATCH && del_gtk_on_mismatch) {
mismatch = GTK_LIFETIME_MISMATCH;
}
}
sec_prot_keys_gtk_clear(gtks, i);
// Only delete in case fresh hash is received
if (del_gtk_on_mismatch) {
sec_prot_keys_gtk_clear(gtks, i);
}
}
} else {
// Check is hash matches to existing key
@ -759,7 +764,10 @@ gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t
if (mismatch < GTK_HASH_MISMATCH) {
mismatch = GTK_HASH_MISMATCH;
}
sec_prot_keys_gtk_clear(gtks, i);
// Only delete in case fresh hash is received
if (del_gtk_on_mismatch) {
sec_prot_keys_gtk_clear(gtks, i);
}
}
}
}

View File

@ -62,6 +62,10 @@
#define SEC_MAXIMUM_LIFETIME (60 * 60 * 24 * 30 * 24) // Maximum life time for PMK, PTK, GTKs etc. is two years
// System time changed
#define SYSTEM_TIME_NOT_CHANGED 0
#define SYSTEM_TIME_CHANGED 1
typedef struct {
uint8_t key[GTK_LEN]; /**< Group Transient Key (128 bits) */
uint64_t expirytime; /**< GTK expiry time on storage */
@ -108,7 +112,8 @@ typedef struct {
typedef struct {
uint8_t gtk[GTK_LEN]; /**< GTK of the frame counter */
uint32_t frame_counter; /**< Current frame counter */
uint32_t stored_frame_counter; /**< Stored Frame counter */
uint32_t stored_frame_counter; /**< Stored frame counter */
uint32_t max_frame_counter_chg; /**< Maximum frame counter change */
bool set : 1; /**< Value has been set */
} frame_counter_t;
@ -144,6 +149,7 @@ typedef struct {
uint16_t new_pan_id; /**< new PAN ID indicated by bootstrap */
uint16_t key_pan_id; /**< PAN ID for keys */
uint16_t pan_version; /**< PAN version for keys */
uint8_t system_time_changed; /**< System time changed */
bool updated : 1; /**< Network info has been updated */
} sec_prot_keys_nw_info_t;
@ -630,7 +636,7 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index
* \return new GTK lifetime
*
*/
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable);
uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint32_t seconds, bool gtk_update_enable);
/**
* sec_prot_keys_gtk_exptime_from_lifetime_get converts GTK lifetime to expiry time.
@ -806,11 +812,12 @@ int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk);
*
* \param gtks GTK keys
* \param gtk_hash GTK hash
* \param del_gtk_on_mismatch Delete GTK in case of mismatch
*
* \return GTK mismatch type or no mismatch
*
*/
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash);
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash, bool del_gtk_on_mismatch);
/**
* sec_prot_keys_gtk_hash_empty checks if GTK hash field is empty

View File

@ -514,19 +514,31 @@ int8_t sec_prot_lib_gtkhash_generate(uint8_t *gtk, uint8_t *gtk_hash)
mbedtls_sha256_init(&ctx);
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_starts(&ctx, 0) != 0) {
#else
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
#endif
ret_val = -1;
goto error;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_update(&ctx, gtk, 16) != 0) {
#else
if (mbedtls_sha256_update_ret(&ctx, gtk, 16) != 0) {
#endif
ret_val = -1;
goto error;
}
uint8_t output[32];
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_sha256_finish(&ctx, output) != 0) {
#else
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
#endif
ret_val = -1;
goto error;
}

View File

@ -595,7 +595,7 @@ static void tls_sec_prot_tls_export_keys(void *handle, const uint8_t *master_sec
const uint8_t *print_data = eap_tls_key_material;
uint16_t print_data_len = 128;
while (true) {
tr_debug("EAP-TLS key material %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
tr_debug("EAP-TLS key material %s", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
if (print_data_len > 32) {
print_data_len -= 32;
print_data += 32;

View File

@ -18,12 +18,8 @@
#include "nsconfig.h"
#ifdef HAVE_WS
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/version.h"
#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_SSL_EXPORT_KEYS) /* EXPORT_KEYS not supported by mbedtls baremetal yet */
#define WS_MBEDTLS_SECURITY_ENABLED
#endif
@ -49,7 +45,6 @@
#include "mbedtls/platform.h"
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/debug.h"
@ -77,7 +72,9 @@ struct tls_security_s {
mbedtls_pk_context pkey; /**< Private key for own certificate */
void *handle; /**< Handle provided in callbacks (defined by library user) */
bool ext_cert_valid : 1; /**< Extended certificate validation enabled */
#if (MBEDTLS_VERSION_MAJOR < 3)
tls_sec_prot_lib_crt_verify_cb *crt_verify; /**< Verify function for client/server certificate */
#endif
tls_sec_prot_lib_send *send; /**< Send callback */
tls_sec_prot_lib_receive *receive; /**< Receive callback */
tls_sec_prot_lib_export_keys *export_keys; /**< Export keys callback */
@ -90,12 +87,22 @@ static int tls_sec_prot_lib_ssl_get_timer(void *ctx);
static int tls_sec_lib_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen);
static int tls_sec_prot_lib_ssl_send(void *ctx, const unsigned char *buf, size_t len);
static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len);
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms,
#if (MBEDTLS_VERSION_MAJOR >= 3)
static void tls_sec_prot_lib_ssl_export_keys(void *p_expkey, mbedtls_ssl_key_export_type type,
const unsigned char *secret,
size_t secret_len,
const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type);
#else
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *secret,
const unsigned char *kb, size_t maclen, size_t keylen,
size_t ivlen, const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type);
#endif
#if (MBEDTLS_VERSION_MAJOR < 3)
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags);
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt);
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt);
@ -105,6 +112,7 @@ static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, m
#ifdef HAVE_PAE_SUPP
static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
#endif
#endif
#ifdef TLS_SEC_PROT_LIB_TLS_DEBUG
static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int line, const char *string);
#endif
@ -234,7 +242,11 @@ static int tls_sec_prot_lib_configure_certificates(tls_security_t *sec, const se
return -1;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (mbedtls_pk_parse_key(&sec->pkey, key, key_len, NULL, 0, mbedtls_ctr_drbg_random, &sec->ctr_drbg) < 0) {
#else
if (mbedtls_pk_parse_key(&sec->pkey, key, key_len, NULL, 0) < 0) {
#endif
tr_error("Private key parse error");
return -1;
}
@ -310,6 +322,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
return -1;
}
#if (MBEDTLS_VERSION_MAJOR < 3)
#ifdef HAVE_PAE_SUPP
if (is_server_is_not_set) {
sec->crt_verify = tls_sec_prot_lib_x509_crt_server_verify;
@ -320,7 +333,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
sec->crt_verify = tls_sec_prot_lib_x509_crt_idevid_ldevid_verify;
}
#endif
#endif
if ((mbedtls_ssl_config_defaults(&sec->conf,
is_server_is_set ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
@ -384,7 +397,11 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
#endif
// Export keys callback
#if (MBEDTLS_VERSION_MAJOR >= 3)
mbedtls_ssl_set_export_keys_cb(&sec->ssl, tls_sec_prot_lib_ssl_export_keys, sec);
#else
mbedtls_ssl_conf_export_keys_ext_cb(&sec->conf, tls_sec_prot_lib_ssl_export_keys, sec);
#endif
#if !defined(MBEDTLS_SSL_CONF_MIN_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MIN_MAJOR_VER)
mbedtls_ssl_conf_min_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3);
@ -395,7 +412,9 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
#endif /* !defined(MBEDTLS_SSL_CONF_MAX_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MAX_MAJOR_VER) */
// Set certificate verify callback
#if (MBEDTLS_VERSION_MAJOR < 3)
mbedtls_ssl_set_verify(&sec->ssl, tls_sec_prot_lib_x509_crt_verify, sec);
#endif
/* Currently assuming we are running fast enough HW that ECC calculations are not blocking any normal operation.
*
@ -432,7 +451,11 @@ int8_t tls_sec_prot_lib_process(tls_security_t *sec)
return TLS_SEC_PROT_LIB_ERROR;
}
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (sec->ssl.private_state == MBEDTLS_SSL_HANDSHAKE_OVER) {
#else
if (sec->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) {
#endif
return TLS_SEC_PROT_LIB_HANDSHAKE_OVER;
}
}
@ -469,16 +492,31 @@ static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len)
return ret;
}
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms,
#if (MBEDTLS_VERSION_MAJOR >= 3)
static void tls_sec_prot_lib_ssl_export_keys(void *p_expkey, mbedtls_ssl_key_export_type type,
const unsigned char *secret,
size_t secret_len,
const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type)
#else
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *secret,
const unsigned char *kb, size_t maclen, size_t keylen,
size_t ivlen, const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type)
#endif
{
#if (MBEDTLS_VERSION_MAJOR >= 3)
if (type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET || secret_len < 48) {
return;
}
#else
(void) kb;
(void) maclen;
(void) keylen;
(void) ivlen;
#endif
tls_security_t *sec = (tls_security_t *)p_expkey;
@ -487,18 +525,24 @@ static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char
memcpy(random, client_random, 32);
memcpy(&random[32], server_random, 32);
int ret = mbedtls_ssl_tls_prf(tls_prf_type, ms, 48, "client EAP encryption",
int ret = mbedtls_ssl_tls_prf(tls_prf_type, secret, 48, "client EAP encryption",
random, 64, eap_tls_key_material, 128);
if (ret != 0) {
tr_error("key material PRF error");
#if (MBEDTLS_VERSION_MAJOR < 3)
return 0;
#endif
}
sec->export_keys(sec->handle, ms, eap_tls_key_material);
sec->export_keys(sec->handle, secret, eap_tls_key_material);
#if (MBEDTLS_VERSION_MAJOR < 3)
return 0;
#endif
}
#if (MBEDTLS_VERSION_MAJOR < 3)
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags)
{
tls_security_t *sec = (tls_security_t *) ctx;
@ -605,6 +649,7 @@ static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_
return 0;
}
#endif
#endif
static int tls_sec_lib_entropy_poll(void *ctx, unsigned char *output, size_t len, size_t *olen)
{

View File

@ -35,7 +35,7 @@ static bool channel_list_bit_test32(uint32_t word, int_fast8_t bit_number)
{
bool bitSet;
if (word & ((uint32_t) 1 << bit_number)) {
if (word & (1U << bit_number)) {
bitSet = true;
} else {
bitSet = false;
@ -92,9 +92,9 @@ void channel_list_set_channel(uint32_t *list, int channel, bool active)
return;
}
if (active) {
list[channel / 32] |= (1 << channel % 32);
list[channel / 32] |= (1U << channel % 32);
} else {
list[channel / 32] &= ~(1 << channel % 32);
list[channel / 32] &= ~(1U << channel % 32);
}
return;
}

View File

@ -292,7 +292,7 @@ static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_
int32_t active_channels = 0;
// Set channel maks outside excluded channels
for (int32_t i = 0; i < number_of_channels; i++) {
if (channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
if (channel_mask[i / 32] & (1U << (i % 32))) {
if (channel_index == active_channels) {
return i;
}

View File

@ -29,12 +29,12 @@ int8_t hmac_md_calc(const alg_hmac_md_e md, const uint8_t *key, uint16_t key_len
{
#ifdef EXTRA_DEBUG_INFO
// Extensive debug for now, to be disabled later
tr_debug("hmac_md key %s\n", trace_array(key, key_len));
tr_debug("hmac_md key %s", trace_array(key, key_len));
const uint8_t *print_data = data;
uint16_t print_data_len = data_len;
while (true) {
tr_debug("hmac_md data %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
tr_debug("hmac_md data %s", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
if (print_data_len > 32) {
print_data_len -= 32;
print_data += 32;
@ -81,7 +81,7 @@ int8_t hmac_md_calc(const alg_hmac_md_e md, const uint8_t *key, uint16_t key_len
memcpy(result, result_value, result_len);
#ifdef EXTRA_DEBUG_INFO
tr_debug("hmac_md result %s\n", trace_array(result_value, 20));
tr_debug("hmac_md result %s", trace_array(result_value, 20));
#endif
return 0;

View File

@ -349,7 +349,7 @@ int nd_proxy_downstream_interface_register(int8_t interface_id, nd_proxy_req_cb
ns_list_foreach(nd_proxy_upstream_list_s, e, &upstream_interface_list) {
if (proxy_cache_interface_enable_proxy(e->id, interface_id) == 0) {
tr_debug("Proxy bridge enabled for interface %i to %i\n", e->id, interface_id);
tr_debug("Proxy bridge enabled for interface %i to %i", e->id, interface_id);
}
}
@ -391,7 +391,7 @@ int nd_proxy_upstream_interface_register(int8_t interface_id, nd_proxy_req_cb *r
ns_list_foreach(nd_proxy_downstream_list_s, e, &downstream_interface_list) {
if (proxy_cache_interface_enable_proxy(interface_id, e->id) == 0) {
tr_debug("Proxy bridge enabled for interface %i to %i \n", interface_id, e->id);
tr_debug("Proxy bridge enabled for interface %i to %i", interface_id, e->id);
}
}
return 0;

View File

@ -21,11 +21,7 @@
#include "ns_list.h"
#include "ns_trace.h"
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/version.h"
#if defined(MBEDTLS_NIST_KW_C) && defined(HAVE_WS) && (defined(HAVE_PAE_SUPP) || defined(HAVE_PAE_AUTH))
#include "mbedtls/nist_kw.h"
@ -48,7 +44,7 @@ int8_t nist_aes_key_wrap(uint8_t is_wrap, const uint8_t *key, int16_t key_bits,
const uint8_t *print_data = key;
uint16_t print_data_len = key_bits / 8;
while (true) {
tr_debug("nist_aes_key_wrap key %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
tr_debug("nist_aes_key_wrap key %s", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
if (print_data_len > 32) {
print_data_len -= 32;
print_data += 32;
@ -60,7 +56,7 @@ int8_t nist_aes_key_wrap(uint8_t is_wrap, const uint8_t *key, int16_t key_bits,
print_data = input;
print_data_len = input_len;
while (true) {
tr_debug("nist_aes_key_wrap in %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
tr_debug("nist_aes_key_wrap in %s", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
if (print_data_len > 32) {
print_data_len -= 32;
print_data += 32;
@ -95,7 +91,7 @@ int8_t nist_aes_key_wrap(uint8_t is_wrap, const uint8_t *key, int16_t key_bits,
print_data = output;
print_data_len = *output_len;
while (true) {
tr_debug("nist_aes_key_wrap out %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
tr_debug("nist_aes_key_wrap out %s", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
if (print_data_len > 32) {
print_data_len -= 32;
print_data += 32;

View File

@ -22,6 +22,9 @@
static ns_time_api_system_time_callback *system_time_read_callback = NULL;
static ns_time_api_system_time_write_callback *system_time_write_callback = NULL;
static ns_time_api_time_configuration_notify_callback *system_time_configuration_notify_callback = NULL;
static bool system_time_acquired = false;
void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callback_rd)
{
@ -33,10 +36,16 @@ void ns_time_api_system_time_write_callback_set(ns_time_api_system_time_write_ca
system_time_write_callback = callback_wr;
}
void ns_time_api_time_configuration_notify_callback_set(ns_time_api_time_configuration_notify_callback callback_wr)
{
system_time_configuration_notify_callback = callback_wr;
}
int ns_time_system_time_write(uint64_t time_write)
{
if (system_time_write_callback) {
system_time_write_callback(time_write);
system_time_acquired = true;
return 0;
}
@ -53,3 +62,23 @@ int ns_time_system_time_read(uint64_t *time_read)
return -1;
}
int ns_time_system_timezone_info_notify(timezone_info_t *info_ptr)
{
if (system_time_configuration_notify_callback && info_ptr) {
system_time_configuration_notify_callback(info_ptr);
return 0;
}
return -1;
}
void ns_time_system_time_acquired_set(void)
{
system_time_acquired = true;
}
bool ns_time_system_time_acquired_get(void)
{
return system_time_acquired;
}

View File

@ -22,6 +22,7 @@
* \file ns_time.h
* \brief Nanostack internal time handling API.
*/
#include "ns_time_api.h"
/**
* Write new time as a platform time
@ -51,6 +52,33 @@ int ns_time_system_time_write(uint64_t time_write);
*/
int ns_time_system_time_read(uint64_t *time_read);
/**
* Notify Time zone and daylight saving time information
*
* \param info_ptr time zone information pointer.
*
* \return 0 in success.
* \return <0 in case of errors.
*
*/
int ns_time_system_timezone_info_notify(timezone_info_t *info_ptr);
/**
* Set system time acquired
*
* Sets system time acquired (e.g. has been acquired from network)
*
*/
void ns_time_system_time_acquired_set(void);
/**
* Get system time acquired
*
* Checks whether system time has been acquired (e.g. has been written)
*
* \return TRUE system time has been acquired, FALSE system time has not been acquired
*
*/
bool ns_time_system_time_acquired_get(void);
#endif /* _NS_TIME_H_ */

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2021, Pelion 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.
*/
#define HAVE_WS
#define HAVE_WS_HOST
#define HAVE_WS_VERSION_1_1
#define HAVE_RPL
#define HAVE_MPL
#define HAVE_6LOWPAN_ND
#define HAVE_IPV6_ND
#define HAVE_PAE_SUPP
#define HAVE_6LOWPAN_ROUTER

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Pelion and affiliates.
* Copyright (c) 2019-2021, Pelion and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -15,12 +15,7 @@
* limitations under the License.
*/
#define HAVE_6LOWPAN_ROUTER
#include "cfg_ws_host.h"
#define HAVE_WS_ROUTER
#define HAVE_RPL
#define HAVE_IPV6_ND
#define HAVE_6LOWPAN_ND
#define HAVE_MPL
#define HAVE_WS
#define HAVE_PAE_SUPP
#define HAVE_EAPOL_RELAY

View File

@ -32,4 +32,5 @@
#define TCP_TEST
#define THREAD_THCI_SUPPORT
#define HAVE_WS
#define HAVE_WS_VERSION_1_1
#define MLE_TEST

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021, Pelion 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 "base/cfg_ws_host.h"
#define FEA_TRACE_SUPPORT
#define EXTRA_CONSISTENCY_CHECKS

View File

@ -323,16 +323,16 @@ static void ipv6_nd_bootstrap(protocol_interface_info_entry_t *cur)
break;
case IPV6_ROUTER_SOLICATION:
tr_debug("Waiting for ICMPv6 Router Advertisement");
if (ipv6_nd_rs(cur)) {
tr_debug("Waiting for ICMPv6 Router Advertisement");
if (cur->ipv6_configure->routerSolicationRetryCounter != ROUTER_SOL_MAX_COUNTER) {
cur->ipv6_configure->routerSolicationRetryCounter++;
}
cur->ipv6_configure->ND_TIMER = (cur->ipv6_configure->routerSolicationRetryCounter * 25);
} else {
cur->ipv6_configure->ND_TIMER = 1;
}
if (cur->ipv6_configure->routerSolicationRetryCounter == 0) {
cur->ipv6_configure->routerSolicationRetryCounter++;
}
cur->ipv6_configure->ND_TIMER = (cur->ipv6_configure->routerSolicationRetryCounter * 25);
break;
case IPV6_GP_GEN:

View File

@ -137,7 +137,7 @@ uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int3
}
option_len = common_read_16_bit(ptr + 2);
ptr += 4;
ptr += 2 * sizeof(uint16_t);
if (option_len < 3 * sizeof(uint32_t)) {
// Corrupted as not enough room for fields
@ -147,11 +147,70 @@ uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int3
if (era) {
*era = (int32_t)common_read_32_bit(ptr);
}
if (offset) {
*offset = common_read_32_bit(ptr + sizeof(uint32_t));
}
if (fraction) {
*fraction = common_read_32_bit(ptr + 2 * sizeof(uint32_t));
*fraction = common_read_32_bit(ptr + sizeof(uint32_t) + sizeof(uint32_t));
}
return ptr;
}
uint16_t net_vendor_option_time_configuration_length(void)
{
return 4 + 1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t);
}
uint8_t *net_vendor_option_time_configuration_write(uint8_t *ptr, uint64_t timestamp, int16_t timezone, int16_t deviation, uint16_t status)
{
ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION, ptr);
ptr = common_write_16_bit(1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t), ptr);
ptr = common_write_16_bit(status, ptr);
ptr = common_write_64_bit(timestamp, ptr);
ptr = common_write_16_bit((uint16_t)deviation, ptr);
ptr = common_write_16_bit((uint16_t)timezone, ptr);
return ptr;
}
uint8_t *net_vendor_option_time_configuration_read(uint8_t *ptr, uint16_t length, uint64_t *timestamp, int16_t *timezone, int16_t *deviation, uint16_t *status)
{
uint16_t option_len;
if (length < net_vendor_option_time_configuration_length()) {
// Corrupted as there is no room for all fields
return 0;
}
if (common_read_16_bit(ptr) != ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION) {
return 0;
}
option_len = common_read_16_bit(ptr + sizeof(uint16_t));
ptr += 2 * sizeof(uint16_t);
if (option_len < 1 * sizeof(uint64_t) + 2 * sizeof(int16_t) + 1 * sizeof(uint16_t)) {
// Corrupted as not enough room for fields
return 0;
}
if (status) {
*status = (uint16_t)common_read_16_bit(ptr);
}
if (timestamp) {
*timestamp = common_read_64_bit(ptr + sizeof(uint16_t));
}
if (deviation) {
*deviation = (int16_t)common_read_16_bit(ptr + sizeof(uint16_t) + sizeof(uint64_t));
}
if (timezone) {
*timezone = (int16_t)common_read_16_bit(ptr + sizeof(uint16_t) + sizeof(uint64_t) + sizeof(uint16_t));
}
return ptr;

View File

@ -66,6 +66,17 @@
* */
#define ARM_DHCP_VENDOR_DATA_NETWORK_TIME 298
/* ARM Defined vendor data option to distribute Time configuration
*
* uint16_t status Bit field for status
* bit 1 Daylight saving time status 0 = false 1 = true
* Additional bits reserved for future and are ignored on receive
* uint64_t timestamp Time stamp of the Daylight saving time change
* int16_t deviation Change that is applied when time stamp is reached
* int16_t timezone Time zone information in minutes compared to UTC time
*/
#define ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION 299
/* DHCPv6 vendor options to distribute ARM vendor data*/
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
@ -78,5 +89,8 @@ uint16_t net_vendor_option_current_time_length(void);
uint8_t *net_vendor_option_current_time_write(uint8_t *ptr, int32_t era, uint32_t offset, uint32_t fraction);
uint8_t *net_vendor_option_current_time_read(uint8_t *ptr, uint16_t length, int32_t *era, uint32_t *offset, uint32_t *fraction);
uint16_t net_vendor_option_time_configuration_length(void);
uint8_t *net_vendor_option_time_configuration_write(uint8_t *ptr, uint64_t timestamp, int16_t timezone, int16_t deviation, uint16_t status);
uint8_t *net_vendor_option_time_configuration_read(uint8_t *ptr, uint16_t length, uint64_t *timestamp, int16_t *timezone, int16_t *deviation, uint16_t *status);
#endif /* LIBDHCPV6_VENDOR_DATA_H_ */

View File

@ -67,7 +67,7 @@
#include "6LoWPAN/Thread/thread_routing.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_common.h"
#ifdef HAVE_WS
#include "6LoWPAN/ws/ws_pae_controller.h"
#endif
@ -168,7 +168,7 @@ int8_t arm_net_nwk_scan(int8_t interface_id, channel_list_s *scan_list, void (*p
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
ret_val = -1;
} else if (arm_channel_list_validation(scan_list)) {
tr_debug("Given channel mask is empty!\n");
tr_debug("Given channel mask is empty!");
ret_val = -2;
} else {
nwk_scan_params_t *scan_params = &cur->mac_parameters->nwk_scan_params;
@ -768,7 +768,7 @@ static int arm_net_channel_bit_mask_to_number(const uint32_t *channel_mask)
for (j = 0; j < 8; j++) {
for (i = 0; i < 32; i++) {
if (channel_mask[j] & ((uint32_t)1 << i)) {
if (channel_mask[j] & (1U << i)) {
break;
}
}
@ -804,7 +804,7 @@ int8_t arm_nwk_interface_network_driver_set(int8_t interface_id, const channel_l
protocol_interface_info_entry_t *cur = 0;
if (arm_channel_list_validation(nwk_channel_list)) {
tr_debug("Given channel mask is empty!\n");
tr_debug("Given channel mask is empty!");
return -5;
}
@ -981,15 +981,21 @@ int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_la
int8_t arm_network_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info)
{
int8_t ret = -2;
#if !defined(PANA) && !defined(HAVE_WS)
(void)chain_info;
#endif
#ifdef HAVE_WS
ws_pae_controller_certificate_chain_set(chain_info);
ret = ws_pae_controller_certificate_chain_set(chain_info);
#endif
return pana_interface_certificate_chain_set(chain_info);
#ifdef PANA
ret = pana_interface_certificate_chain_set(chain_info);
#endif
return ret;
}
int8_t arm_network_trusted_certificate_add(const arm_certificate_entry_s *cert)
@ -1207,7 +1213,7 @@ int8_t arm_nwk_interface_configure_6lowpan_bootstrap_set(int8_t interface_id, ne
if (net_6lowpan_mode_extension == NET_6LOWPAN_THREAD) {
ret_val = thread_node_bootstrap_init(interface_id, bootstrap_mode);
} else if (net_6lowpan_mode_extension == NET_6LOWPAN_WS) {
ret_val = ws_bootstrap_init(interface_id, bootstrap_mode);
ret_val = ws_common_init(interface_id, bootstrap_mode);
} else {
ret_val = arm_6lowpan_bootstarp_bootstrap_set(interface_id, bootstrap_mode, net_6lowpan_mode_extension);
}
@ -1226,7 +1232,7 @@ int8_t arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s *nwk_c
}
if (arm_channel_list_validation(nwk_channel_list)) {
tr_debug("Given channel mask is empty!\n");
tr_debug("Given channel mask is empty!");
return -2;
}

View File

@ -23,6 +23,9 @@ SRCS += \
source/6LoWPAN/ws/ws_mpx_header.c \
source/6LoWPAN/ws/ws_neighbor_class.c \
source/6LoWPAN/ws/ws_bootstrap.c \
source/6LoWPAN/ws/ws_bootstrap_6lbr.c \
source/6LoWPAN/ws/ws_bootstrap_ffn.c \
source/6LoWPAN/ws/ws_bootstrap_lfn.c \
source/6LoWPAN/ws/ws_common.c \
source/6LoWPAN/ws/ws_management_api.c \
source/6LoWPAN/ws/ws_bbr_api.c \
@ -43,6 +46,7 @@ SRCS += \
source/6LoWPAN/ws/ws_eapol_pdu.c \
source/6LoWPAN/ws/ws_stats.c \
source/6LoWPAN/ws/ws_cfg_settings.c \
source/6LoWPAN/ws/ws_phy.c \
source/BorderRouter/border_router.c \
source/Common_Protocols/icmpv6.c \
source/Common_Protocols/icmpv6_prefix.c \
@ -83,6 +87,7 @@ SRCS += \
source/MAC/IEEE802_15_4/sw_mac.c \
source/MAC/IEEE802_15_4/mac_fhss_callbacks.c \
source/MAC/IEEE802_15_4/mac_cca_threshold.c \
source/MAC/IEEE802_15_4/mac_mode_switch.c \
source/MAC/ethernet/ethernet_mac_api.c \
source/MAC/serial/serial_mac_api.c \
source/MAC/virtual_rf/virtual_rf_client.c \