mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #14573 from artokin/nanostack_release_13_0_0_for_master
Nanostack release v13.0.0pull/14612/head
commit
64eb60e4cc
|
@ -619,7 +619,7 @@ static void rf_handle_cca_ed_done(void)
|
|||
backup_time = 0;
|
||||
}
|
||||
rf_backup_timer_start(0, backup_time + PACKET_PROCESSING_TIME);
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL_RX, 0, 0);
|
||||
return;
|
||||
}
|
||||
if ((cca_enabled == true) && (((int8_t) rf_read_rf_register(RF_EDV, rf_module) > cca_threshold))) {
|
||||
|
@ -997,7 +997,7 @@ static void rf_backup_timer_interrupt(void)
|
|||
}
|
||||
if ((rf_state == RF_CSMA_STARTED) || (rf_state == RF_CSMA_WHILE_RX)) {
|
||||
TEST_CSMA_DONE
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL_RX, 0, 0);
|
||||
}
|
||||
TEST_TX_DONE
|
||||
TEST_RX_DONE
|
||||
|
|
|
@ -848,7 +848,11 @@ static void rf_cca_timer_interrupt(void)
|
|||
rf_flush_tx_fifo();
|
||||
tx_finnish_time = rf_get_timestamp();
|
||||
if (device_driver.phy_tx_done_cb) {
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
|
||||
if (rf_state == RF_RX_STARTED) {
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL_RX, 0, 0);
|
||||
} else {
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (status == PHY_RESTART_CSMA) {
|
||||
|
@ -1143,7 +1147,7 @@ static void rf_irq_task_process_irq(void)
|
|||
tx_finnish_time = rf_get_timestamp();
|
||||
rf_update_tx_active_time();
|
||||
TEST_TX_DONE
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 0);
|
||||
device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL_RX, 1, 0);
|
||||
rf_send_command(S2LP_CMD_SABORT);
|
||||
rf_poll_state_change(S2LP_STATE_READY);
|
||||
rf_send_command(S2LP_CMD_FLUSHTXFIFO);
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2016-2017 ARM Ltd.
|
||||
//
|
||||
// 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.
|
||||
// ----------------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright (c) 2016-2017 ARM Limited. All rights reserved.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* NanoStack NVM helper functions to read, write and delete key-value pairs to platform NVM.
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2016-2017 ARM Ltd.
|
||||
//
|
||||
// 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.
|
||||
// ----------------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright (c) 2016-2017 ARM Limited. All rights reserved.
|
||||
* 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 <ns_types.h>
|
||||
|
|
|
@ -142,6 +142,15 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
|
|||
*/
|
||||
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address);
|
||||
|
||||
/**
|
||||
* \brief Enable DHCPv6 Relay Agent to add interface ID option to relay frame. Default is disabled.
|
||||
*
|
||||
*
|
||||
* \param instance The instance ID of the registered server.
|
||||
* \param enable true add interface option
|
||||
*/
|
||||
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable);
|
||||
|
||||
/**
|
||||
* \brief Get DHCPv6 Relay Agent address pointer.
|
||||
*
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct fhss_callback fhss_callback_t;
|
|||
typedef enum {
|
||||
FHSS_UNSYNCHRONIZED,
|
||||
FHSS_SYNCHRONIZED,
|
||||
FHSS_EXPEDITED_FORWARDING
|
||||
} fhss_states;
|
||||
|
||||
/**
|
||||
|
|
|
@ -118,6 +118,27 @@ extern int ns_fhss_set_neighbor_info_fp(const fhss_api_t *fhss_api, fhss_get_nei
|
|||
*/
|
||||
extern int ns_fhss_ws_set_hop_count(const fhss_api_t *fhss_api, const uint8_t hop_count);
|
||||
|
||||
/**
|
||||
* @brief WS TX allowance levels.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Allow transmitting only on TX slots. */
|
||||
WS_TX_SLOT,
|
||||
/** Allow transmitting only on TX and RX slots. */
|
||||
WS_TX_AND_RX_SLOT,
|
||||
/** Allow transmitting always. Also unicast on broadcast channel. */
|
||||
WS_TX_ALWAYS
|
||||
} fhss_ws_tx_allow_level;
|
||||
|
||||
/**
|
||||
* @brief Set node unicast TX allowance level. Allows device to use the unicast and broadcast channel for unicast transmission as described by fhss_ws_tx_allow_level.
|
||||
* @param fhss_api FHSS instance.
|
||||
* @param global_level Level of TX allowance in normal mode.
|
||||
* @param ef_level Level of TX allowance in expedited forwarding mode.
|
||||
* @return 0 on success, -1 on fail.
|
||||
*/
|
||||
extern int ns_fhss_ws_set_tx_allowance_level(const fhss_api_t *fhss_api, const fhss_ws_tx_allow_level global_level, const fhss_ws_tx_allow_level ef_level);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -128,10 +128,11 @@ typedef void mcps_data_request(const mac_api_t *api, const mcps_data_req_t *data
|
|||
* @param data MCPS-DATA.request specific values
|
||||
* @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
|
||||
*
|
||||
* 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);
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief mcps_purge_request MCPS_PURGE request call
|
||||
|
|
|
@ -192,5 +192,17 @@ typedef struct mcps_edfe_response_s {
|
|||
bool use_message_handle_to_discover: 1; /**< EDFE Data request message ID is valid at message_handle. */
|
||||
} mcps_edfe_response_t;
|
||||
|
||||
/**
|
||||
* @brief enum mac_data_priority_t Data request priority level
|
||||
*
|
||||
* Data request priority level may affect CCA process and MAC queue process
|
||||
*/
|
||||
typedef enum mac_data_priority_e {
|
||||
MAC_DATA_NORMAL_PRIORITY = 0, /**< Normal MCPS DATA REQ */
|
||||
MAC_DATA_MEDIUM_PRIORITY = 1, /**< Indirect Data which is polled */
|
||||
MAC_DATA_HIGH_PRIORITY = 2, /**< MAC command usually use this and beacon */
|
||||
MAC_DATA_EXPEDITE_FORWARD = 3 /**< Expedite forward level give highest priority */
|
||||
} mac_data_priority_t;
|
||||
|
||||
|
||||
#endif // MAC_MCPS_H
|
||||
|
|
|
@ -264,6 +264,7 @@ typedef enum {
|
|||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||
//NON standard extension
|
||||
macRequestRestart = 0xf1, /*< Configure failed packet data request restart */
|
||||
macEdfeForceStop = 0xf2, /*< Use this command for Data wait timeout at LLC: Mac stop Edfe session data wait and enable normal FHSS mode */
|
||||
macSetDataWhitening = 0xf3, /*< Enable or disable data whitening, boolean true for enable, false for disable */
|
||||
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
|
||||
|
@ -517,4 +518,16 @@ typedef struct mlme_multi_csma_ca_s {
|
|||
uint16_t multi_cca_interval; /**< Length of the additional CSMA-CA period(s) in microseconds */
|
||||
} mlme_multi_csma_ca_param_t;
|
||||
|
||||
/**
|
||||
* @brief struct mlme_request_restart_config_s Set failed packet request restart configuration
|
||||
*
|
||||
* Non standard extension to restart data request after failed CCA or TX attempts
|
||||
*/
|
||||
typedef struct mlme_request_restart_config_s {
|
||||
uint8_t cca_failure_restart_max; /**< Max number of restarts after CCA failure */
|
||||
uint8_t tx_failure_restart_max; /**< Max number of restarts after TX failure */
|
||||
uint16_t blacklist_min_ms; /**< Blacklist min, which is doubled by every restart */
|
||||
uint16_t blacklist_max_ms; /**< Blacklist max, largest allowed blacklist time */
|
||||
} mlme_request_restart_config_t;
|
||||
|
||||
#endif /* MLME_H_ */
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef enum {
|
|||
PHY_LINK_TX_SUCCESS, /**< MAC TX complete. MAC will a make decision to enter wait ACK or TX done state. */
|
||||
PHY_LINK_TX_FAIL, /**< Link TX process fail. */
|
||||
PHY_LINK_CCA_FAIL, /**< RF link CCA process fail. */
|
||||
PHY_LINK_CCA_FAIL_RX, /**< RF link CCA process failed because of packet reception. */
|
||||
PHY_LINK_CCA_OK, /**< RF link CCA process ok. */
|
||||
PHY_LINK_CCA_PREPARE, /**< Prepare for CCA after CSMA-CA: changes to CCA channel and gives permission to TX. See PHY_LINK_CCA_PREPARE status definitions for return values */
|
||||
} phy_link_tx_status_e;
|
||||
|
|
|
@ -138,10 +138,41 @@ extern "C" {
|
|||
* After the successful state change, data can be sent using socket_send().
|
||||
* The connection can be shut down in either direction with socket_shutdown() function - shutting down write signals end-of-data to the peer.
|
||||
*
|
||||
*
|
||||
* \section socket-udpicmp How to use UDP and RAW socket:
|
||||
*
|
||||
* A UDP socket is ready to receive and send data immediately after a successful call of socket_open() and a NET_READY event is received.
|
||||
* Data can be transmitted with the socket_sendto() function. An ICMP socket works with same function call.
|
||||
*
|
||||
* \section socket-trafficpriority How to set socket message priority to improve Quality of Service (QoS):
|
||||
*
|
||||
* IPv6 header has a field traffic class that contains a 6-bit Differentiated Services Code Point (DSCP) field that is used for packet
|
||||
* classification. By default the packet class level is set to 0 NS_DSCP_DEFAULT.
|
||||
*
|
||||
* Recommend QoS levels:
|
||||
*
|
||||
* | Level |Description |
|
||||
* | :--------------: | :-------------------------------------------------------------------------------------------------: |
|
||||
* | NS_DSCP_DEFAULT | Default level for normal data usage |
|
||||
* | NS_DSCP_AF11 | Higher Application data service for prioritize packet forwarding. |
|
||||
* | NS_DSCP_EF | Expedited Forwarding (EF) for short messages. Allows low loss, low delay, and low jitter services. |
|
||||
* | | This is meant for very important messages like alerts. EF packet length should be kept in |
|
||||
* | | minimum. This should not be used for any other purpose as it will block other network traffic |
|
||||
* | NS_DSCP_CS6 | Network protocol message Priority. Application should not use this. |
|
||||
*
|
||||
* High priority messages can be set to use higher than default class by using socket_setsockopt() and
|
||||
* socket_option_traffic_class_dsc_set() helper.
|
||||
*
|
||||
* Example to send a message using Expedited Forwarding class:
|
||||
*
|
||||
* //Set EF class to high priority messages
|
||||
* int16_t traffic_class = socket_option_traffic_class_dsc_set(NS_DSCP_EF);
|
||||
* socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &traffic_class, sizeof traffic_class);
|
||||
*
|
||||
* //Set traffic class back to default
|
||||
* traffic_class = socket_option_traffic_class_dsc_set(NS_DSCP_DEFAULT);
|
||||
* socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &traffic_class, sizeof traffic_class);
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns_address.h"
|
||||
|
@ -250,6 +281,24 @@ typedef struct ns_in6_pktinfo {
|
|||
int8_t ipi6_ifindex; /**< send/recv interface index */
|
||||
} ns_in6_pktinfo_t;
|
||||
|
||||
/** \name Socket DSCP (Differentiated Services Code Point) QoS level examples.
|
||||
* \anchor MSG_QOS_LEVELS
|
||||
*/
|
||||
///@{
|
||||
/** Standard priority and it is socket default */
|
||||
#define NS_DSCP_DEFAULT 0
|
||||
/** Application high priority service: Stack priorities these messages over the default priority messages */
|
||||
#define NS_DSCP_AF11 10
|
||||
/** Expedited Forwarding (EF) QoS level enable high priority state: low loss, low delay, and low jitter services */
|
||||
#define NS_DSCP_EF 46
|
||||
/** Network protocol traffic allocated QoS level stack may internally use that */
|
||||
#define NS_DSCP_CS6 48
|
||||
///@}
|
||||
|
||||
/** Helper Traffic class Differentiated Services Code for QoS 0-63. 0 is default which define Lowest Priority
|
||||
*
|
||||
* */
|
||||
#define socket_option_traffic_class_dsc_set(x) (uint8_t)((x & 63) << 2)
|
||||
|
||||
/** \name Alignment macros for control message headers
|
||||
* \anchor CMSG_ALIGN_FLAGS
|
||||
|
|
|
@ -99,6 +99,7 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
|||
#define BBR_REQUIRE_DAO_REFRESH 0x0000 /**< Deprecated DAO Refresh is now the default functionality*/
|
||||
#define BBR_PERIODIC_VERSION_INC 0x0010 /**< Increment PAN version number Periodically*/
|
||||
#define BBR_GUA_SLAAC 0x0020 /**< in Global prefix use SLAAC address generation to reduce traffic during bootstrap */
|
||||
#define BBR_DHCP_ANONYMOUS 0x0040 /**< Generate anonymous addresses from DHCP server */
|
||||
|
||||
/**
|
||||
* Configure border router features.
|
||||
|
@ -108,6 +109,9 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
|||
* BBR_ULA_C Configure Mesh local ULA prefix with SLAAC address
|
||||
* BBR_GUA_ROUTE Add more specific route for GUA
|
||||
* BBR_BB_WAIT Start Wi-SUN network only when backbone is ready
|
||||
* BBR_DHCP_ANONYMOUS if true give anonymous address (16 bit suffix) to
|
||||
* optimize data in RF interface (saves 12 bytes per hop)
|
||||
* or false to reduce RAM usage in Border router as assigned address list is not needed (40 bytes per device).
|
||||
*
|
||||
* By default Wi-SUN network is started and is treated as separate interface even if backbone is not available.
|
||||
*
|
||||
|
|
|
@ -90,11 +90,48 @@ extern "C" {
|
|||
#define NETWORK_SIZE_XLARGE 0x19 /**< 2500+ devices */
|
||||
#define NETWORK_SIZE_AUTOMATIC 0xFF /**< Automatic network size */
|
||||
|
||||
/**
|
||||
* \brief Neighbor type to differentiate the Role of the neighbor.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
WS_OTHER = 0, /**< temporary or soon to be removed neighbor*/
|
||||
WS_PRIMARY_PARENT, /**< Primary parent used for upward packets and used from Border router downwards*/
|
||||
WS_SECONDARY_PARENT, /**< Secondary parent reported to border router and might be used as alternate route*/
|
||||
WS_CANDIDATE_PARENT, /**< Candidate neighbor that is considered as parent if there is problem with active parents*/
|
||||
WS_CHILD /**< Child with registered address*/
|
||||
} ws_management_neighbor_type_e;
|
||||
|
||||
|
||||
/** Temporary API change flag. this will be removed when new version of API is implemented on applications
|
||||
*
|
||||
*/
|
||||
#define WS_MANAGEMENT_API_VER_2 /**< Management API version */
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
* Configure PHY mode ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param phy_mode_id PHY mode ID. Default 255 (not used).
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
#define ws_management_phy_mode_id_set(interface_id, phy_mode_id) ws_management_domain_configuration_set(interface_id, 0, phy_mode_id, 0)
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
* Configure Channel plan ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param channel_plan_id Channel plan ID. Default 255 (not used).
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
#define ws_management_channel_plan_id_set(interface_id, channel_plan_id) ws_management_domain_configuration_set(interface_id, 0, 0, channel_plan_id)
|
||||
|
||||
/**
|
||||
* \brief Struct ws_statistics defines the Wi-SUN statistics storage structure.
|
||||
*/
|
||||
|
@ -103,6 +140,47 @@ typedef struct ws_statistics {
|
|||
uint32_t asynch_tx_count;
|
||||
/** Asynch RX counter */
|
||||
uint32_t asynch_rx_count;
|
||||
|
||||
|
||||
/** Time spent in individual Wi-SUN join state 1 Discovery*/
|
||||
uint32_t join_state_1;
|
||||
/** Time spent in individual Wi-SUN join state 2 Authentication*/
|
||||
uint32_t join_state_2;
|
||||
/** Time spent in individual Wi-SUN join state 3 Configuration learn*/
|
||||
uint32_t join_state_3;
|
||||
/** Time spent in individual Wi-SUN join state 4 RPL parent discovery*/
|
||||
uint32_t join_state_4;
|
||||
/** Time spent in individual Wi-SUN join state 5 Active state*/
|
||||
uint32_t join_state_5;
|
||||
|
||||
|
||||
/** Amount of Wi-SUN Pan Advertisement Solicit Message sent*/
|
||||
uint32_t sent_PAS;
|
||||
/** Amount of Wi-SUN Pan Advertisement Message sent*/
|
||||
uint32_t sent_PA;
|
||||
/** Amount of Wi-SUN Pan Configuration Solicit Message sent*/
|
||||
uint32_t sent_PCS;
|
||||
/** Amount of Wi-SUN Pan Configuration Message sent*/
|
||||
uint32_t sent_PC;
|
||||
|
||||
/** Amount of Wi-SUN Pan Advertisement Solicit Message sent*/
|
||||
uint32_t recv_PAS;
|
||||
/** Amount of Wi-SUN Pan Advertisement Message sent*/
|
||||
uint32_t recv_PA;
|
||||
/** Amount of Wi-SUN Pan Configuration Solicit Message sent*/
|
||||
uint32_t recv_PCS;
|
||||
/** Amount of Wi-SUN Pan Configuration Message sent*/
|
||||
uint32_t recv_PC;
|
||||
|
||||
/** New Neighbours found */
|
||||
uint32_t Neighbour_add;
|
||||
/** New Neighbours Removed */
|
||||
uint32_t Neighbour_remove;
|
||||
/** New Child added */
|
||||
uint32_t Child_add;
|
||||
/** Child lost */
|
||||
uint32_t child_remove;
|
||||
|
||||
} ws_statistics_t;
|
||||
|
||||
/**
|
||||
|
@ -125,6 +203,28 @@ typedef struct ws_stack_info {
|
|||
uint8_t join_state;
|
||||
} ws_stack_info_t;
|
||||
|
||||
/**
|
||||
* \brief Struct ws_neighbour_info_t Gives the neighbour information.
|
||||
*/
|
||||
typedef struct ws_neighbour_info {
|
||||
/** Link local address*/
|
||||
uint8_t link_local_address[16];
|
||||
/** Global address if it is known set to 0 if not available*/
|
||||
uint8_t global_address[16];
|
||||
/** parent RSSI Out measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/
|
||||
uint8_t rsl_out;
|
||||
/** parent RSSI in measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/
|
||||
uint8_t rsl_in;
|
||||
/** RPL Rank value for parents 0xffff for neighbors RANK is unknown*/
|
||||
uint16_t rpl_rank;
|
||||
/** Measured ETX value if known set to 0xFFFF if not known or Child*/
|
||||
uint16_t etx;
|
||||
/** Remaining lifetime Link lifetime for parents and ARO lifetime for children*/
|
||||
uint32_t lifetime;
|
||||
/** Neighbour type (Primary Parent, Secondary Parent, Candidate parent, child, other(Temporary neighbours))*/
|
||||
ws_management_neighbor_type_e type;
|
||||
} ws_neighbour_info_t;
|
||||
|
||||
/**
|
||||
* Initialize Wi-SUN stack.
|
||||
*
|
||||
|
@ -187,80 +287,107 @@ int ws_management_network_name_validate(
|
|||
char *network_name_ptr);
|
||||
|
||||
/**
|
||||
* Configure PHY mode ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
* Set domain configuration of Wi-SUN stack.
|
||||
*
|
||||
* Change the default configuration for Wi-SUN PHY operation.
|
||||
*
|
||||
* Supported values:
|
||||
* FSK without FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 1 50 0.5
|
||||
* 2 50 1.0
|
||||
* 3 100 0.5
|
||||
* 4 100 1.0
|
||||
* 5 150 0.5
|
||||
* 6 200 0.5
|
||||
* 7 200 1.0
|
||||
* 8 300 0.5
|
||||
* Regulatory domain: "NA"(0x01), "KR"(0x09), "EU"(0x03), "IN"(0x05), "BZ"(0x07), "JP"(0x09), "WW"(0x00)
|
||||
*
|
||||
* FSK with FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 17 50 0.5
|
||||
* 18 50 1.0
|
||||
* 19 100 0.5
|
||||
* 20 100 1.0
|
||||
* 21 150 0.5
|
||||
* 22 200 0.5
|
||||
* 23 200 1.0
|
||||
* 24 300 0.5
|
||||
* PHY mode ID:
|
||||
* FSK without FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 1 50 0.5
|
||||
* 2 50 1.0
|
||||
* 3 100 0.5
|
||||
* 4 100 1.0
|
||||
* 5 150 0.5
|
||||
* 6 200 0.5
|
||||
* 7 200 1.0
|
||||
* 8 300 0.5
|
||||
*
|
||||
* OFDM:
|
||||
* PHY mode ID | Option | MCS | Data rate (kbps)
|
||||
* 34 1 2 400
|
||||
* 35 1 3 800
|
||||
* 36 1 4 1200
|
||||
* 37 1 5 1600
|
||||
* 38 1 6 2400
|
||||
* 51 2 3 400
|
||||
* 52 2 4 600
|
||||
* 53 2 5 800
|
||||
* 54 2 6 1200
|
||||
* 68 3 4 300
|
||||
* 69 3 5 400
|
||||
* 70 3 6 600
|
||||
* 84 4 4 150
|
||||
* 85 4 5 200
|
||||
* 86 4 6 300
|
||||
* FSK with FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 17 50 0.5
|
||||
* 18 50 1.0
|
||||
* 19 100 0.5
|
||||
* 20 100 1.0
|
||||
* 21 150 0.5
|
||||
* 22 200 0.5
|
||||
* 23 200 1.0
|
||||
* 24 300 0.5
|
||||
*
|
||||
* if value of 255 is given then previous value is used.
|
||||
* OFDM:
|
||||
* PHY mode ID | Option | MCS | Data rate (kbps)
|
||||
* 34 1 2 400
|
||||
* 35 1 3 800
|
||||
* 36 1 4 1200
|
||||
* 37 1 5 1600
|
||||
* 38 1 6 2400
|
||||
* 51 2 3 400
|
||||
* 52 2 4 600
|
||||
* 53 2 5 800
|
||||
* 54 2 6 1200
|
||||
* 68 3 4 300
|
||||
* 69 3 5 400
|
||||
* 70 3 6 600
|
||||
* 84 4 4 150
|
||||
* 85 4 5 200
|
||||
* 86 4 6 300
|
||||
*
|
||||
* Channel plan ID:
|
||||
* North America (NA): (1), (2), (5)
|
||||
* Brazil (BZ): (1), (2), (5)
|
||||
*
|
||||
* If value of 0 is given then previous value is used.
|
||||
* If value of 255 is given then default value is used.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param phy_mode_id PHY mode ID. Default 255 (not used).
|
||||
* \param regulatory_domain Regulatory domain.
|
||||
* \param phy_mode_id PHY mode ID.
|
||||
* \param channel_plan_id Channel plan ID.
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
* \return 0, OK.
|
||||
* \return <0 Fail.
|
||||
*/
|
||||
int ws_management_phy_mode_id_set(
|
||||
int ws_management_domain_configuration_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id);
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id);
|
||||
|
||||
/**
|
||||
* Configure Channel plan ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
*
|
||||
* Change the default channel configuration for Wi-SUN.
|
||||
*
|
||||
* Supported values: TBD
|
||||
*
|
||||
* if value of 255 is given then previous value is used.
|
||||
* Get domain configuration of Wi-SUN stack.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param channel_plan_id Channel plan ID. Default 255 (not used).
|
||||
* \param regulatory_domain Regulatory domain.
|
||||
* \param phy_mode_id PHY mode ID.
|
||||
* \param channel_plan_id Channel plan ID.
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
* \return 0, OK.
|
||||
* \return <0 Fail.
|
||||
*/
|
||||
int ws_management_channel_plan_id_set(
|
||||
int ws_management_domain_configuration_get(
|
||||
int8_t interface_id,
|
||||
uint8_t *regulatory_domain,
|
||||
uint8_t *phy_mode_id,
|
||||
uint8_t *channel_plan_id);
|
||||
|
||||
/**
|
||||
* Validate domain configuration of Wi-SUN stack.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param regulatory_domain Regulatory domain.
|
||||
* \param phy_mode_id PHY mode ID.
|
||||
* \param channel_plan_id Channel plan ID.
|
||||
*
|
||||
* \return 0, OK.
|
||||
* \return <0 Fail.
|
||||
*/
|
||||
int ws_management_domain_configuration_validate(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id);
|
||||
|
||||
/**
|
||||
|
@ -701,6 +828,25 @@ int ws_stack_info_get(
|
|||
int8_t interface_id,
|
||||
ws_stack_info_t *info_ptr);
|
||||
|
||||
/**
|
||||
* Get Neighbor table information from stack.
|
||||
*
|
||||
* To allocate correct amount of memory first use the API with NULL to get current amount
|
||||
* of neighbors. Then Allocate the memory and call the function to fill the table.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param neighbor_ptr Pointer to memory where Neighbor table entries can be written.
|
||||
* \param count amount of neighbor table entries allocated to memory.
|
||||
*
|
||||
* \return >=0 Success with amount of entries written in table.
|
||||
* \return >=0 if neighbor_ptr is NULL returns the amount of neighbors currently.
|
||||
* \return <0 Failure.
|
||||
*/
|
||||
int ws_neighbor_info_get(
|
||||
int8_t interface_id,
|
||||
ws_neighbour_info_t *neighbor_ptr,
|
||||
uint16_t count);
|
||||
|
||||
/**
|
||||
* Set minimum RF sensitivity acceptable for the parent selection
|
||||
*
|
||||
|
|
|
@ -83,7 +83,10 @@
|
|||
#define TRACE_GROUP "6lo"
|
||||
|
||||
/* Data rate for application used in Stagger calculation */
|
||||
#define STAGGER_DATARATE_FOR_APPL(n) ((n)*25/100)
|
||||
#define STAGGER_DATARATE_FOR_APPL(n) ((n)*75/100)
|
||||
|
||||
/* Time after network is considered stable and smaller stagger values can be given*/
|
||||
#define STAGGER_STABLE_NETWORK_TIME 3600*4
|
||||
|
||||
#ifdef HAVE_RPL
|
||||
rpl_domain_t *protocol_6lowpan_rpl_domain;
|
||||
|
@ -839,7 +842,7 @@ bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_am
|
|||
datarate = 250000;
|
||||
} else if (ws_info(cur_interface)) {
|
||||
network_size = ws_common_network_size_estimate_get(cur_interface);
|
||||
datarate = ws_common_datarate_get(cur_interface);
|
||||
datarate = ws_common_usable_application_datarate_get(cur_interface);
|
||||
} else {
|
||||
// 6LoWPAN ND
|
||||
network_size = 1000;
|
||||
|
@ -850,11 +853,23 @@ bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_am
|
|||
// If no data amount given, use 1kB
|
||||
data_amount = 1;
|
||||
}
|
||||
if (datarate < 25000) {
|
||||
// Minimum data rate used in calculations is 25kbs to prevent invalid values
|
||||
datarate = 25000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not occupy whole bandwidth, leave space for network formation etc...
|
||||
*/
|
||||
datarate = STAGGER_DATARATE_FOR_APPL(datarate);
|
||||
if (ws_info(cur_interface) &&
|
||||
(ws_common_connected_time_get(cur_interface) > STAGGER_STABLE_NETWORK_TIME || ws_common_authentication_time_get(cur_interface) == 0)) {
|
||||
// After four hours of network connected full bandwidth is given to application
|
||||
// Authentication has not been required during bootstrap so network load is much smaller
|
||||
} else {
|
||||
// Smaller data rate allowed as we have just joined to the network and Authentication was made
|
||||
datarate = STAGGER_DATARATE_FOR_APPL(datarate);
|
||||
}
|
||||
|
||||
stagger_value = 1 + ((data_amount * 1024 * 8 * network_size) / datarate);
|
||||
/**
|
||||
* Example:
|
||||
|
|
|
@ -2184,7 +2184,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t *
|
|||
// arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set
|
||||
rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false);
|
||||
rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
|
||||
rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur);
|
||||
rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, NULL, cur);
|
||||
}
|
||||
// Send unicast DIS to coordinator
|
||||
nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur);
|
||||
|
|
|
@ -964,6 +964,62 @@ int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_mac_mlme_max_csma_backoffs_set(int8_t interface_id, uint8_t csma_backoffs)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macMaxCSMABackoffs;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &csma_backoffs;
|
||||
set_req.value_size = 1;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_mac_mlme_be_set(int8_t interface_id, uint8_t min_be, uint8_t max_be)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macMinBE;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &min_be;
|
||||
set_req.value_size = 1;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
|
||||
set_req.attr = macMaxBE;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &max_be;
|
||||
set_req.value_size = 1;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_mac_mlme_data_request_restart_set(int8_t interface_id, mlme_request_restart_config_t *request_restart_config)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macRequestRestart;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = (void *)request_restart_config;
|
||||
set_req.value_size = sizeof(mlme_request_restart_config_t);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id)
|
||||
{
|
||||
|
|
|
@ -130,6 +130,12 @@ void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_dev
|
|||
|
||||
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);
|
||||
|
||||
int8_t mac_helper_mac_mlme_max_csma_backoffs_set(int8_t interface_id, uint8_t csma_backoffs);
|
||||
|
||||
int8_t mac_helper_mac_mlme_be_set(int8_t interface_id, uint8_t min_be, uint8_t max_be);
|
||||
|
||||
int8_t mac_helper_mac_mlme_data_request_restart_set(int8_t interface_id, mlme_request_restart_config_t *request_restart_config);
|
||||
|
||||
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id);
|
||||
|
||||
int8_t mac_helper_start_auto_cca_threshold(int8_t interface_id, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#ifndef MPX_API_H_
|
||||
#define MPX_API_H_
|
||||
|
||||
#include "mac_mcps.h"
|
||||
struct mcps_data_req_s;
|
||||
struct mcps_data_conf_s;
|
||||
struct mcps_data_ind_s;
|
||||
|
@ -30,9 +30,10 @@ typedef struct mpx_api_s mpx_api_t;
|
|||
* @param api API to handle the request
|
||||
* @param data MCPS-DATA.request specific values
|
||||
* @param user_id MPX user ID
|
||||
* @param priority priority level
|
||||
*
|
||||
*/
|
||||
typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id);
|
||||
typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id, mac_data_priority_t priority);
|
||||
|
||||
/**
|
||||
* @brief mpx_data_queue_clean clean MPX user data
|
||||
|
@ -82,6 +83,22 @@ typedef uint16_t mpx_header_size_get(const mpx_api_t *api, uint16_t user_id);
|
|||
*/
|
||||
typedef int8_t mpx_data_cb_register(const mpx_api_t *api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id);
|
||||
|
||||
/**
|
||||
* @brief mpx_eui64_purge_request Purge EUI-64 related data from MPX
|
||||
* @param api The API which handled the response
|
||||
* @param eui64 EUI-64 to purge
|
||||
*
|
||||
*/
|
||||
typedef void mpx_eui64_purge_request(const mpx_api_t *api, const uint8_t *eui64);
|
||||
|
||||
/**
|
||||
* \brief mpx_high_priority_mode_set Enable/Disable MPX high priority mode for TX process
|
||||
* @param api The API which handled the response
|
||||
* @param enable_mode True for enable High Priority mode, False disable
|
||||
*
|
||||
*/
|
||||
typedef void mpx_high_priority_mode_set(const mpx_api_t *api, bool enable_mode);
|
||||
|
||||
/**
|
||||
* \brief Struct mpx_api_s defines functions for MPX user for register call backs and send data.
|
||||
*/
|
||||
|
@ -90,6 +107,8 @@ struct mpx_api_s {
|
|||
mpx_data_purge_request *mpx_data_purge; /**< MPX data Purge. */
|
||||
mpx_header_size_get *mpx_headroom_size_get; /**< MPX headroom size get in bytes. */
|
||||
mpx_data_cb_register *mpx_user_registration; /**< MPX User cb registration must be call before enable to send or RX data*/
|
||||
mpx_eui64_purge_request *mpx_eui64_purge; /**< MPX Purge EUI-64 related data */
|
||||
mpx_high_priority_mode_set *mpx_priority_mode_set; /**< MPX request to enable / disable High Priority mode */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -699,7 +699,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *
|
|||
return -1;
|
||||
}
|
||||
|
||||
return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous, false);
|
||||
return DHCPv6_server_service_set_address_generation_anonymous(interface_id, prefix_ptr, anonymous, false);
|
||||
#else
|
||||
(void) interface_id;
|
||||
(void) prefix_ptr;
|
||||
|
|
|
@ -70,7 +70,7 @@ int_fast8_t arm_nwk_6lowpan_thread_test_add_neighbour(
|
|||
const uint8_t *id_mask,
|
||||
const uint8_t *route_data)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
|
@ -94,7 +94,7 @@ int_fast8_t arm_nwk_6lowpan_thread_test_remove_neighbour(
|
|||
int8_t interface_id,
|
||||
uint16_t neighbour_short_addr)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
|
@ -1220,7 +1220,7 @@ int8_t thread_test_initial_slaac_iid_set(int8_t interface_id, uint8_t *iid)
|
|||
|
||||
int8_t thread_test_router_id_request_send(int8_t interface_id, uint8_t status)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
|
|
@ -101,6 +101,7 @@ typedef struct {
|
|||
uint16_t indirect_big_packet_threshold;
|
||||
uint16_t max_indirect_big_packets_total;
|
||||
uint16_t max_indirect_small_packets_per_child;
|
||||
uint32_t last_rx_high_priority;
|
||||
bool fragmenter_active; /*!< Fragmenter state */
|
||||
adaptation_etx_update_cb *etx_update_cb;
|
||||
mpx_api_t *mpx_api;
|
||||
|
@ -109,6 +110,7 @@ typedef struct {
|
|||
} fragmenter_interface_t;
|
||||
|
||||
#define LOWPAN_ACTIVE_UNICAST_ONGOING_MAX 10
|
||||
#define LOWPAN_HIGH_PRIORITY_STATE_LENGTH 50 //5 seconds 100us ticks
|
||||
|
||||
/* Minimum buffer amount and memory size to ensure operation even in out of memory situation
|
||||
*/
|
||||
|
@ -116,6 +118,7 @@ typedef struct {
|
|||
#define LOWPAN_MEM_LIMIT_MIN_MEMORY 10000
|
||||
#define LOWPAN_MEM_LIMIT_REMOVE_NORMAL 3000 // Remove when approaching memory limit
|
||||
#define LOWPAN_MEM_LIMIT_REMOVE_MAX 10000 // Remove when at memory limit
|
||||
#define LOWPAN_MEM_LIMIT_REMOVE_EF_MODE 20000 // Remove when out of memory and we are in EF mode
|
||||
|
||||
|
||||
|
||||
|
@ -155,6 +158,7 @@ static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interf
|
|||
static fragmenter_tx_entry_t *lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
|
||||
|
||||
static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buffer_t *buf);
|
||||
static bool lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle);
|
||||
|
||||
static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm)
|
||||
{
|
||||
|
@ -251,6 +255,28 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
|
|||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
|
||||
static void lowpan_adaptation_tx_queue_write_to_front(fragmenter_interface_t *interface_ptr, buffer_t *buf)
|
||||
{
|
||||
buffer_t *lower_priority_buf = NULL;
|
||||
|
||||
ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) {
|
||||
|
||||
if (cur->priority <= buf->priority) {
|
||||
lower_priority_buf = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lower_priority_buf) {
|
||||
ns_list_add_before(&interface_ptr->directTxQueue, lower_priority_buf, buf);
|
||||
} else {
|
||||
ns_list_add_to_end(&interface_ptr->directTxQueue, buf);
|
||||
}
|
||||
interface_ptr->directTxQueue_size++;
|
||||
lowpan_adaptation_tx_queue_level_update(interface_ptr);
|
||||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
|
||||
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr)
|
||||
{
|
||||
// Currently this function is called only when data confirm is received for previously sent packet.
|
||||
|
@ -258,6 +284,12 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa
|
|||
return NULL;
|
||||
}
|
||||
ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) {
|
||||
|
||||
if (buf->link_specific.ieee802_15_4.requestAck && interface_ptr->last_rx_high_priority && buf->priority < QOS_EXPEDITE_FORWARD) {
|
||||
//Stop reading at this point when Priority is not enough big
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lowpan_buffer_tx_allowed(interface_ptr, buf)) {
|
||||
ns_list_remove(&interface_ptr->directTxQueue, buf);
|
||||
interface_ptr->directTxQueue_size--;
|
||||
|
@ -460,6 +492,7 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
|
|||
buffer_free_list(&interface_ptr->directTxQueue);
|
||||
interface_ptr->directTxQueue_size = 0;
|
||||
interface_ptr->directTxQueue_level = 0;
|
||||
interface_ptr->last_rx_high_priority = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -506,12 +539,30 @@ void lowpan_adaptation_free_heap(bool full_gc)
|
|||
{
|
||||
ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) {
|
||||
// Go through all interfaces and free small amount of memory
|
||||
// This is not very radical, but gives time to recover wthout causing too harsh changes
|
||||
lowpan_adaptation_free_low_priority_packets(interface_ptr->interface_id, full_gc ? LOWPAN_MEM_LIMIT_REMOVE_MAX : LOWPAN_MEM_LIMIT_REMOVE_NORMAL);
|
||||
// This is not very radical, but gives time to recover without causing too harsh changes
|
||||
buffer_priority_t priority = QOS_NORMAL;
|
||||
uint32_t amount = LOWPAN_MEM_LIMIT_REMOVE_NORMAL;
|
||||
|
||||
if (full_gc && interface_ptr->last_rx_high_priority) {
|
||||
// We have encountered out of memory in EF state We handle this as Critical state
|
||||
// Large amount of memory is freed and packets lower than EF priority can be dropped
|
||||
priority = QOS_NETWORK_CTRL;
|
||||
amount = LOWPAN_MEM_LIMIT_REMOVE_EF_MODE;
|
||||
} else if (interface_ptr->last_rx_high_priority) {
|
||||
// We are running out of memory and we are in EF state. We handle this as severe state
|
||||
// Some amount of memory is freed and also lower than EF priority packets are dropped
|
||||
priority = QOS_NETWORK_CTRL;
|
||||
amount = LOWPAN_MEM_LIMIT_REMOVE_MAX;
|
||||
} else if (full_gc) {
|
||||
// We have encountered out of memory. we need to remove more packets, but we only remove normal priority packets
|
||||
amount = LOWPAN_MEM_LIMIT_REMOVE_MAX;
|
||||
}
|
||||
|
||||
lowpan_adaptation_free_low_priority_packets(interface_ptr->interface_id, priority, amount);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount)
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, buffer_priority_t max_priority, uint32_t requested_amount)
|
||||
{
|
||||
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
|
||||
|
||||
|
@ -543,7 +594,7 @@ int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t
|
|||
|
||||
//Only remove last entries from TX queue with low priority
|
||||
ns_list_foreach_reverse_safe(buffer_t, entry, &interface_ptr->directTxQueue) {
|
||||
if (entry->priority == QOS_NORMAL) {
|
||||
if (entry->priority <= max_priority) {
|
||||
memory_freed += sizeof(buffer_t) + entry->size;
|
||||
packets_freed++;
|
||||
ns_list_remove(&interface_ptr->directTxQueue, entry);
|
||||
|
@ -1028,12 +1079,34 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
|
|||
buf->link_specific.ieee802_15_4.rf_channel_switch = false;
|
||||
}
|
||||
}
|
||||
//Define data priority
|
||||
mac_data_priority_t data_priority;
|
||||
|
||||
switch (buf->priority) {
|
||||
case QOS_HIGH:
|
||||
data_priority = MAC_DATA_MEDIUM_PRIORITY;
|
||||
break;
|
||||
case QOS_NETWORK_CTRL:
|
||||
data_priority = MAC_DATA_HIGH_PRIORITY;
|
||||
break;
|
||||
case QOS_EXPEDITE_FORWARD:
|
||||
data_priority = MAC_DATA_EXPEDITE_FORWARD;
|
||||
break;
|
||||
case QOS_MAC_BEACON:
|
||||
data_priority = MAC_DATA_HIGH_PRIORITY;
|
||||
break;
|
||||
default:
|
||||
data_priority = MAC_DATA_NORMAL_PRIORITY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (interface_ptr->mpx_api) {
|
||||
dataReq.ExtendedFrameExchange = buf->options.edfe_mode;
|
||||
interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id);
|
||||
interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id, data_priority);
|
||||
} else {
|
||||
cur->mac_api->mcps_data_req(cur->mac_api, &dataReq);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1075,9 +1148,119 @@ static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buff
|
|||
if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_unicast && interface_ptr->last_rx_high_priority && buf->priority < QOS_EXPEDITE_FORWARD) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t lowpan_adaptation_time_stamp_diff(uint32_t compare_stamp)
|
||||
{
|
||||
if (protocol_core_monotonic_time < compare_stamp) {
|
||||
return compare_stamp - protocol_core_monotonic_time;
|
||||
}
|
||||
return protocol_core_monotonic_time - compare_stamp;
|
||||
}
|
||||
|
||||
static bool lowpan_adaptation_high_priority_state_exit(fragmenter_interface_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr->last_rx_high_priority || lowpan_adaptation_time_stamp_diff(interface_ptr->last_rx_high_priority) < LOWPAN_HIGH_PRIORITY_STATE_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check First buffer_from tx queue
|
||||
buffer_t *buf = ns_list_get_first(&interface_ptr->directTxQueue);
|
||||
if (buf && buf->priority == QOS_EXPEDITE_FORWARD) {
|
||||
//TX queue must not include any
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check If we have a Any active TX process still active
|
||||
ns_list_foreach(fragmenter_tx_entry_t, entry, &interface_ptr->activeUnicastList) {
|
||||
if (entry->buf->priority == QOS_EXPEDITE_FORWARD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Disable High Priority Mode
|
||||
if (interface_ptr->mpx_api) {
|
||||
interface_ptr->mpx_api->mpx_priority_mode_set(interface_ptr->mpx_api, false);
|
||||
}
|
||||
interface_ptr->last_rx_high_priority = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lowpan_adaptation_high_priority_state_enable(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr)
|
||||
{
|
||||
|
||||
if (!interface_ptr->last_rx_high_priority) {
|
||||
// MPX enaled stack must inform MPX to priority enable
|
||||
if (interface_ptr->mpx_api) {
|
||||
interface_ptr->mpx_api->mpx_priority_mode_set(interface_ptr->mpx_api, true);
|
||||
}
|
||||
//Purge Active tx queue's all possible's
|
||||
if (!interface_ptr->fragmenter_active) {
|
||||
//Purge Only When Fragmenter is not active
|
||||
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, entry, &interface_ptr->activeUnicastList) {
|
||||
|
||||
if (lowpan_adaptation_purge_from_mac(cur, interface_ptr, entry->buf->seq)) {
|
||||
buffer_t *buf = entry->buf;
|
||||
ns_list_remove(&interface_ptr->activeUnicastList, entry);
|
||||
interface_ptr->activeTxList_size--;
|
||||
ns_dyn_mem_free(entry);
|
||||
//Add message to tx queue front based on priority. Now same priority at buf is prioritised at order
|
||||
lowpan_adaptation_tx_queue_write_to_front(interface_ptr, buf);
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Store timestamp for indicate last RX High Priority message
|
||||
interface_ptr->last_rx_high_priority = protocol_core_monotonic_time ? protocol_core_monotonic_time : 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void lowpan_adaptation_priority_status_update(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, buffer_priority_t priority)
|
||||
{
|
||||
if (priority == QOS_EXPEDITE_FORWARD) {
|
||||
lowpan_adaptation_high_priority_state_enable(cur, interface_ptr);
|
||||
} else {
|
||||
//Let check can we disable possible High Priority state
|
||||
lowpan_adaptation_high_priority_state_exit(interface_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void lowpan_adaptation_expedite_forward_enable(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id);
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
lowpan_adaptation_high_priority_state_enable(cur, interface_ptr);
|
||||
}
|
||||
|
||||
void lowpan_adaptation_interface_slow_timer(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id);
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lowpan_adaptation_high_priority_state_exit(interface_ptr)) {
|
||||
//Activate Packets from TX queue
|
||||
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
|
||||
while (buf_from_queue) {
|
||||
lowpan_adaptation_interface_tx(cur, buf_from_queue);
|
||||
buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
|
||||
}
|
||||
//Update Average QUEUE
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf)
|
||||
{
|
||||
bool is_room_for_new_message;
|
||||
|
@ -1105,6 +1288,8 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
|||
buffer_priority_set(buf, QOS_HIGH);
|
||||
}
|
||||
|
||||
//Update priority status
|
||||
lowpan_adaptation_priority_status_update(cur, interface_ptr, buf->priority);
|
||||
|
||||
//Check packet size
|
||||
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
|
||||
|
@ -1409,6 +1594,8 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
|
|||
}
|
||||
// When confirmation is for direct transmission, push all allowed buffers to MAC
|
||||
if (active_direct_confirm == true) {
|
||||
//Check Possibility for exit from High Priority state
|
||||
lowpan_adaptation_high_priority_state_exit(interface_ptr);
|
||||
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
|
||||
while (buf_from_queue) {
|
||||
lowpan_adaptation_interface_tx(cur, buf_from_queue);
|
||||
|
|
|
@ -38,7 +38,7 @@ int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_
|
|||
|
||||
void lowpan_adaptation_free_heap(bool full_gc);
|
||||
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount);
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, buffer_priority_t max_priority, uint32_t requested_amount);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -62,4 +62,8 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in
|
|||
|
||||
int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child);
|
||||
|
||||
void lowpan_adaptation_expedite_forward_enable(struct protocol_interface_info_entry *cur);
|
||||
|
||||
void lowpan_adaptation_interface_slow_timer(struct protocol_interface_info_entry *cur);
|
||||
|
||||
#endif /* LOWPAN_ADAPTATION_INTERFACE_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2021, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -38,16 +38,18 @@
|
|||
#include "RPL/rpl_data.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "Common_Protocols/icmpv6_radv.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "ws_management_api.h"
|
||||
#include "net_rpl.h"
|
||||
#include "Service_Libs/nd_proxy/nd_proxy.h"
|
||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "6LoWPAN/lowpan_adaptation_interface.h"
|
||||
#include "DHCPv6_Server/DHCPv6_server_service.h"
|
||||
#include "DHCPv6_client/dhcpv6_client_api.h"
|
||||
#include "libDHCPv6/libDHCPv6_vendordata.h"
|
||||
#include "libNET/src/net_dns_internal.h"
|
||||
|
||||
#include "platform/os_whiteboard.h"
|
||||
|
||||
#include "ws_bbr_api.h"
|
||||
|
||||
|
@ -197,7 +199,7 @@ static void ws_bbr_rpl_version_increase(protocol_interface_info_entry_t *cur)
|
|||
ws_bbr_rpl_version_timer_start(cur, rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag));
|
||||
}
|
||||
|
||||
void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase)
|
||||
void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase, uint32_t lifetime)
|
||||
{
|
||||
if (imin == 0 || doubling == 0) {
|
||||
// use default values
|
||||
|
@ -205,12 +207,33 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8
|
|||
doubling = WS_RPL_DIO_DOUBLING_SMALL;
|
||||
redundancy = WS_RPL_DIO_REDUNDANCY_SMALL;
|
||||
}
|
||||
uint8_t lifetime_unit = 60;
|
||||
uint8_t default_lifetime;
|
||||
|
||||
if (lifetime == 0) {
|
||||
// 2 hours default lifetime
|
||||
lifetime = 120 * 60;
|
||||
} else if (lifetime <= 250 * 60) {
|
||||
// Lifetime unit of 60 is ok up to 4 hours
|
||||
} else if (lifetime <= 250 * 120) {
|
||||
//more than 4 hours needs larger lifetime unit
|
||||
lifetime_unit = 120;
|
||||
} else if (lifetime <= 250 * 240) {
|
||||
lifetime_unit = 240;
|
||||
} else {
|
||||
// Maximum lifetime is 16 hours 40 minutes
|
||||
lifetime = 250 * 240;
|
||||
lifetime_unit = 240;
|
||||
}
|
||||
default_lifetime = lifetime / lifetime_unit;
|
||||
|
||||
if (rpl_conf.dio_interval_min == imin &&
|
||||
rpl_conf.dio_interval_doublings == doubling &&
|
||||
rpl_conf.dio_redundancy_constant == redundancy &&
|
||||
rpl_conf.dag_max_rank_increase == dag_max_rank_increase &&
|
||||
rpl_conf.min_hop_rank_increase == min_hop_rank_increase) {
|
||||
rpl_conf.min_hop_rank_increase == min_hop_rank_increase &&
|
||||
rpl_conf.default_lifetime == default_lifetime &&
|
||||
rpl_conf.lifetime_unit == lifetime_unit) {
|
||||
// Same values no update needed
|
||||
return;
|
||||
}
|
||||
|
@ -220,6 +243,8 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8
|
|||
rpl_conf.dio_redundancy_constant = redundancy;
|
||||
rpl_conf.dag_max_rank_increase = dag_max_rank_increase;
|
||||
rpl_conf.min_hop_rank_increase = min_hop_rank_increase;
|
||||
rpl_conf.default_lifetime = default_lifetime;
|
||||
rpl_conf.lifetime_unit = lifetime_unit;
|
||||
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf);
|
||||
|
@ -343,6 +368,34 @@ static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *u
|
|||
addr_policy_table_delete_entry(ula_prefix, 64);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 static non rooted self generated own address
|
||||
* 1 static address with backbone connectivity
|
||||
*/
|
||||
static uint8_t *ws_bbr_bb_static_prefix_get(uint8_t *dodag_id_ptr)
|
||||
{
|
||||
|
||||
/* Get static ULA prefix if we have configuration in backbone and there is address we use that.
|
||||
*
|
||||
* If there is no address we can use our own generated ULA as a backup ULA
|
||||
*/
|
||||
|
||||
protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
|
||||
|
||||
if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
|
||||
ns_list_foreach(if_address_entry_t, addr, &bb_interface->ip_addresses) {
|
||||
if (bitsequal(addr->address, bb_interface->ipv6_configure->static_prefix64, 64)) {
|
||||
// static address available in interface copy the prefix and return the address
|
||||
if (dodag_id_ptr) {
|
||||
memcpy(dodag_id_ptr, bb_interface->ipv6_configure->static_prefix64, 8);
|
||||
}
|
||||
return addr->address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
@ -350,6 +403,14 @@ static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
|
|||
// address generated
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *static_address_ptr = ws_bbr_bb_static_prefix_get(NULL);
|
||||
if (static_address_ptr) {
|
||||
memcpy(current_dodag_id, static_address_ptr, 16);
|
||||
tr_info("BBR Static DODAGID %s", trace_ipv6(current_dodag_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This address is only used if no other address available.
|
||||
if_address_entry_t *add_entry = ws_bbr_slaac_generate(cur, static_dodag_id_prefix);
|
||||
if (!add_entry) {
|
||||
|
@ -362,29 +423,6 @@ static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 static non rooted self generated own address
|
||||
* 1 static address with backbone connectivity
|
||||
*/
|
||||
static void ws_bbr_bb_static_prefix_get(uint8_t *dodag_id_ptr)
|
||||
{
|
||||
|
||||
/* Get static ULA prefix if we have configuration in backbone and there is address we use that.
|
||||
*
|
||||
* If there is no address we can use our own generated ULA as a backup ULA
|
||||
*/
|
||||
|
||||
protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
|
||||
|
||||
if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
|
||||
if (protocol_address_prefix_cmp(bb_interface, bb_interface->ipv6_configure->static_prefix64, 64)) {
|
||||
memcpy(dodag_id_ptr, bb_interface->ipv6_configure->static_prefix64, 8);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_ptr)
|
||||
{
|
||||
uint8_t global_address[16];
|
||||
|
@ -414,6 +452,7 @@ static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_p
|
|||
memcpy(global_prefix_ptr, global_address, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
@ -425,6 +464,8 @@ static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 1
|
|||
return;
|
||||
}
|
||||
|
||||
whiteboard_os_modify(target, ADD);
|
||||
|
||||
buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
|
||||
protocol_push(buffer);
|
||||
return;
|
||||
|
@ -478,7 +519,6 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
|
|||
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
|
||||
if (pre_resolved_dns_queries[n].domain_name != NULL) {
|
||||
ptr = net_dns_option_vendor_option_data_dns_query_write(ptr, pre_resolved_dns_queries[n].address, pre_resolved_dns_queries[n].domain_name);
|
||||
tr_info("set DNS query result for %s, addr: %s", pre_resolved_dns_queries[n].domain_name, tr_ipv6(pre_resolved_dns_queries[n].address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -486,6 +526,15 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
|
|||
DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
|
||||
}
|
||||
|
||||
static void wisun_dhcp_address_remove_cb(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info)
|
||||
{
|
||||
(void) interfaceId;
|
||||
(void) prefix_info;
|
||||
if (targetAddress) {
|
||||
whiteboard_os_modify(targetAddress, REMOVE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id, uint32_t dhcp_address_lifetime)
|
||||
{
|
||||
uint8_t ll[16];
|
||||
|
@ -499,9 +548,11 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
|
|||
tr_error("DHCPv6 Server create fail");
|
||||
return;
|
||||
}
|
||||
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
|
||||
//Enable SLAAC mode to border router
|
||||
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false);
|
||||
DHCPv6_server_service_callback_set(cur->id, global_id, wisun_dhcp_address_remove_cb, wisun_dhcp_address_add_cb);
|
||||
//Check for anonymous mode
|
||||
bool anonymous = (configuration & BBR_DHCP_ANONYMOUS) ? true : false;
|
||||
|
||||
DHCPv6_server_service_set_address_generation_anonymous(cur->id, global_id, anonymous, false);
|
||||
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, dhcp_address_lifetime);
|
||||
//SEt max value for not limiting address allocation
|
||||
DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE);
|
||||
|
@ -510,6 +561,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
|
|||
|
||||
ws_dhcp_client_address_request(cur, global_id, ll);
|
||||
}
|
||||
|
||||
static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
|
||||
{
|
||||
if (!cur) {
|
||||
|
@ -626,9 +678,16 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
*/
|
||||
if ((configuration & BBR_ULA_C) == 0 && memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
|
||||
//Global prefix not available count if backup ULA should be created
|
||||
uint32_t prefix_wait_time = BBR_BACKUP_ULA_DELAY;
|
||||
global_prefix_unavailable_timer += BBR_CHECK_INTERVAL;
|
||||
tr_debug("Check for backup prefix %"PRIu32"", global_prefix_unavailable_timer);
|
||||
if (global_prefix_unavailable_timer >= BBR_BACKUP_ULA_DELAY) {
|
||||
|
||||
if (NULL != ws_bbr_bb_static_prefix_get(NULL)) {
|
||||
// If we have a static configuration we activate it faster.
|
||||
prefix_wait_time = 40;
|
||||
}
|
||||
|
||||
tr_debug("Check for backup prefix %"PRIu32" / %"PRIu32"", prefix_wait_time, global_prefix_unavailable_timer);
|
||||
if (global_prefix_unavailable_timer >= prefix_wait_time) {
|
||||
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
|
||||
tr_info("start using backup prefix %s", trace_ipv6_prefix(local_prefix, 64));
|
||||
}
|
||||
|
@ -850,6 +909,18 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ws_bbr_forwarding_cb(protocol_interface_info_entry_t *interface, buffer_t *buf)
|
||||
{
|
||||
uint8_t traffic_class = buf->options.traffic_class >> IP_TCLASS_DSCP_SHIFT;
|
||||
|
||||
if (traffic_class == IP_DSCP_EF) {
|
||||
//indicate EF forwarding to adaptation
|
||||
lowpan_adaptation_expedite_forward_enable(interface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ws_bbr_init(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
(void) interface;
|
||||
|
@ -862,6 +933,7 @@ void ws_bbr_init(protocol_interface_info_entry_t *interface)
|
|||
ws_bbr_fhss_bsi = ws_bbr_bsi_read(&bbr_info_nvm_tlv);
|
||||
tr_debug("Read BSI %u from NVM", ws_bbr_fhss_bsi);
|
||||
}
|
||||
interface->if_common_forwarding_out_cb = &ws_bbr_forwarding_cb;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1401,6 +1473,7 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
|
|||
if (address) {
|
||||
// Update address
|
||||
memcpy(pre_resolved_dns_queries[n].address, address, 16);
|
||||
tr_info("Update DNS query result for %s, addr: %s", pre_resolved_dns_queries[n].domain_name, tr_ipv6(pre_resolved_dns_queries[n].address));
|
||||
} else {
|
||||
// delete entry
|
||||
memset(pre_resolved_dns_queries[n].address, 0, 16);
|
||||
|
@ -1423,6 +1496,7 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
|
|||
}
|
||||
memcpy(pre_resolved_dns_queries[n].address, address, 16);
|
||||
strcpy(pre_resolved_dns_queries[n].domain_name, domain_name_ptr);
|
||||
tr_info("set DNS query result for %s, addr: %s", pre_resolved_dns_queries[n].domain_name, tr_ipv6(pre_resolved_dns_queries[n].address));
|
||||
goto update_information;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur);
|
|||
|
||||
uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase);
|
||||
void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase, uint32_t lifetime);
|
||||
|
||||
void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint32_t dhcp_address_lifetime);
|
||||
|
||||
|
@ -45,7 +45,7 @@ void ws_bbr_init(protocol_interface_info_entry_t *interface);
|
|||
#define ws_bbr_seconds_timer( cur, seconds)
|
||||
#define ws_bbr_pan_version_increase(cur)
|
||||
#define ws_bbr_pan_size(cur) 0
|
||||
#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase)
|
||||
#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase, lifetime)
|
||||
#define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime)
|
||||
#define ws_bbr_ready_to_start(cur) true
|
||||
#define ws_bbr_backbone_address_get(address) 0
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,9 @@ typedef enum {
|
|||
WS_DISCOVERY_START, /**< discovery start*/
|
||||
WS_CONFIGURATION_START, /**< configuration learn start*/
|
||||
WS_OPERATION_START, /**< active operation start*/
|
||||
WS_ROUTING_READY /**< RPL routing connected to BR*/
|
||||
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_bootsrap_event_type_e;
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
@ -34,6 +36,7 @@ struct ws_us_ie;
|
|||
struct ws_bs_ie;
|
||||
struct ws_neighbor_class_entry;
|
||||
struct ws_stack_info;
|
||||
struct ws_neighbour_info;
|
||||
|
||||
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
|
||||
|
||||
|
@ -60,6 +63,8 @@ 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);
|
||||
|
@ -92,7 +97,9 @@ void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry
|
|||
|
||||
void ws_bootstrap_neighbor_set_stable(struct protocol_interface_info_entry *interface, const uint8_t *src64);
|
||||
|
||||
int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr);
|
||||
int ws_bootstrap_stack_info_get(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr);
|
||||
|
||||
int ws_bootstrap_neighbor_info_get(protocol_interface_info_entry_t *cur, struct ws_neighbour_info *neighbor_ptr, uint16_t table_max);
|
||||
|
||||
void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time);
|
||||
|
||||
|
@ -106,7 +113,8 @@ void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_ent
|
|||
#define ws_bootstrap_neighbor_set_stable(interface, src64)
|
||||
#define ws_bootstrap_primary_parent_update(interface, neighbor)
|
||||
#define ws_bootstrap_secondary_parent_update(interface)
|
||||
#define ws_bootstrap_get_info(cur, info_ptr)
|
||||
#define ws_bootstrap_stack_info_get(cur, info_ptr)
|
||||
#define ws_bootstrap_neighbor_info_get(cur, neighbor_ptr, count)
|
||||
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -98,10 +98,10 @@ typedef struct cfg_devices_in_config {
|
|||
*
|
||||
*/
|
||||
const cfg_devices_in_config_t devices_by_datarate[] = {
|
||||
{ 1, 4, 10, 25}, // Configuration for 50 -100kbs
|
||||
{ 1, 8, 15, 25}, // Configuration for 150kbs - 200kbs
|
||||
{ 2, 15, 25, 50}, // Configuration for 300kbs
|
||||
{ 3, 20, 40, 100}, // Configuration for 600kbs - 2400kbs
|
||||
{ 1, 5, 10, 25}, // Configuration for 50 -100kbs
|
||||
{ 1, 10, 20, 40}, // Configuration for 150kbs - 200kbs
|
||||
{ 1, 15, 30, 60}, // Configuration for 300kbs
|
||||
{ 2, 20, 50, 100}, // Configuration for 600kbs - 2400kbs
|
||||
};
|
||||
|
||||
|
||||
|
@ -301,6 +301,8 @@ 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;
|
||||
|
||||
/* 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) {
|
||||
|
@ -309,7 +311,7 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
|
|||
}
|
||||
|
||||
uint8_t set_flags = 0;
|
||||
if (cfg->network_size == NETWORK_SIZE_AUTOMATIC) {
|
||||
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
|
||||
|
@ -336,12 +338,45 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
|
|||
}
|
||||
|
||||
// If is in an automatic network size mode, updates automatic configuration
|
||||
if (cfg->network_size == NETWORK_SIZE_AUTOMATIC && cur) {
|
||||
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;
|
||||
}
|
||||
|
||||
static uint8_t ws_cfg_config_get_by_size(protocol_interface_info_entry_t *cur, uint8_t network_size)
|
||||
{
|
||||
(void)cur;
|
||||
|
||||
ws_phy_cfg_t phy_cfg;
|
||||
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
|
||||
return CONFIG_SMALL;
|
||||
}
|
||||
uint32_t data_rate = ws_common_datarate_get_from_phy_mode(phy_cfg.phy_mode_id, phy_cfg.operating_mode);
|
||||
|
||||
uint8_t index;
|
||||
if (data_rate < 150000) {
|
||||
index = 0;
|
||||
} else if (data_rate < 300000) {
|
||||
index = 1;
|
||||
} else if (data_rate < 600000) {
|
||||
index = 2;
|
||||
} else {
|
||||
index = 3;
|
||||
}
|
||||
|
||||
if (network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
return CONFIG_CERTIFICATE;
|
||||
} else if (network_size <= devices_by_datarate[index].max_for_small) {
|
||||
return CONFIG_SMALL;
|
||||
} else if (network_size <= devices_by_datarate[index].max_for_medium) {
|
||||
return CONFIG_MEDIUM;
|
||||
} else if (network_size <= devices_by_datarate[index].max_for_large) {
|
||||
return CONFIG_LARGE;
|
||||
}
|
||||
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
|
||||
|
@ -362,18 +397,18 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1
|
|||
memcpy(nw_size_external_cfg, &new_nw_size_cfg, sizeof(ws_cfg_nw_size_t));
|
||||
}
|
||||
|
||||
// Small
|
||||
if (network_size < 100) {
|
||||
// Automatic
|
||||
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 (network_size < 800) {
|
||||
// Medium
|
||||
} 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 (network_size < 1500) {
|
||||
// Medium
|
||||
} 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 {
|
||||
// Large
|
||||
ws_cfg_network_size_config_set_xlarge(&new_nw_size_cfg);
|
||||
}
|
||||
|
||||
|
@ -398,33 +433,8 @@ cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_
|
|||
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
|
||||
return CONFIG_SMALL;
|
||||
}
|
||||
ws_phy_cfg_t phy_cfg;
|
||||
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
|
||||
return CONFIG_SMALL;
|
||||
}
|
||||
|
||||
uint32_t data_rate = ws_get_datarate_using_operating_mode(phy_cfg.operating_mode);
|
||||
uint8_t index;
|
||||
if (data_rate < 150000) {
|
||||
index = 0;
|
||||
} else if (data_rate < 300000) {
|
||||
index = 1;
|
||||
} else if (data_rate < 600000) {
|
||||
index = 2;
|
||||
} else {
|
||||
index = 3;
|
||||
}
|
||||
|
||||
if (cfg.network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
return CONFIG_CERTIFICATE;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_small) {
|
||||
return CONFIG_SMALL;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_medium) {
|
||||
return CONFIG_MEDIUM;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_large) {
|
||||
return CONFIG_LARGE;
|
||||
}
|
||||
return CONFIG_XLARGE;
|
||||
return ws_cfg_config_get_by_size(cur, cfg.network_size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -448,6 +458,7 @@ static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg)
|
|||
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
|
||||
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME;
|
||||
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
|
||||
|
||||
// EAPOL configuration
|
||||
|
@ -456,8 +467,6 @@ static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg)
|
|||
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
||||
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
||||
|
||||
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
|
||||
|
||||
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -492,6 +501,7 @@ static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg)
|
|||
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10
|
||||
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_MEDIUM;
|
||||
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
|
||||
|
||||
// EAPOL configuration
|
||||
|
@ -500,8 +510,6 @@ static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg)
|
|||
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
||||
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
||||
|
||||
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
|
||||
|
||||
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->sec_prot.initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->sec_prot.initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -522,7 +530,7 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
|
|||
cfg->gen.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
||||
|
||||
// Configure the Wi-SUN timing trickle parameters
|
||||
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 2; // 240 seconds
|
||||
cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS << 1; // 120 seconds
|
||||
cfg->timing.disc_trickle_imax = 1536; // 1536 seconds; 25 minutes
|
||||
cfg->timing.disc_trickle_k = 1;
|
||||
cfg->timing.pan_timeout = PAN_VERSION_LARGE_NETWORK_TIMEOUT;
|
||||
|
@ -530,11 +538,12 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
|
|||
cfg->timing.temp_eapol_min_timeout = WS_EAPOL_TEMPORARY_ENTRY_LARGE_TIMEOUT;
|
||||
|
||||
// RPL configuration
|
||||
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 18; 262s, 4.5min
|
||||
cfg->bbr.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 18; 256s, 4.5min
|
||||
cfg->bbr.dio_interval_doublings = WS_RPL_DIO_DOUBLING_LARGE; // 3; 2048s, 34min
|
||||
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10
|
||||
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_LARGE;
|
||||
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
|
||||
|
||||
// EAPOL configuration
|
||||
|
@ -543,8 +552,6 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg)
|
|||
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
||||
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
|
||||
|
||||
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
|
||||
|
||||
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->sec_prot.initial_key_imin = LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->sec_prot.initial_key_imax = LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -579,6 +586,7 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg)
|
|||
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_XLARGE; // 10
|
||||
cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_XLARGE;
|
||||
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE;
|
||||
|
||||
// EAPOL configuration
|
||||
|
@ -587,8 +595,6 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg)
|
|||
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
||||
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE;
|
||||
|
||||
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE;
|
||||
|
||||
cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->sec_prot.initial_key_imin = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->sec_prot.initial_key_imax = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -622,6 +628,7 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg)
|
|||
cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled
|
||||
cfg->bbr.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->bbr.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME;
|
||||
cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL;
|
||||
|
||||
// EAPOL configuration
|
||||
|
@ -630,8 +637,6 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg)
|
|||
cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS;
|
||||
cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
||||
|
||||
cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL;
|
||||
|
||||
cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -698,6 +703,7 @@ int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, w
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
@ -883,6 +889,7 @@ int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *
|
|||
cur->ws_info->trickle_params_pan_discovery.Imax = new_cfg->disc_trickle_imax * 10;
|
||||
cur->ws_info->trickle_params_pan_discovery.k = new_cfg->disc_trickle_k;
|
||||
cur->ws_info->trickle_params_pan_discovery.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE;
|
||||
ws_pae_controller_configure(cur, NULL, NULL, new_cfg);
|
||||
}
|
||||
|
||||
if (cfg == new_cfg) {
|
||||
|
@ -909,6 +916,7 @@ static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg)
|
|||
cfg->dio_redundancy_constant = 10;
|
||||
cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE;
|
||||
cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE;
|
||||
cfg->rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_MEDIUM;
|
||||
cfg->dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM;
|
||||
|
||||
return CFG_SETTINGS_OK;
|
||||
|
@ -932,7 +940,8 @@ int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg)
|
|||
cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant ||
|
||||
cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase ||
|
||||
cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase ||
|
||||
cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime) {
|
||||
cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime ||
|
||||
cfg->rpl_default_lifetime != new_cfg->rpl_default_lifetime) {
|
||||
return CFG_SETTINGS_CHANGED;
|
||||
}
|
||||
|
||||
|
@ -954,7 +963,7 @@ int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, w
|
|||
// cur is optional, default values are for Wi-SUN small network parameters,
|
||||
ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings,
|
||||
new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase,
|
||||
new_cfg->min_hop_rank_increase);
|
||||
new_cfg->min_hop_rank_increase, new_cfg->rpl_default_lifetime);
|
||||
ws_bbr_dhcp_address_lifetime_set(cur, new_cfg->dhcp_address_lifetime);
|
||||
}
|
||||
|
||||
|
@ -1210,7 +1219,7 @@ int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_c
|
|||
}
|
||||
|
||||
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
||||
ws_pae_controller_configure(cur, new_cfg, NULL);
|
||||
ws_pae_controller_configure(cur, new_cfg, NULL, NULL);
|
||||
}
|
||||
|
||||
if (cfg == new_cfg) {
|
||||
|
@ -1230,7 +1239,8 @@ static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg)
|
|||
cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX;
|
||||
cfg->sec_prot_trickle_timer_exp = 2;
|
||||
cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL;
|
||||
cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM;
|
||||
cfg->max_simult_sec_neg_tx_queue_min = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MIN;
|
||||
cfg->max_simult_sec_neg_tx_queue_max = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MAX;
|
||||
cfg->initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER;
|
||||
cfg->initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS;
|
||||
cfg->initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS;
|
||||
|
@ -1256,7 +1266,8 @@ int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_c
|
|||
cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax ||
|
||||
cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp ||
|
||||
cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout ||
|
||||
cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication ||
|
||||
cfg->max_simult_sec_neg_tx_queue_min != new_cfg->max_simult_sec_neg_tx_queue_min ||
|
||||
cfg->max_simult_sec_neg_tx_queue_max != new_cfg->max_simult_sec_neg_tx_queue_max ||
|
||||
cfg->initial_key_retry_delay != new_cfg->initial_key_retry_delay ||
|
||||
cfg->initial_key_imin != new_cfg->initial_key_retry_delay ||
|
||||
cfg->initial_key_imax != new_cfg->initial_key_retry_delay ||
|
||||
|
@ -1277,7 +1288,7 @@ int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg
|
|||
}
|
||||
|
||||
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
||||
ws_pae_controller_configure(cur, NULL, new_cfg);
|
||||
ws_pae_controller_configure(cur, NULL, new_cfg, NULL);
|
||||
}
|
||||
|
||||
if (cfg == new_cfg) {
|
||||
|
@ -1438,7 +1449,7 @@ uint32_t ws_cfg_neighbour_temporary_lifetime_get(void)
|
|||
}
|
||||
void ws_cfg_neighbour_temporary_lifetime_set(uint32_t lifetime)
|
||||
{
|
||||
if (lifetime >= WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME || lifetime == 0) {
|
||||
if (lifetime > WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME || lifetime == 0) {
|
||||
if (lifetime > WS_NEIGHBOR_LINK_TIMEOUT) {
|
||||
lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct ws_bbr_cfg_s {
|
|||
uint16_t dag_max_rank_increase;
|
||||
uint16_t min_hop_rank_increase;
|
||||
uint32_t dhcp_address_lifetime; /**< DHCP address lifetime in seconds minimum 2 hours and maximum as days hours*/
|
||||
uint32_t rpl_default_lifetime; /**< RPL default lifetime value minimum from 30 minutes to 16 hours*/
|
||||
} ws_bbr_cfg_t;
|
||||
|
||||
/**
|
||||
|
@ -114,7 +115,8 @@ typedef struct ws_sec_prot_cfg_s {
|
|||
uint16_t sec_prot_trickle_imin; /**< Security protocol trickle parameters Imin; seconds; default 30 */
|
||||
uint16_t sec_prot_trickle_imax; /**< Security protocol trickle parameters Imax; seconds; default 90 */
|
||||
uint8_t sec_prot_trickle_timer_exp; /**< Security protocol trickle timer expirations; default 2 */
|
||||
uint16_t sec_max_ongoing_authentication; /**< Pae authenticator max Accept ongoing authentication count */
|
||||
uint16_t max_simult_sec_neg_tx_queue_min; /**< PAE authenticator max simultaneous security negotiations TX queue minimum */
|
||||
uint16_t max_simult_sec_neg_tx_queue_max; /**< PAE authenticator max simultaneous security negotiations TX queue maximum */
|
||||
uint16_t initial_key_retry_delay; /**< Delay before starting initial key trickle; seconds; default 120 */
|
||||
uint16_t initial_key_imin; /**< Initial key trickle Imin; seconds; default 360 */
|
||||
uint16_t initial_key_imax; /**< Initial key trickle Imax; seconds; default 720 */
|
||||
|
|
|
@ -34,6 +34,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_stats.h"
|
||||
#include "Service_Libs/etx/etx.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
#include "Service_Libs/blacklist/blacklist.h"
|
||||
|
@ -223,7 +224,7 @@ phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t oper
|
|||
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule)
|
||||
{
|
||||
(void)cur;
|
||||
if (ws_get_datarate_using_operating_mode(hopping_schdule->operating_mode) == 0) {
|
||||
if (ws_common_datarate_get_from_phy_mode(hopping_schdule->phy_mode_id, hopping_schdule->operating_mode) == 0) {
|
||||
//Unsupported operation mode
|
||||
return -1;
|
||||
}
|
||||
|
@ -629,6 +630,7 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte
|
|||
ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime);
|
||||
tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
|
||||
|
||||
ws_stats_update(interface, STATS_WS_CHILD_ADD, 1);
|
||||
return ARO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -639,9 +641,7 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con
|
|||
return false;
|
||||
}
|
||||
|
||||
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index);
|
||||
ws_neighbor->negative_aro_send = true;
|
||||
neighbour->lifetime = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; //Remove anyway if Packet is freed before MAC push
|
||||
ws_bootstrap_mac_neighbor_short_time_set(interface, eui64, WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -663,11 +663,37 @@ uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur)
|
|||
return latency;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return ws_get_datarate_using_operating_mode(operating_mode);
|
||||
}
|
||||
|
||||
uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
return ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
return ws_common_datarate_get_from_phy_mode(cur->ws_info->hopping_schdule.phy_mode_id, cur->ws_info->hopping_schdule.operating_mode);
|
||||
}
|
||||
|
||||
uint32_t ws_common_usable_application_datarate_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
/* Usable data rate is a available data rate when removed ACK and wait times required to send a packet
|
||||
*
|
||||
* Estimated to be around 70% with following assumptions with 150kbs data rate
|
||||
* Average ACK size 48 bytes
|
||||
* Average tACK 2ms
|
||||
* Average CCA check time + processing 7ms
|
||||
* Delays in bytes with 150kbs data rate 168 + 48 bytes for ACK 216 bytes
|
||||
* Usable data rate is 1 - 216/(216 + 500) about 70%
|
||||
*/
|
||||
return 70 * ws_common_datarate_get_from_phy_mode(cur->ws_info->hopping_schdule.phy_mode_id, cur->ws_info->hopping_schdule.operating_mode) / 100;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
uint32_t network_size_estimate = 100;
|
||||
|
@ -680,6 +706,30 @@ uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cu
|
|||
return network_size_estimate;
|
||||
}
|
||||
|
||||
uint32_t ws_common_connected_time_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!ws_info(cur)) {
|
||||
return 0;
|
||||
}
|
||||
if (cur->ws_info->connected_time == 0) {
|
||||
// We are not connected
|
||||
return 0;
|
||||
}
|
||||
return cur->ws_info->uptime - cur->ws_info->connected_time;
|
||||
}
|
||||
|
||||
uint32_t ws_common_authentication_time_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!ws_info(cur)) {
|
||||
return 0;
|
||||
}
|
||||
if (cur->ws_info->authentication_time == 0) {
|
||||
// Authentication was not done when joined to network so time is not known
|
||||
return 0;
|
||||
}
|
||||
return cur->ws_info->uptime - cur->ws_info->authentication_time;
|
||||
}
|
||||
|
||||
void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor)
|
||||
{
|
||||
ws_bootstrap_primary_parent_update(interface, neighbor);
|
||||
|
@ -690,4 +740,14 @@ void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interfac
|
|||
ws_bootstrap_secondary_parent_update(interface);
|
||||
}
|
||||
|
||||
void ws_common_border_router_alive_update(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// After successful DAO ACK connection to border router is verified
|
||||
interface->ws_info->pan_timeout_timer = interface->ws_info->cfg->timing.pan_timeout;
|
||||
}
|
||||
|
||||
#endif // HAVE_WS
|
||||
|
|
|
@ -97,7 +97,10 @@ typedef struct ws_info_s {
|
|||
ws_bsi_block_t ws_bsi_block;
|
||||
uint16_t aro_registration_timer; /**< Aro registration timer */
|
||||
uint16_t rpl_version_timer; /**< RPL version update timeout */
|
||||
uint32_t pan_timeout_timer; /**< routers will fallback to previous state after this */
|
||||
uint32_t pan_timeout_timer; /**< routers will fallback to previous state after this */
|
||||
uint32_t uptime; /**< Seconds after interface has been started */
|
||||
uint32_t authentication_time; /**< When the last authentication was performed */
|
||||
uint32_t connected_time; /**< Time we have been connected to network */
|
||||
uint32_t pan_config_sol_max_timeout;
|
||||
uint8_t gtkhash[32];
|
||||
uint16_t network_pan_id;
|
||||
|
@ -164,15 +167,25 @@ uint32_t ws_common_version_timeout_get(uint8_t config);
|
|||
|
||||
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);
|
||||
|
||||
uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint32_t ws_common_usable_application_datarate_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint32_t ws_common_connected_time_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint32_t ws_common_authentication_time_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);
|
||||
|
||||
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);
|
||||
|
||||
#define ws_info(cur) ((cur)->ws_info)
|
||||
#else
|
||||
#define ws_info(cur) ((ws_info_t *) NULL)
|
||||
|
@ -185,10 +198,15 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size);
|
|||
#define ws_common_allow_child_registration(cur, eui64, aro_timeout) (2)
|
||||
#define ws_common_negative_aro_mark(interface, eui64)(false)
|
||||
#define ws_common_latency_estimate_get(cur) 0
|
||||
#define ws_common_datarate_get_from_phy_mode(phy_mode_id, operating_mode) 0
|
||||
#define ws_common_datarate_get(cur) 0
|
||||
#define ws_common_usable_application_datarate_get(cur) 0
|
||||
#define ws_common_network_size_estimate_get(cur) 0
|
||||
#define ws_common_connected_time_get(cur) 0
|
||||
#define ws_common_authentication_time_get(cur) 0
|
||||
#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)
|
||||
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -239,6 +239,13 @@ typedef struct ws_bs_ie {
|
|||
#define MPX_KEY_MANAGEMENT_ENC_USER_ID 0x0001 /**< MPX Key management user ID */
|
||||
#define MPX_LOWPAN_ENC_USER_ID 0xA0ED /**< MPX Lowpan User Id */
|
||||
|
||||
/*
|
||||
* Wi-SUN MPX MTU size
|
||||
*
|
||||
*/
|
||||
|
||||
#define WS_MPX_MAX_MTU 1576
|
||||
|
||||
#define WS_FAN_VERSION_1_0 1
|
||||
|
||||
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
|
||||
|
@ -319,10 +326,10 @@ typedef struct ws_bs_ie {
|
|||
|
||||
|
||||
/* WS requires at least 19 MAC retransmissions (total 1+19=20 attempts). Default 802.15.4 macMaxFrameRetries is 3 (total 1+3=4 attempts).
|
||||
* At least 4 channel retries must be used: (Initial channel + WS_NUMBER_OF_CHANNEL_RETRIES) * MAC attempts = (1+4)*4=20 attempts
|
||||
* At least 4 request restarts must be used: (Initial channel + WS_TX_REQUEST_RESTART_MAX) * MAC attempts = (1+4)*4=20 attempts
|
||||
*
|
||||
* Valid settings could be for example:
|
||||
* WS_MAX_FRAME_RETRIES WS_NUMBER_OF_CHANNEL_RETRIES Total attempts
|
||||
* WS_MAX_FRAME_RETRIES WS_TX_REQUEST_RESTART_MAX Total attempts
|
||||
* 0 19 1+0*1+19=20
|
||||
* 1 9 1+1*1+9=20
|
||||
* 2 6 1+2*1+6=21
|
||||
|
@ -331,16 +338,28 @@ typedef struct ws_bs_ie {
|
|||
*/
|
||||
// This configuration is used when bootstrap is ready
|
||||
#define WS_MAX_FRAME_RETRIES 3
|
||||
#define WS_NUMBER_OF_CHANNEL_RETRIES 4
|
||||
// This configuration is used during bootstrap
|
||||
#define WS_MAX_FRAME_RETRIES_BOOTSTRAP 0
|
||||
#define WS_NUMBER_OF_CHANNEL_RETRIES_BOOTSTRAP 19
|
||||
#define WS_MAX_FRAME_RETRIES_BOOTSTRAP 0
|
||||
|
||||
// Configuring data request restart allows MAC to push failed packet back to MAC TX queue up to WS_CCA_REQUEST_RESTART_MAX times for CCA failure and WS_TX_REQUEST_RESTART_MAX for TX failure.
|
||||
// Packet cannot be taken back to transmission before it has finished the blacklist period.
|
||||
#define WS_CCA_REQUEST_RESTART_MAX 9
|
||||
#define WS_TX_REQUEST_RESTART_MAX 4
|
||||
#define WS_TX_REQUEST_RESTART_MAX_BOOTSTRAP 19
|
||||
#define WS_REQUEST_RESTART_BLACKLIST_MIN 20
|
||||
#define WS_REQUEST_RESTART_BLACKLIST_MAX 300
|
||||
|
||||
#if (1 + WS_MAX_FRAME_RETRIES) * (1 + WS_NUMBER_OF_CHANNEL_RETRIES) < 20
|
||||
#if (1 + WS_MAX_FRAME_RETRIES) * (1 + WS_TX_REQUEST_RESTART_MAX) < 20
|
||||
#warning "MAX frame retries set too low"
|
||||
#endif
|
||||
|
||||
// Total CCA attempts: 1 + WS_MAX_CSMA_BACKOFFS
|
||||
#define WS_MAX_CSMA_BACKOFFS 0
|
||||
|
||||
// Use minimum possible CSMA-CA backoffs
|
||||
#define WS_MAC_MIN_BE 1
|
||||
#define WS_MAC_MAX_BE 1
|
||||
|
||||
/*
|
||||
* Automatic CCA threshold: default threshold and range in dBm.
|
||||
*/
|
||||
|
@ -373,4 +392,5 @@ typedef struct ws_bs_ie {
|
|||
#define BR_EAPOL_RELAY_SOCKET_PORT 10255
|
||||
#define PAE_AUTH_SOCKET_PORT 10254
|
||||
|
||||
|
||||
#endif /* WS_COMMON_DEFINES_H_ */
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
#define WS_RPL_MIN_HOP_RANK_INCREASE 196
|
||||
#define WS_RPL_MAX_HOP_RANK_INCREASE 2048
|
||||
|
||||
#define WS_RPL_DEFAULT_LIFETIME (3600*2) // 2 hours
|
||||
#define WS_RPL_DEFAULT_LIFETIME_MEDIUM (3600*4) // 4 hours
|
||||
#define WS_RPL_DEFAULT_LIFETIME_LARGE (3600*8) // 8 hours
|
||||
#define WS_RPL_DEFAULT_LIFETIME_XLARGE (3600*12) // 12 hours
|
||||
|
||||
#define WS_DHCP_ADDRESS_LIFETIME_SMALL 2*3600 // small networks less than devices 100
|
||||
#define WS_DHCP_ADDRESS_LIFETIME_MEDIUM 12*3600 // Medium size networks from 100 - 1000 device networks
|
||||
#define WS_DHCP_ADDRESS_LIFETIME_LARGE 24*3600 // Large size networks 1000 + device networks
|
||||
|
@ -60,7 +65,7 @@
|
|||
/*
|
||||
* RPL DAO timeout maximum value. This will force DAO timeout to happen before this time
|
||||
*/
|
||||
#define WS_RPL_DAO_MAX_TIMOUT (3600*2)
|
||||
#define WS_RPL_DAO_MAX_TIMOUT (3600*12)
|
||||
|
||||
/* Border router version change interval
|
||||
*
|
||||
|
@ -90,9 +95,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define PAN_VERSION_SMALL_NETWORK_TIMEOUT 32*60
|
||||
#define PAN_VERSION_SMALL_NETWORK_TIMEOUT 30*60
|
||||
|
||||
#define PAN_VERSION_MEDIUM_NETWORK_TIMEOUT 64*60
|
||||
#define PAN_VERSION_MEDIUM_NETWORK_TIMEOUT 60*60
|
||||
|
||||
#define PAN_VERSION_LARGE_NETWORK_TIMEOUT 90*60
|
||||
|
||||
|
@ -249,9 +254,8 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
#define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries
|
||||
|
||||
// Maximum number of simultaneous security negotiations
|
||||
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 20
|
||||
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM 20
|
||||
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 50
|
||||
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MIN 64
|
||||
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MAX 192
|
||||
|
||||
/*
|
||||
* Security protocol timer configuration parameters
|
||||
|
@ -286,7 +290,7 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
// Large network trickle values for sending of initial EAPOL-key
|
||||
#define LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 600 /* 10 to 20 minutes */
|
||||
#define LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS 1200
|
||||
#define LARGE_NW_INITIAL_KEY_RETRY_COUNT 4
|
||||
#define LARGE_NW_INITIAL_KEY_RETRY_COUNT 3
|
||||
|
||||
// Very slow network values for sending of initial EAPOL-key
|
||||
#define EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS 600 /* 10 to 20 minutes */
|
||||
|
|
|
@ -214,7 +214,19 @@ int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr,
|
|||
|
||||
eapol_pdu_data->msdu_handle++;
|
||||
|
||||
eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id);
|
||||
eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id, MAC_DATA_NORMAL_PRIORITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_mpx_eui64_purge(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
||||
{
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data->mpx_api->mpx_eui64_purge(eapol_pdu_data->mpx_api, eui_64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,4 +161,16 @@ typedef int8_t ws_eapol_pdu_tx_status(protocol_interface_info_entry_t *interface
|
|||
*/
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer, ws_eapol_pdu_tx_status tx_status, uint8_t tx_identifier);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_mpx_eui64_purge purge EUI-64 from MPX
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 EUI-64 to purge
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_mpx_eui64_purge(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
|
||||
#endif /* WS_EAPOL_PDU_H_ */
|
||||
|
|
|
@ -189,6 +189,13 @@ static void ws_eapol_relay_socket_cb(void *cb)
|
|||
return;
|
||||
}
|
||||
|
||||
// EAPOL PDU data length is zero (message contains only supplicant EUI-64 and KMP ID)
|
||||
if (cb_data->d_len == 9) {
|
||||
ws_eapol_pdu_mpx_eui64_purge(eapol_relay->interface_ptr, socket_pdu);
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
return;
|
||||
}
|
||||
|
||||
//First 8 byte is EUID64 and rsr payload
|
||||
if (ws_eapol_pdu_send_to_mpx(eapol_relay->interface_ptr, socket_pdu, socket_pdu + 8, cb_data->d_len - 8, socket_pdu, NULL, 0) < 0) {
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
|
|
|
@ -68,20 +68,41 @@ int ws_management_network_name_validate(
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_phy_mode_id_set(
|
||||
int ws_management_domain_configuration_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id)
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
(void)regulatory_domain;
|
||||
(void)interface_id;
|
||||
(void)phy_mode_id;
|
||||
(void)channel_plan_id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_channel_plan_id_set(
|
||||
int ws_management_domain_configuration_get(
|
||||
int8_t interface_id,
|
||||
uint8_t *regulatory_domain,
|
||||
uint8_t *phy_mode_id,
|
||||
uint8_t *channel_plan_id)
|
||||
{
|
||||
(void)regulatory_domain;
|
||||
(void)interface_id;
|
||||
(void)phy_mode_id;
|
||||
(void)channel_plan_id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_domain_configuration_validate(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
(void)regulatory_domain;
|
||||
(void)interface_id;
|
||||
(void)phy_mode_id;
|
||||
(void)channel_plan_id;
|
||||
return -1;
|
||||
}
|
||||
|
@ -431,6 +452,17 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws_neighbor_info_get(
|
||||
int8_t interface_id,
|
||||
ws_neighbour_info_t *neighbor_ptr,
|
||||
uint16_t count)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) neighbor_ptr;
|
||||
(void) count;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_device_min_sens_set(
|
||||
int8_t interface_id,
|
||||
uint8_t device_min_sens)
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "Security/eapol/eapol_helper.h"
|
||||
#include "Service_Libs/etx/etx.h"
|
||||
#include "fhss_ws_extension.h"
|
||||
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
|
@ -90,6 +91,7 @@ typedef struct {
|
|||
uint8_t mpx_user_handle; /**< This MPX user defined handle */
|
||||
ns_ie_iovec_t ie_vector_list[3]; /**< IE vectors: 1 for Header's, 1 for Payload and for MPX payload */
|
||||
mcps_data_req_ie_list_t ie_ext;
|
||||
mac_data_priority_t priority;
|
||||
ns_list_link_t link; /**< List link entry */
|
||||
uint8_t ie_buffer[]; /**< Trailing buffer data */
|
||||
} llc_message_t;
|
||||
|
@ -109,6 +111,7 @@ typedef struct {
|
|||
ws_neighbor_temp_list_t active_eapol_temp_neigh;
|
||||
ws_neighbor_temp_list_t free_temp_neigh;
|
||||
llc_message_list_t llc_eap_pending_list; /**< Active Message list */
|
||||
uint16_t llc_eap_pending_list_size; /**< EAPOL active Message list size */
|
||||
bool active_eapol_session: 1; /**< Indicating active EAPOL message */
|
||||
} temp_entriest_t;
|
||||
|
||||
|
@ -117,6 +120,8 @@ typedef struct {
|
|||
#define ENHANCED_FRAME_RESPONSE (WH_IE_ELEMENT_HEADER_LENGTH + 2 + WH_IE_ELEMENT_HEADER_LENGTH + 4 + WH_IE_ELEMENT_HEADER_LENGTH + 1 + WH_IE_ELEMENT_HEADER_LENGTH + 5)
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< List link entry */
|
||||
|
||||
uint8_t mac_handle_base; /**< Mac handle id base this will be updated by 1 after use */
|
||||
uint8_t llc_message_list_size; /**< llc_message_list list size */
|
||||
uint16_t edfe_rx_wait_timer;
|
||||
|
@ -131,9 +136,8 @@ typedef struct {
|
|||
ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/
|
||||
uint8_t ws_enhanced_response_elements[ENHANCED_FRAME_RESPONSE];
|
||||
ns_ie_iovec_t ws_header_vector;
|
||||
bool high_priority_mode;
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
||||
|
||||
ns_list_link_t link; /**< List link entry */
|
||||
} llc_data_base_t;
|
||||
|
||||
static NS_LIST_DEFINE(llc_data_base_list, llc_data_base_t, link);
|
||||
|
@ -159,7 +163,7 @@ static llc_data_base_t *ws_llc_base_allocate(void);
|
|||
static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *data, const mcps_data_conf_payload_t *conf_data);
|
||||
static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t *data, const mcps_data_ie_list_t *ie_ext);
|
||||
static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id);
|
||||
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id);
|
||||
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id, mac_data_priority_t priority);
|
||||
static int8_t ws_llc_mpx_data_cb_register(const mpx_api_t *api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id);
|
||||
static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t *api, uint16_t user_id);
|
||||
static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
|
||||
|
@ -245,6 +249,7 @@ static void llc_message_free(llc_message_t *message, llc_data_base_t *llc_base)
|
|||
ns_list_remove(&llc_base->llc_message_list, message);
|
||||
ns_dyn_mem_free(message);
|
||||
llc_base->llc_message_list_size--;
|
||||
random_early_detetction_aq_calc(llc_base->interface_ptr->llc_random_early_detection, llc_base->llc_message_list_size);
|
||||
}
|
||||
|
||||
static void llc_message_id_allocate(llc_message_t *message, llc_data_base_t *llc_base, bool mpx_user)
|
||||
|
@ -286,6 +291,7 @@ static llc_message_t *llc_message_allocate(uint16_t ie_buffer_size, llc_data_bas
|
|||
}
|
||||
message->ack_requested = false;
|
||||
message->eapol_temporary = false;
|
||||
message->priority = MAC_DATA_NORMAL_PRIORITY;
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -534,10 +540,12 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
|
|||
if (message) {
|
||||
//Start A pending EAPOL
|
||||
ns_list_remove(&base->temp_entries->llc_eap_pending_list, message);
|
||||
base->temp_entries->llc_eap_pending_list_size--;
|
||||
random_early_detetction_aq_calc(base->interface_ptr->llc_eapol_random_early_detection, base->temp_entries->llc_eap_pending_list_size);
|
||||
ws_llc_mpx_eapol_send(base, message);
|
||||
}
|
||||
} else {
|
||||
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime <= WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME) {
|
||||
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime <= WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) {
|
||||
//Remove temp neighbour
|
||||
tr_debug("Remove Temp Entry by TX confirm");
|
||||
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor);
|
||||
|
@ -969,7 +977,7 @@ 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;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
memset(&ie_header_mask, 0, sizeof(wh_ie_sub_list_t));
|
||||
|
@ -1020,6 +1028,8 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
|
|||
//Add To active list
|
||||
llc_message_id_allocate(message, base, true);
|
||||
base->llc_message_list_size++;
|
||||
message->priority = priority;
|
||||
random_early_detetction_aq_calc(base->interface_ptr->llc_random_early_detection, base->llc_message_list_size);
|
||||
ns_list_add_to_end(&base->llc_message_list, message);
|
||||
|
||||
mcps_data_req_t data_req;
|
||||
|
@ -1097,7 +1107,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);
|
||||
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority);
|
||||
}
|
||||
|
||||
static bool ws_llc_eapol_temp_entry_set(llc_data_base_t *base, const uint8_t *mac64)
|
||||
|
@ -1147,15 +1157,16 @@ static void ws_llc_mpx_eapol_send(llc_data_base_t *base, llc_message_t *message)
|
|||
mcps_data_req_t data_req;
|
||||
llc_message_id_allocate(message, base, true);
|
||||
base->llc_message_list_size++;
|
||||
random_early_detetction_aq_calc(base->interface_ptr->llc_random_early_detection, base->llc_message_list_size);
|
||||
ns_list_add_to_end(&base->llc_message_list, message);
|
||||
message->eapol_temporary = ws_llc_eapol_temp_entry_set(base, message->dst_address);
|
||||
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);
|
||||
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL, message->priority);
|
||||
}
|
||||
|
||||
|
||||
static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb, const struct mcps_data_req_s *data)
|
||||
static void ws_llc_mpx_eapol_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;
|
||||
memset(&ie_header_mask, 0, sizeof(wh_ie_sub_list_t));
|
||||
|
@ -1190,6 +1201,7 @@ static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb,
|
|||
user_cb->data_confirm(&base->mpx_data_base.mpx_api, &data_conf);
|
||||
return;
|
||||
}
|
||||
message->priority = priority;
|
||||
message->mpx_user_handle = data->msduHandle;
|
||||
message->ack_requested = data->TxAckReq;
|
||||
|
||||
|
@ -1240,6 +1252,8 @@ static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb,
|
|||
if (base->temp_entries->active_eapol_session) {
|
||||
//Move to pending list
|
||||
ns_list_add_to_end(&base->temp_entries->llc_eap_pending_list, message);
|
||||
base->temp_entries->llc_eap_pending_list_size++;
|
||||
random_early_detetction_aq_calc(base->interface_ptr->llc_eapol_random_early_detection, base->temp_entries->llc_eap_pending_list_size);
|
||||
} else {
|
||||
ws_llc_mpx_eapol_send(base, message);
|
||||
}
|
||||
|
@ -1247,7 +1261,7 @@ static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb,
|
|||
}
|
||||
|
||||
|
||||
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id)
|
||||
static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id, mac_data_priority_t priority)
|
||||
{
|
||||
llc_data_base_t *base = ws_llc_discover_by_mpx(api);
|
||||
if (!base) {
|
||||
|
@ -1270,12 +1284,21 @@ static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data
|
|||
}
|
||||
|
||||
if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) {
|
||||
ws_llc_mpx_eapol_request(base, user_cb, data);
|
||||
ws_llc_mpx_eapol_request(base, user_cb, data, priority);
|
||||
} else if (user_id == MPX_LOWPAN_ENC_USER_ID) {
|
||||
ws_llc_lowpan_mpx_data_request(base, user_cb, data);
|
||||
ws_llc_lowpan_mpx_data_request(base, user_cb, data, priority);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_llc_mpx_eui64_purge_request(const mpx_api_t *api, const uint8_t *eui64)
|
||||
{
|
||||
llc_data_base_t *base = ws_llc_discover_by_mpx(api);
|
||||
if (!base) {
|
||||
return;
|
||||
}
|
||||
tr_info("LLC purge EAPOL temporary entry: %s", tr_array(eui64, 8));
|
||||
ws_llc_release_eapol_temp_entry(base->temp_entries, eui64);
|
||||
}
|
||||
|
||||
static int8_t ws_llc_mpx_data_cb_register(const mpx_api_t *api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id)
|
||||
{
|
||||
|
@ -1325,6 +1348,15 @@ static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_p
|
|||
return purge_status;
|
||||
}
|
||||
|
||||
static void wc_llc_mpx_priority_set_request(const mpx_api_t *api, bool enable_mode)
|
||||
{
|
||||
llc_data_base_t *base = ws_llc_discover_by_mpx(api);
|
||||
if (!base) {
|
||||
return;
|
||||
}
|
||||
base->high_priority_mode = enable_mode;
|
||||
}
|
||||
|
||||
static void ws_llc_mpx_init(mpx_class_t *mpx_class)
|
||||
{
|
||||
//Init Mbed Class and API
|
||||
|
@ -1334,6 +1366,8 @@ static void ws_llc_mpx_init(mpx_class_t *mpx_class)
|
|||
mpx_class->mpx_api.mpx_user_registration = &ws_llc_mpx_data_cb_register;
|
||||
mpx_class->mpx_api.mpx_data_request = &ws_llc_mpx_data_request;
|
||||
mpx_class->mpx_api.mpx_data_purge = &ws_llc_mpx_data_purge_request;
|
||||
mpx_class->mpx_api.mpx_eui64_purge = &ws_llc_mpx_eui64_purge_request;
|
||||
mpx_class->mpx_api.mpx_priority_mode_set = &wc_llc_mpx_priority_set_request;
|
||||
}
|
||||
|
||||
static void ws_llc_clean(llc_data_base_t *base)
|
||||
|
@ -1351,10 +1385,13 @@ static void ws_llc_clean(llc_data_base_t *base)
|
|||
ns_list_remove(&base->temp_entries->llc_eap_pending_list, message);
|
||||
ns_dyn_mem_free(message);
|
||||
}
|
||||
base->temp_entries->llc_eap_pending_list_size = 0;
|
||||
base->temp_entries->active_eapol_session = false;
|
||||
memset(&base->ie_params, 0, sizeof(llc_ie_params_t));
|
||||
|
||||
ws_llc_temp_neigh_info_table_reset(base->temp_entries);
|
||||
//Disable High Priority mode
|
||||
base->high_priority_mode = false;
|
||||
}
|
||||
|
||||
static void ws_llc_temp_neigh_info_table_reset(temp_entriest_t *base)
|
||||
|
@ -1657,6 +1694,11 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (base->high_priority_mode) {
|
||||
//Drop asynch messages at High Priority mode
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//Calculate IE Buffer size
|
||||
request->wh_requested_ie_list.fc_ie = false; //Never should not be a part Asynch message
|
||||
|
@ -1683,6 +1725,7 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
|
|||
//Add To active list
|
||||
llc_message_id_allocate(message, base, false);
|
||||
base->llc_message_list_size++;
|
||||
random_early_detetction_aq_calc(base->interface_ptr->llc_random_early_detection, base->llc_message_list_size);
|
||||
ns_list_add_to_end(&base->llc_message_list, message);
|
||||
message->messsage_type = request->message_type;
|
||||
|
||||
|
@ -1761,7 +1804,7 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
|
|||
}
|
||||
}
|
||||
|
||||
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, &request->channel_list);
|
||||
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, &request->channel_list, message->priority);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -156,12 +156,13 @@ int ws_management_network_name_validate(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_phy_mode_id_set(
|
||||
int ws_management_domain_configuration_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id)
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (interface_id >= 0 && (!cur || !ws_info(cur))) {
|
||||
return -1;
|
||||
|
@ -177,10 +178,22 @@ int ws_management_phy_mode_id_set(
|
|||
return -3;
|
||||
}
|
||||
|
||||
if (phy_mode_id != 255) {
|
||||
cfg.phy_mode_id = phy_mode_id;
|
||||
} else {
|
||||
if (regulatory_domain == 255) {
|
||||
cfg.regulatory_domain = cfg_default.regulatory_domain;
|
||||
} else if (regulatory_domain != 0) {
|
||||
cfg.regulatory_domain = regulatory_domain;
|
||||
}
|
||||
|
||||
if (phy_mode_id == 255) {
|
||||
cfg.phy_mode_id = cfg_default.phy_mode_id;
|
||||
} else if (phy_mode_id != 0) {
|
||||
cfg.phy_mode_id = phy_mode_id;
|
||||
}
|
||||
|
||||
if (channel_plan_id == 255) {
|
||||
cfg.channel_plan_id = cfg_default.channel_plan_id;
|
||||
} else if (channel_plan_id != 0) {
|
||||
cfg.channel_plan_id = channel_plan_id;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
|
||||
|
@ -190,34 +203,58 @@ int ws_management_phy_mode_id_set(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_channel_plan_id_set(
|
||||
int ws_management_domain_configuration_get(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_plan_id)
|
||||
uint8_t *regulatory_domain,
|
||||
uint8_t *phy_mode_id,
|
||||
uint8_t *channel_plan_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (interface_id >= 0 && (!cur || !ws_info(cur))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_phy_cfg_t cfg;
|
||||
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (regulatory_domain) {
|
||||
*regulatory_domain = cfg.regulatory_domain;
|
||||
}
|
||||
if (phy_mode_id) {
|
||||
*phy_mode_id = cfg.phy_mode_id;
|
||||
}
|
||||
if (channel_plan_id) {
|
||||
*channel_plan_id = cfg.channel_plan_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_domain_configuration_validate(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t phy_mode_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (interface_id >= 0 && (!cur || !ws_info(cur))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_phy_cfg_t cfg;
|
||||
ws_phy_cfg_t cfg_default;
|
||||
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_default_set(&cfg_default) < 0) {
|
||||
return -3;
|
||||
}
|
||||
cfg.regulatory_domain = regulatory_domain;
|
||||
cfg.phy_mode_id = phy_mode_id;
|
||||
cfg.channel_plan_id = channel_plan_id;
|
||||
|
||||
if (channel_plan_id != 255) {
|
||||
cfg.channel_plan_id = channel_plan_id;
|
||||
} else {
|
||||
cfg.channel_plan_id = cfg_default.channel_plan_id;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
|
||||
if (ws_cfg_phy_validate(NULL, &cfg) < 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
|
@ -890,7 +927,20 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
|
|||
if (!cur || !ws_info(cur) || !info_ptr) {
|
||||
return -1;
|
||||
}
|
||||
return ws_bootstrap_get_info(cur, info_ptr);
|
||||
return ws_bootstrap_stack_info_get(cur, info_ptr);
|
||||
}
|
||||
|
||||
int ws_neighbor_info_get(
|
||||
int8_t interface_id,
|
||||
ws_neighbour_info_t *neighbor_ptr,
|
||||
uint16_t count)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
return ws_bootstrap_neighbor_info_get(cur, neighbor_ptr, count);
|
||||
}
|
||||
|
||||
int ws_device_min_sens_set(
|
||||
|
|
|
@ -33,7 +33,6 @@ typedef struct ws_neighbor_class_entry {
|
|||
bool broadcast_timing_info_stored: 1;
|
||||
bool broadcast_shedule_info_stored: 1;
|
||||
bool synch_done : 1;
|
||||
bool negative_aro_send : 1;
|
||||
bool unicast_data_rx : 1;
|
||||
} ws_neighbor_class_entry_t;
|
||||
|
||||
|
|
|
@ -66,10 +66,8 @@
|
|||
#define WAIT_FOR_AUTHENTICATION_TICKS 2 * 60 * 10 // 2 minutes
|
||||
// Wait after authentication has completed before supplicant entry goes inactive
|
||||
#define WAIT_AFTER_AUTHENTICATION_TICKS 15 * 10 // 15 seconds
|
||||
|
||||
/* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how
|
||||
long to wait for previous negotiation to complete */
|
||||
#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds
|
||||
// Waiting for authentication supplicant list maximum size
|
||||
#define WAITING_SUPPLICANT_LIST_MAX_SIZE 50
|
||||
|
||||
// Default for maximum number of supplicants
|
||||
#define SUPPLICANT_MAX_NUMBER 5000
|
||||
|
@ -93,7 +91,9 @@ typedef struct {
|
|||
ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
|
||||
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 */
|
||||
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 */
|
||||
arm_event_storage_t *timer; /**< Timer */
|
||||
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
|
||||
|
@ -101,6 +101,7 @@ typedef struct {
|
|||
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
|
||||
sec_cfg_t *sec_cfg; /**< Security configuration */
|
||||
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 */
|
||||
|
@ -128,14 +129,17 @@ static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth);
|
|||
static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
||||
static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address);
|
||||
static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
|
||||
static bool ws_pae_auth_active_limit_reached(uint16_t active_supp, pae_auth_t *pae_auth);
|
||||
static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size);
|
||||
static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
|
||||
static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
|
||||
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||
static bool ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static bool ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||
static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, uint8_t socked_msg_if_instance_id, supp_entry_t *supp_entry, sec_cfg_t *sec_cfg);
|
||||
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
|
||||
static void ws_pae_auth_active_supp_deleted(void *pae_auth);
|
||||
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);
|
||||
|
@ -159,6 +163,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
|||
pae_auth->pan_id = 0xffff;
|
||||
pae_auth->interface_ptr = interface_ptr;
|
||||
ws_pae_lib_supp_list_init(&pae_auth->active_supp_list);
|
||||
ws_pae_lib_supp_list_init(&pae_auth->waiting_supp_list);
|
||||
ws_pae_lib_shared_comp_list_init(&pae_auth->shared_comp_list);
|
||||
pae_auth->timer = NULL;
|
||||
|
||||
|
@ -166,12 +171,16 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
|||
pae_auth->nw_key_insert = NULL;
|
||||
pae_auth->nw_keys_remove = NULL;
|
||||
pae_auth->nw_key_index_set = NULL;
|
||||
pae_auth->nw_info_updated = NULL;
|
||||
pae_auth->ip_addr_get = NULL;
|
||||
pae_auth->congestion_get = 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->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;
|
||||
|
@ -302,7 +311,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)
|
||||
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)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
|
@ -318,6 +327,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
|||
pae_auth->nw_key_index_set = nw_key_index_set;
|
||||
pae_auth->nw_info_updated = nw_info_updated;
|
||||
pae_auth->ip_addr_get = ip_addr_get;
|
||||
pae_auth->congestion_get = congestion_get;
|
||||
}
|
||||
|
||||
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
|
||||
|
@ -394,8 +404,11 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p
|
|||
return ret_value;
|
||||
}
|
||||
|
||||
// Checks if supplicant is active
|
||||
// Checks if supplicant is active or waiting
|
||||
supp_entry_t *supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, eui_64);
|
||||
if (!supp) {
|
||||
supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->waiting_supp_list, eui_64);
|
||||
}
|
||||
|
||||
if (supp) {
|
||||
// Deletes keys and marks as revoked
|
||||
|
@ -507,7 +520,8 @@ void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr)
|
|||
|
||||
/* Purge in maximum five entries from supplicant list (starting from oldest one)
|
||||
per call to the function (called by nanostack monitor) */
|
||||
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE);
|
||||
ws_pae_lib_supp_list_purge(pae_auth, &pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE, NULL);
|
||||
ws_pae_lib_supp_list_purge(pae_auth, &pae_auth->waiting_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE, ws_pae_auth_waiting_supp_deleted);
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated)
|
||||
|
@ -608,6 +622,7 @@ static void ws_pae_auth_free(pae_auth_t *pae_auth)
|
|||
ws_pae_lib_shared_comp_list_free(&pae_auth->shared_comp_list);
|
||||
|
||||
ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list);
|
||||
ws_pae_lib_supp_list_delete(&pae_auth->waiting_supp_list);
|
||||
|
||||
kmp_socket_if_unregister(pae_auth->kmp_service);
|
||||
|
||||
|
@ -690,8 +705,9 @@ void ws_pae_auth_fast_timer(uint16_t ticks)
|
|||
}
|
||||
|
||||
// Updates KMP timers
|
||||
bool running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->active_supp_list, ticks, kmp_service_timer_if_timeout);
|
||||
if (!running) {
|
||||
bool active_running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->active_supp_list, ticks, kmp_service_timer_if_timeout, ws_pae_auth_active_supp_deleted);
|
||||
bool wait_running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->waiting_supp_list, ticks, kmp_service_timer_if_timeout, ws_pae_auth_waiting_supp_deleted);
|
||||
if (!active_running && !wait_running) {
|
||||
ws_pae_auth_timer_stop(pae_auth);
|
||||
}
|
||||
}
|
||||
|
@ -936,6 +952,40 @@ static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_ap
|
|||
return ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type);
|
||||
}
|
||||
|
||||
static bool ws_pae_auth_active_limit_reached(uint16_t active_supp, pae_auth_t *pae_auth)
|
||||
{
|
||||
return pae_auth->congestion_get(pae_auth->interface_ptr, active_supp);
|
||||
}
|
||||
|
||||
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) {
|
||||
ns_list_add_to_start(&pae_auth->waiting_supp_list, supp_entry);
|
||||
pae_auth->waiting_supp_list_size++;
|
||||
} else {
|
||||
// Create a new supplicant entry if not at limit
|
||||
if (pae_auth->waiting_supp_list_size > WAITING_SUPPLICANT_LIST_MAX_SIZE) {
|
||||
tr_info("PAE: waiting list full, eui-64: %s", trace_array(addr->eui_64, 8));
|
||||
return NULL;
|
||||
}
|
||||
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->waiting_supp_list, addr);
|
||||
if (!supp_entry) {
|
||||
tr_info("PAE: waiting list no memory, eui-64: %s", trace_array(addr->eui_64, 8));
|
||||
return NULL;
|
||||
}
|
||||
pae_auth->waiting_supp_list_size++;
|
||||
sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->sec_keys_nw_info->gtks, pae_auth->certs);
|
||||
}
|
||||
|
||||
// 90 percent of the EAPOL temporary entry lifetime (10 ticks per second)
|
||||
supp_entry->waiting_ticks = pae_auth->sec_cfg->timing_cfg.temp_eapol_min_timeout * 900 / 100;
|
||||
|
||||
tr_debug("PAE: to waiting, list size %i, retry %i, eui-64: %s", pae_auth->waiting_supp_list_size, supp_entry->waiting_ticks, trace_array(supp_entry->addr.eui_64, 8));
|
||||
|
||||
return supp_entry;
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size)
|
||||
{
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
|
@ -954,21 +1004,43 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t m
|
|||
supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr));
|
||||
|
||||
if (!supp_entry) {
|
||||
// Checks if active supplicant list has space for new supplicants
|
||||
if (ws_pae_lib_supp_list_active_limit_reached(&pae_auth->active_supp_list, pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication)) {
|
||||
tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8));
|
||||
return NULL;
|
||||
}
|
||||
// Find supplicant from key storage
|
||||
supp_entry = ws_pae_key_storage_supp_read(pae_auth, kmp_address_eui_64_get(addr), pae_auth->sec_keys_nw_info->gtks, pae_auth->certs);
|
||||
uint16_t active_supp = ns_list_count(&pae_auth->active_supp_list);
|
||||
|
||||
// Check if supplicant is already on the the waiting supplicant list
|
||||
supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->waiting_supp_list, kmp_address_eui_64_get(addr));
|
||||
if (supp_entry) {
|
||||
// Move supplicant to active list
|
||||
tr_debug("PAE: to active, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
ns_list_add_to_start(&pae_auth->active_supp_list, supp_entry);
|
||||
/* Remove from waiting list (supplicant is later added to active list, or if no room back to the start of the
|
||||
* waiting list with updated timer)
|
||||
*/
|
||||
ns_list_remove(&pae_auth->waiting_supp_list, supp_entry);
|
||||
pae_auth->waiting_supp_list_size--;
|
||||
supp_entry->waiting_ticks = 0;
|
||||
} else {
|
||||
// Find supplicant from key storage
|
||||
supp_entry = ws_pae_key_storage_supp_read(pae_auth, kmp_address_eui_64_get(addr), pae_auth->sec_keys_nw_info->gtks, pae_auth->certs);
|
||||
}
|
||||
|
||||
// Checks if active supplicant list has space for new supplicants
|
||||
if (ws_pae_auth_active_limit_reached(active_supp, pae_auth)) {
|
||||
tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8));
|
||||
// If there is no space, add supplicant entry to the start of the waiting supplicant list
|
||||
supp_entry = ws_pae_auth_waiting_supp_list_add(pae_auth, supp_entry, addr);
|
||||
if (!supp_entry) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (supp_entry) {
|
||||
/*
|
||||
* If there is space and there is already an allocated supplicant, add it to active list and
|
||||
* start/continue authentication
|
||||
*/
|
||||
tr_debug("PAE: to active, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
ns_list_add_to_start(&pae_auth->active_supp_list, supp_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If does not exists add it to list
|
||||
// If supplicant does not exists create a new supplicant entry to the active list
|
||||
if (!supp_entry) {
|
||||
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr);
|
||||
if (!supp_entry) {
|
||||
|
@ -1044,35 +1116,37 @@ static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ
|
|||
kmp_api_create_response(kmp, KMP_RESULT_OK);
|
||||
}
|
||||
|
||||
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
|
||||
static bool ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
|
||||
{
|
||||
(void) sec_keys;
|
||||
|
||||
// For now, just ignore if not ok
|
||||
if (result != KMP_RESULT_OK) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
if (!supp_entry) {
|
||||
// Should not be possible
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
// Should not be possible
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry);
|
||||
// Ensures that supplicant is in active supplicant list before initiating next KMP
|
||||
if (!ws_pae_lib_supp_list_entry_is_in_list(&pae_auth->active_supp_list, supp_entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry);
|
||||
}
|
||||
|
||||
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry)
|
||||
static bool ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry)
|
||||
{
|
||||
// Disables KMP retry timer
|
||||
supp_entry->retry_ticks = 0;
|
||||
|
||||
// Get next protocol based on what keys supplicant has
|
||||
kmp_type_e next_type = ws_pae_auth_next_protocol_get(pae_auth, supp_entry);
|
||||
|
||||
|
@ -1080,7 +1154,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
// Supplicant goes inactive after 15 seconds
|
||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_AFTER_AUTHENTICATION_TICKS);
|
||||
// All done
|
||||
return;
|
||||
return true;
|
||||
} else {
|
||||
kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type);
|
||||
if (api != NULL) {
|
||||
|
@ -1088,7 +1162,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
for GTK there can be previous terminating and the new one for next key index */
|
||||
if (next_type != IEEE_802_11_GKH) {
|
||||
tr_info("KMP already ongoing; ignored, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1096,25 +1170,10 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
// Increases waiting time for supplicant authentication
|
||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
|
||||
if (next_type == IEEE_802_1X_MKA || next_type == RADIUS_IEEE_802_1X_MKA) {
|
||||
/* For EAP-TLS, limits the number of ongoing negotiations. If limit
|
||||
is reached, authenticator does not initiate EAP-TLS right away.
|
||||
If previous EAP-TLS negotiation completes before negotiation
|
||||
trigger timeout, authenticator initiates EAP-TLS towards
|
||||
supplicant. Otherwise supplicant must re-send initial EAPOL-Key
|
||||
to try again using its trickle schedule */
|
||||
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, next_type);
|
||||
if (ongoing_eap_tls_cnt >= pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication) {
|
||||
supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT;
|
||||
tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new instance
|
||||
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, pae_auth->relay_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg);
|
||||
if (!new_kmp) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// For radius EAP-TLS create also radius client in addition to EAP-TLS
|
||||
|
@ -1122,12 +1181,12 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, RADIUS_CLIENT_PROT) != NULL) {
|
||||
// Radius client already exists, wait for it to be deleted
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// Create radius client instance */
|
||||
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, RADIUS_CLIENT_PROT, pae_auth->radius_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg) == NULL) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// For EAP-TLS create also TLS client in addition to EAP-TLS
|
||||
|
@ -1135,16 +1194,17 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) {
|
||||
// TLS already exists, wait for it to be deleted
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// Create TLS instance */
|
||||
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, pae_auth->relay_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg) == NULL) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
kmp_api_create_request(new_kmp, next_type, &supp_entry->addr, &supp_entry->sec_keys);
|
||||
return false;
|
||||
}
|
||||
|
||||
static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry)
|
||||
|
@ -1161,11 +1221,11 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
|||
} else {
|
||||
next_type = IEEE_802_1X_MKA;
|
||||
}
|
||||
tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
} else if (sec_keys->ptk_mismatch) {
|
||||
// start 4WH towards supplicant
|
||||
next_type = IEEE_802_11_4WH;
|
||||
tr_info("PAE start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
}
|
||||
|
||||
int8_t gtk_index = -1;
|
||||
|
@ -1191,19 +1251,19 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
|||
// start 4WH towards supplicant
|
||||
next_type = IEEE_802_11_4WH;
|
||||
sec_keys->ptk_mismatch = true;
|
||||
tr_info("PAE start 4WH due to GTK index re-use, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: start 4WH due to GTK index re-use, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
} else {
|
||||
// Update just GTK
|
||||
next_type = IEEE_802_11_GKH;
|
||||
tr_info("PAE start GKH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: start GKH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
}
|
||||
}
|
||||
|
||||
tr_info("PAE update GTK index: %i, eui-64: %s", gtk_index, trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: update GTK index: %i, eui-64: %s", gtk_index, trace_array(supp_entry->addr.eui_64, 8));
|
||||
}
|
||||
|
||||
if (next_type == KMP_TYPE_NONE) {
|
||||
tr_info("PAE authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
tr_info("PAE: authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
}
|
||||
|
||||
return next_type;
|
||||
|
@ -1254,26 +1314,38 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
|
|||
return;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = NULL;
|
||||
supp_entry_t *retry_supp = NULL;
|
||||
// When EAP-TLS completes check if there are other supplicants that have requested it lately
|
||||
if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA || kmp_api_type_get(kmp) == RADIUS_IEEE_802_1X_MKA) {
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (pae_auth) {
|
||||
retry_supp = ws_pae_lib_supp_list_entry_retry_timer_get(&pae_auth->active_supp_list);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete KMP
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);
|
||||
}
|
||||
|
||||
if (retry_supp) {
|
||||
tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8));
|
||||
static void ws_pae_auth_active_supp_deleted(void *pae_auth_ptr)
|
||||
{
|
||||
pae_auth_t *pae_auth = pae_auth_ptr;
|
||||
|
||||
tr_info("Supplicant deleted");
|
||||
|
||||
uint16_t active_supp = ns_list_count(&pae_auth->active_supp_list);
|
||||
if (ws_pae_auth_active_limit_reached(active_supp, pae_auth)) {
|
||||
return;
|
||||
}
|
||||
|
||||
supp_entry_t *retry_supp = ns_list_get_first(&pae_auth->waiting_supp_list);
|
||||
if (retry_supp != NULL) {
|
||||
ns_list_remove(&pae_auth->waiting_supp_list, retry_supp);
|
||||
pae_auth->waiting_supp_list_size--;
|
||||
ns_list_add_to_start(&pae_auth->active_supp_list, retry_supp);
|
||||
tr_info("PAE: waiting supplicant to active, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8));
|
||||
retry_supp->waiting_ticks = 0;
|
||||
ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_auth_waiting_supp_deleted(void *pae_auth_ptr)
|
||||
{
|
||||
pae_auth_t *pae_auth = pae_auth_ptr;
|
||||
pae_auth->waiting_supp_list_size--;
|
||||
}
|
||||
|
||||
#endif /* HAVE_PAE_AUTH */
|
||||
#endif /* HAVE_WS */
|
||||
|
||||
|
|
|
@ -249,6 +249,17 @@ typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interf
|
|||
*/
|
||||
typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_congestion_get get congestion information
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param active_supp active supplicants
|
||||
*
|
||||
* \return TRUE reject, FALSE accept
|
||||
*
|
||||
*/
|
||||
typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_cb_register register PAE authenticator callbacks
|
||||
*
|
||||
|
@ -258,9 +269,10 @@ typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_
|
|||
* \param nw_key_index_set network send key index callback
|
||||
* \param nw_info_updated network keys updated callback
|
||||
* \param ip_addr_get IP addressing information callback
|
||||
* \param congestion_get congestion get 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);
|
||||
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);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -268,7 +280,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
|||
#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) {(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) {(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
|
||||
|
|
|
@ -88,6 +88,7 @@ typedef struct {
|
|||
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
|
||||
ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */
|
||||
ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */
|
||||
ws_pae_controller_congestion_get *congestion_get; /**< Congestion get callback */
|
||||
ws_pae_controller_ip_addr_get *ip_addr_get; /**< IP address get callback */
|
||||
ws_pae_delete *pae_delete; /**< PAE delete callback */
|
||||
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
|
||||
|
@ -117,6 +118,7 @@ static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_key
|
|||
static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr);
|
||||
#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);
|
||||
#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);
|
||||
|
@ -139,8 +141,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, 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, 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 const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
|
||||
|
@ -238,7 +240,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_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);
|
||||
|
||||
controller->auth_started = true;
|
||||
|
||||
|
@ -247,7 +249,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated)
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
|
@ -267,6 +269,7 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
|
|||
controller->pan_ver_increment = pan_ver_increment;
|
||||
controller->nw_info_updated = nw_info_updated;
|
||||
controller->auth_next_target = auth_next_target;
|
||||
controller->congestion_get = congestion_get;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -368,7 +371,13 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr
|
|||
}
|
||||
|
||||
if (controller->sec_keys_nw_info.updated || sec_prot_keys_gtks_are_updated(controller->sec_keys_nw_info.gtks)) {
|
||||
ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, controller->sec_keys_nw_info.gtks);
|
||||
// Get own EUI-64
|
||||
uint8_t gtk_eui64[8] = {0};
|
||||
link_layer_address_s mac_params;
|
||||
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);
|
||||
controller->sec_keys_nw_info.updated = false;
|
||||
sec_prot_keys_gtks_updated_reset(controller->sec_keys_nw_info.gtks);
|
||||
}
|
||||
|
@ -388,6 +397,20 @@ static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *
|
|||
|
||||
controller->ip_addr_get(interface_ptr, address);
|
||||
}
|
||||
|
||||
static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return controller->congestion_get(interface_ptr, active_supp);
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
|
||||
|
@ -472,7 +495,6 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_
|
|||
tr_info("GTK: %s", trace_array(gtk, 16));
|
||||
tr_info("GAK: %s", trace_array(gak, 16));
|
||||
#endif
|
||||
|
||||
} else {
|
||||
tr_error("GAK generation failed network name: %s", controller->sec_keys_nw_info.network_name);
|
||||
continue;
|
||||
|
@ -675,6 +697,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
|||
controller->pan_ver_increment = NULL;
|
||||
controller->nw_info_updated = NULL;
|
||||
controller->auth_next_target = NULL;
|
||||
controller->congestion_get = NULL;
|
||||
|
||||
memset(&controller->sec_cfg, 0, sizeof(sec_cfg_t));
|
||||
|
||||
|
@ -685,7 +708,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg)
|
||||
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg)
|
||||
{
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (controller == NULL) {
|
||||
|
@ -698,9 +721,6 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
|
|||
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.k = 0;
|
||||
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp;
|
||||
controller->sec_cfg.prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10;
|
||||
|
||||
controller->sec_cfg.prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication;
|
||||
|
||||
controller->sec_cfg.prot_cfg.initial_key_retry_delay = sec_prot_cfg->initial_key_retry_delay;
|
||||
controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imin = sec_prot_cfg->initial_key_imin;
|
||||
controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imax = sec_prot_cfg->initial_key_imax;
|
||||
|
@ -715,6 +735,10 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
|
|||
|
||||
controller->sec_cfg.radius_cfg = pae_controller_config.radius_cfg;
|
||||
|
||||
if (timing_cfg) {
|
||||
controller->sec_cfg.timing_cfg.temp_eapol_min_timeout = timing_cfg->temp_eapol_min_timeout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -826,32 +850,46 @@ static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_
|
|||
|
||||
static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
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, gtks) < 0) {
|
||||
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) {
|
||||
// If no stored GTKs and network info (pan_id and network name) exits
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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
|
||||
authenticator EUI-64 to the network. */
|
||||
uint8_t gtk_eui64[8] = {0};
|
||||
link_layer_address_s mac_params;
|
||||
if (arm_nwk_mac_address_read(controller->interface_ptr->id, &mac_params) >= 0) {
|
||||
memcpy(gtk_eui64, mac_params.mac_long, 8);
|
||||
}
|
||||
if (memcmp(nvm_gtk_eui64, gtk_eui64, 8) != 0) {
|
||||
tr_warn("NVM EUI-64 mismatch, current: %s stored: %s", tr_array(gtk_eui64, 8), tr_array(nvm_gtk_eui64, 8));
|
||||
sec_prot_keys_gtks_clear(gtks);
|
||||
}
|
||||
|
||||
// Sets also new pan_id used for pan_id set by bootstrap
|
||||
controller->sec_keys_nw_info.new_pan_id = controller->sec_keys_nw_info.key_pan_id;
|
||||
|
||||
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, 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)
|
||||
{
|
||||
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, gtks);
|
||||
ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtk_eui64, gtks);
|
||||
|
||||
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, 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)
|
||||
{
|
||||
nw_info_nvm_tlv_t *tlv_entry = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr);
|
||||
if (!tlv_entry) {
|
||||
|
@ -864,7 +902,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, gtks) < 0) {
|
||||
if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtk_eui64, gtks) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -946,7 +984,8 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
|
|||
}
|
||||
if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) {
|
||||
// Key material invalid or GTKs are expired, delete GTKs from NVM
|
||||
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, NULL);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1232,7 +1271,7 @@ int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) {
|
||||
if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1282,7 +1321,7 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin
|
|||
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (controller) {
|
||||
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1335,7 +1374,7 @@ int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, bbr_radius_timin
|
|||
|
||||
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||
if (controller) {
|
||||
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
typedef enum {
|
||||
AUTH_RESULT_OK = 0, // Successful
|
||||
AUTH_RESULT_ERR_NO_MEM = -1, // No memory
|
||||
AUTH_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received
|
||||
AUTH_RESULT_ERR_TX_ERR = -2, // TX error (e.g. no acknowledge was received)
|
||||
AUTH_RESULT_ERR_UNSPEC = -3 // Other reason
|
||||
} auth_result_e;
|
||||
|
||||
|
@ -31,6 +31,7 @@ struct nvm_tlv_entry;
|
|||
struct ws_sec_timer_cfg_s;
|
||||
struct ws_sec_prot_cfg_s;
|
||||
struct bbr_radius_timing;
|
||||
struct ws_timing_cfg_s;
|
||||
|
||||
/**
|
||||
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
|
||||
|
@ -98,12 +99,13 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr);
|
|||
* \param interface_ptr interface
|
||||
* \param sec_timer_cfg timer configuration or NULL if not set
|
||||
* \param sec_prot_cfg protocol configuration or NULL if not set
|
||||
* \param timing_cfg timing configuration or NULL if not set
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg);
|
||||
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_init initializes PAE supplicant
|
||||
|
@ -612,6 +614,17 @@ typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t
|
|||
*/
|
||||
typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_congestion_get get congestion information
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param active_supp active supplicants
|
||||
*
|
||||
* \return TRUE reject, FALSE accept
|
||||
*
|
||||
*/
|
||||
typedef bool ws_pae_controller_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_cb_register register controller callbacks
|
||||
*
|
||||
|
@ -625,12 +638,13 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *
|
|||
* \param nw_frame_counter_read network frame counter read callback
|
||||
* \param pan_ver_increment PAN version increment callback
|
||||
* \param nw_info_updated network information updated callback
|
||||
* \param congestion_get congestion get callback
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_ip_addr_get gets IP addressing information
|
||||
|
@ -701,7 +715,7 @@ void ws_pae_controller_forced_gc(bool full_gc);
|
|||
|
||||
#define ws_pae_controller_stop(interface_ptr)
|
||||
#define ws_pae_controller_delete(interface_ptr)
|
||||
#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment) 1
|
||||
#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment, congestion_get) 1
|
||||
#define ws_pae_controller_nvm_tlv_get(interface_ptr) NULL
|
||||
|
||||
#define ws_pae_controller_forced_gc NULL
|
||||
|
|
|
@ -193,18 +193,23 @@ supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t
|
|||
entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
|
||||
kmp_address_copy(&entry->addr, addr);
|
||||
|
||||
ns_list_add_to_end(supp_list, entry);
|
||||
ns_list_add_to_start(supp_list, entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *supp)
|
||||
int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted)
|
||||
{
|
||||
ns_list_remove(supp_list, supp);
|
||||
|
||||
ws_pae_lib_supp_delete(supp);
|
||||
|
||||
ns_dyn_mem_free(supp);
|
||||
|
||||
if (supp_deleted != NULL) {
|
||||
supp_deleted(instance);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -222,11 +227,11 @@ supp_entry_t *ws_pae_lib_supp_list_entry_eui_64_get(const supp_list_t *supp_list
|
|||
void ws_pae_lib_supp_list_delete(supp_list_t *supp_list)
|
||||
{
|
||||
ns_list_foreach_safe(supp_entry_t, entry, supp_list) {
|
||||
ws_pae_lib_supp_list_remove(supp_list, entry);
|
||||
ws_pae_lib_supp_list_remove(NULL, supp_list, entry, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
|
||||
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted)
|
||||
{
|
||||
bool timer_running = false;
|
||||
|
||||
|
@ -235,7 +240,7 @@ bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_
|
|||
if (running) {
|
||||
timer_running = true;
|
||||
} else {
|
||||
ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry);
|
||||
ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry, supp_deleted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +265,7 @@ void ws_pae_lib_supp_init(supp_entry_t *entry)
|
|||
memset(&entry->addr, 0, sizeof(kmp_addr_t));
|
||||
memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
|
||||
entry->ticks = 0;
|
||||
entry->retry_ticks = 0;
|
||||
entry->waiting_ticks = 0;
|
||||
entry->store_ticks = ws_pae_key_storage_storing_interval_get() * 1000;
|
||||
entry->active = true;
|
||||
entry->access_revoked = false;
|
||||
|
@ -283,18 +288,18 @@ bool ws_pae_lib_supp_timer_update(void *instance, supp_entry_t *entry, uint16_t
|
|||
entry->ticks -= ticks;
|
||||
} else {
|
||||
entry->ticks = 0;
|
||||
entry->retry_ticks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates retry timer
|
||||
if (entry->retry_ticks > ticks) {
|
||||
entry->retry_ticks -= ticks;
|
||||
if (entry->waiting_ticks > ticks) {
|
||||
keep_timer_running = true;
|
||||
entry->waiting_ticks -= ticks;
|
||||
} else {
|
||||
if (entry->retry_ticks > 0) {
|
||||
tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
|
||||
if (entry->waiting_ticks > 0) {
|
||||
tr_info("Waiting supplicant timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
|
||||
}
|
||||
entry->retry_ticks = 0;
|
||||
entry->waiting_ticks = 0;
|
||||
}
|
||||
|
||||
if (!instance) {
|
||||
|
@ -350,7 +355,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
|
|||
entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
|
||||
}
|
||||
|
||||
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry)
|
||||
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted)
|
||||
{
|
||||
if (!entry->active) {
|
||||
return;
|
||||
|
@ -360,7 +365,7 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l
|
|||
|
||||
if (entry->access_revoked) {
|
||||
tr_info("Access revoked; deleted, eui-64: %s", trace_array(entry->addr.eui_64, 8));
|
||||
ws_pae_lib_supp_list_remove(active_supp_list, entry);
|
||||
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -368,10 +373,13 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l
|
|||
ws_pae_key_storage_supp_write(instance, entry);
|
||||
|
||||
// Remove supplicant entry
|
||||
ws_pae_lib_supp_list_remove(active_supp_list, entry);
|
||||
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
|
||||
if (supp_deleted) {
|
||||
supp_deleted(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge)
|
||||
void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted)
|
||||
{
|
||||
uint16_t active_supp = ns_list_count(active_supp_list);
|
||||
|
||||
|
@ -385,7 +393,7 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb
|
|||
ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) {
|
||||
if (remove_count > 0 && ws_pae_lib_kmp_list_empty(&entry->kmp_list)) {
|
||||
tr_info("Active supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8));
|
||||
ws_pae_lib_supp_list_remove(active_supp_list, entry);
|
||||
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
|
||||
remove_count--;
|
||||
} else {
|
||||
break;
|
||||
|
@ -394,16 +402,6 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb
|
|||
}
|
||||
}
|
||||
|
||||
bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number)
|
||||
{
|
||||
uint16_t active_supp = ns_list_count(active_supp_list);
|
||||
if (active_supp > max_number) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
|
||||
{
|
||||
uint16_t kmp_count = 0;
|
||||
|
@ -419,6 +417,17 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
|
|||
return kmp_count;
|
||||
}
|
||||
|
||||
bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry)
|
||||
{
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
if (entry == searched_entry) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size)
|
||||
{
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
|
@ -432,22 +441,6 @@ kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
|
||||
{
|
||||
supp_entry_t *retry_supp = NULL;
|
||||
|
||||
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||
// Finds entry with shortest timeout i.e. oldest one
|
||||
if (entry->retry_ticks > 0) {
|
||||
if (!retry_supp || retry_supp->retry_ticks > entry->retry_ticks) {
|
||||
retry_supp = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retry_supp;
|
||||
}
|
||||
|
||||
int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list)
|
||||
{
|
||||
ns_list_init(comp_list);
|
||||
|
|
|
@ -36,7 +36,7 @@ typedef struct supp_entry_s {
|
|||
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
|
||||
sec_prot_keys_t sec_keys; /**< Security keys */
|
||||
uint32_t ticks; /**< Ticks */
|
||||
uint16_t retry_ticks; /**< Retry ticks */
|
||||
uint16_t waiting_ticks; /**< Waiting ticks */
|
||||
uint16_t store_ticks; /**< NVM store ticks */
|
||||
bool active : 1; /**< Is active */
|
||||
bool access_revoked : 1; /**< Nodes access is revoked */
|
||||
|
@ -211,16 +211,26 @@ void ws_pae_lib_supp_list_init(supp_list_t *supp_list);
|
|||
*/
|
||||
supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_deleted supplicant delete callback
|
||||
*
|
||||
* \param instance Instance
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_lib_supp_deleted(void *instance);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_add removes entry from supplicant list
|
||||
*
|
||||
* \param instance Instance
|
||||
* \param supp_list supplicant list
|
||||
* \param entry entry
|
||||
* \param supp_deleted callback to call on supplicant delete
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*/
|
||||
int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *entry);
|
||||
int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_entry_eui_64_get gets entry from supplicant list based on EUI-64
|
||||
|
@ -249,11 +259,12 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list);
|
|||
* \param inactive_supp_list list of inactive supplicants
|
||||
* \param ticks timer ticks
|
||||
* \param timeout callback to call on timeout
|
||||
* \param supp_deleted callback to call on supplicant delete
|
||||
*
|
||||
* \return true timer needs still to be running
|
||||
* \return false timer can be stopped
|
||||
*/
|
||||
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
|
||||
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list
|
||||
|
@ -336,31 +347,23 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
|
|||
* \param instance Instance
|
||||
* \param active_supp_list list of active supplicants
|
||||
* \param entry supplicant entry
|
||||
* \param supp_deleted callback to call on supplicant delete
|
||||
*
|
||||
*/
|
||||
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry);
|
||||
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_purge purge inactive supplicants list
|
||||
*
|
||||
* \param instance Instance
|
||||
* \param active_supp_list list of active supplicants
|
||||
* \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge
|
||||
* to free list entries even when maximum number supplicant entries has not been reached
|
||||
* \param max_purge maximum number of supplicants to purge in one call, 0 means not limited
|
||||
* \param supp_deleted callback to call on supplicant delete
|
||||
*
|
||||
*/
|
||||
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_limit_reached_check check if active supplicant list limit has been reached
|
||||
*
|
||||
* \param active_supp_list list of active supplicants
|
||||
* \param max_number maximum number of supplicant entries
|
||||
*
|
||||
* \return true limit has been reached
|
||||
* \return false limit has not been reached
|
||||
*/
|
||||
bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number);
|
||||
void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants
|
||||
|
@ -373,6 +376,17 @@ bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, ui
|
|||
*/
|
||||
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_entry_is_in_list checks if the entry is in the list
|
||||
*
|
||||
* \param supp_list list of supplicants
|
||||
* \param searched_entry entry that is searched
|
||||
*
|
||||
* \return TRUE entry is in list, FALSE otherwise
|
||||
*
|
||||
*/
|
||||
bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_kmp_receive_check check if received message is for this KMP in a list of supplicants
|
||||
*
|
||||
|
@ -385,16 +399,6 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
|
|||
*/
|
||||
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
|
||||
*
|
||||
* \param supp_list list of supplicants
|
||||
*
|
||||
* \return supplicant with retry timer running or NULL if no supplicants with timer running
|
||||
*
|
||||
*/
|
||||
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_shared_comp_list_init init shared component list
|
||||
*
|
||||
|
|
|
@ -67,7 +67,7 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry)
|
|||
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, 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)
|
||||
{
|
||||
int len;
|
||||
tlv_entry->tag = PAE_NVM_NW_INFO_TAG;
|
||||
|
@ -87,6 +87,9 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
|
|||
memcpy((char *)tlv, nw_name, len);
|
||||
tlv += 33;
|
||||
|
||||
memcpy((char *)tlv, gtk_eui64, 8);
|
||||
tlv += 8;
|
||||
|
||||
uint64_t current_time = ws_pae_current_time_get();
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
|
@ -119,7 +122,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
|
|||
|
||||
}
|
||||
|
||||
int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, 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)
|
||||
{
|
||||
if (!tlv_entry || !pan_id || !nw_name) {
|
||||
return -1;
|
||||
|
@ -144,6 +147,9 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t
|
|||
}
|
||||
tlv += 33;
|
||||
|
||||
memcpy(gtk_eui64, (char *)tlv, 8);
|
||||
tlv += 8;
|
||||
|
||||
uint64_t current_time = ws_pae_current_time_get();
|
||||
|
||||
tr_debug("NVM NW_INFO current time: %"PRIi64, current_time);
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
#define PAE_NVM_KEY_STORAGE_INDEX_TAG 4
|
||||
#define PAE_NVM_KEY_STORAGE_TAG 5
|
||||
|
||||
// pan_id (2) + network name (33) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4
|
||||
#define PAE_NVM_NW_INFO_LEN 2 + 33 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
@ -95,7 +95,7 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry);
|
|||
* \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, 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);
|
||||
|
||||
/**
|
||||
* ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV
|
||||
|
@ -109,7 +109,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t
|
|||
* \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, 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);
|
||||
|
||||
/**
|
||||
* ws_pae_nvm_store_keys_tlv_create create NVM keys TLV
|
||||
|
|
|
@ -151,7 +151,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp);
|
|||
|
||||
static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
|
||||
static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
|
||||
static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static bool ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp);
|
||||
|
||||
|
||||
|
@ -429,11 +429,7 @@ static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_
|
|||
pae_supp->auth_trickle_running = false;
|
||||
if (pae_supp->auth_requested && pae_supp->auth_completed) {
|
||||
pae_supp->auth_requested = false;
|
||||
uint8_t *target_eui_64 = NULL;
|
||||
if (result != AUTH_RESULT_OK) {
|
||||
target_eui_64 = pae_supp->target_addr.eui_64;
|
||||
}
|
||||
pae_supp->auth_completed(pae_supp->interface_ptr, result, target_eui_64);
|
||||
pae_supp->auth_completed(pae_supp->interface_ptr, result, pae_supp->target_addr.eui_64);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -841,7 +837,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
|
|||
}
|
||||
auth_result_e result = AUTH_RESULT_ERR_UNSPEC;
|
||||
if (pae_supp->tx_failure_on_initial_key) {
|
||||
result = AUTH_RESULT_ERR_TX_NO_ACK;
|
||||
result = AUTH_RESULT_ERR_TX_ERR;
|
||||
pae_supp->tx_failure_on_initial_key = false;
|
||||
}
|
||||
ws_pae_supp_authenticate_response(pae_supp, result);
|
||||
|
@ -1226,12 +1222,12 @@ static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ
|
|||
kmp_api_create_response(kmp, KMP_RESULT_OK);
|
||||
}
|
||||
|
||||
static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
|
||||
static bool ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
|
||||
{
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
|
||||
if (!pae_supp) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
kmp_type_e type = kmp_api_type_get(kmp);
|
||||
|
@ -1254,7 +1250,7 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
|
|||
|
||||
/* If initial EAPOL-key message sending fails to tx no acknowledge, indicates failure so
|
||||
that bootstrap can decide if EAPOL target should be changed */
|
||||
else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) {
|
||||
else if (type > IEEE_802_1X_INITIAL_KEY && (result == KMP_RESULT_ERR_TX_NO_ACK || result == KMP_RESULT_ERR_TX_UNSPEC)) {
|
||||
tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
|
||||
/* Fails authentication only if other authentication protocols are not yet
|
||||
started by authenticator */
|
||||
|
@ -1263,6 +1259,8 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
|
|||
pae_supp->tx_failure_on_initial_key = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp)
|
||||
|
|
|
@ -51,20 +51,69 @@ int ws_statistics_stop(int8_t interface_id)
|
|||
|
||||
void ws_stats_update(protocol_interface_info_entry_t *cur, ws_stats_type_t type, uint32_t update_val)
|
||||
{
|
||||
if (!cur || !ws_info(cur)) {
|
||||
if (!cur || !ws_info(cur) || !cur->ws_info->stored_stats_ptr) {
|
||||
return;
|
||||
}
|
||||
ws_statistics_t *stored_stats = cur->ws_info->stored_stats_ptr;
|
||||
|
||||
if (stored_stats) {
|
||||
switch (type) {
|
||||
case STATS_WS_ASYNCH_TX:
|
||||
stored_stats->asynch_tx_count += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX:
|
||||
stored_stats->asynch_rx_count += update_val;
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case STATS_WS_ASYNCH_TX:
|
||||
stored_stats->asynch_tx_count += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX:
|
||||
stored_stats->asynch_rx_count += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_TX_PAS:
|
||||
stored_stats->sent_PAS += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_TX_PA:
|
||||
stored_stats->sent_PA += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_TX_PCS:
|
||||
stored_stats->sent_PCS += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_TX_PC:
|
||||
stored_stats->sent_PC += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX_PAS:
|
||||
stored_stats->recv_PAS += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX_PA:
|
||||
stored_stats->recv_PA += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX_PCS:
|
||||
stored_stats->recv_PCS += update_val;
|
||||
break;
|
||||
case STATS_WS_ASYNCH_RX_PC:
|
||||
stored_stats->recv_PC += update_val;
|
||||
break;
|
||||
case STATS_WS_STATE_1:
|
||||
stored_stats->join_state_1 += update_val;
|
||||
break;
|
||||
case STATS_WS_STATE_2:
|
||||
stored_stats->join_state_2 += update_val;
|
||||
break;
|
||||
case STATS_WS_STATE_3:
|
||||
stored_stats->join_state_3 += update_val;
|
||||
break;
|
||||
case STATS_WS_STATE_4:
|
||||
stored_stats->join_state_4 += update_val;
|
||||
break;
|
||||
case STATS_WS_STATE_5:
|
||||
stored_stats->join_state_5 += update_val;
|
||||
break;
|
||||
case STATS_WS_NEIGHBOUR_ADD:
|
||||
stored_stats->Neighbour_add += update_val;
|
||||
break;
|
||||
case STATS_WS_NEIGHBOUR_REMOVE:
|
||||
stored_stats->Neighbour_remove += update_val;
|
||||
break;
|
||||
case STATS_WS_CHILD_ADD:
|
||||
stored_stats->Child_add += update_val;
|
||||
break;
|
||||
case STATS_WS_CHILD_REMOVE:
|
||||
stored_stats->child_remove += update_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_WS
|
||||
|
|
|
@ -22,7 +22,24 @@
|
|||
|
||||
typedef enum {
|
||||
STATS_WS_ASYNCH_TX,
|
||||
STATS_WS_ASYNCH_RX
|
||||
STATS_WS_ASYNCH_RX,
|
||||
STATS_WS_ASYNCH_RX_PAS,
|
||||
STATS_WS_ASYNCH_RX_PA,
|
||||
STATS_WS_ASYNCH_RX_PCS,
|
||||
STATS_WS_ASYNCH_RX_PC,
|
||||
STATS_WS_ASYNCH_TX_PAS,
|
||||
STATS_WS_ASYNCH_TX_PA,
|
||||
STATS_WS_ASYNCH_TX_PCS,
|
||||
STATS_WS_ASYNCH_TX_PC,
|
||||
STATS_WS_STATE_1,
|
||||
STATS_WS_STATE_2,
|
||||
STATS_WS_STATE_3,
|
||||
STATS_WS_STATE_4,
|
||||
STATS_WS_STATE_5,
|
||||
STATS_WS_NEIGHBOUR_ADD,
|
||||
STATS_WS_NEIGHBOUR_REMOVE,
|
||||
STATS_WS_CHILD_ADD,
|
||||
STATS_WS_CHILD_REMOVE,
|
||||
} ws_stats_type_t;
|
||||
|
||||
void ws_stats_update(protocol_interface_info_entry_t *cur, ws_stats_type_t type, uint32_t update_val);
|
||||
|
|
|
@ -212,10 +212,12 @@ buffer_routing_info_t *ipv6_buffer_route_to(buffer_t *buf, const uint8_t *next_h
|
|||
* reduce an existing entry if route has changed) */
|
||||
if (dest_entry->pmtu > outgoing_if->ipv6_neighbour_cache.link_mtu) {
|
||||
dest_entry->pmtu = outgoing_if->ipv6_neighbour_cache.link_mtu;
|
||||
dest_entry->pmtu_lifetime = outgoing_if->pmtu_lifetime;
|
||||
}
|
||||
/* Route can also limit PMTU */
|
||||
if (dest_entry->pmtu > route->route_info.pmtu) {
|
||||
dest_entry->pmtu = route->route_info.pmtu;
|
||||
dest_entry->pmtu_lifetime = outgoing_if->pmtu_lifetime;
|
||||
}
|
||||
/* Buffer then gets this PMTU (overwriting what we wrote from the route) */
|
||||
route->route_info.pmtu = dest_entry->pmtu;
|
||||
|
@ -613,6 +615,16 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
|
|||
|
||||
/* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */
|
||||
if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) {
|
||||
|
||||
if (buffer_data_length(buf) > IPV6_MIN_LINK_MTU) {
|
||||
/* recover IP addresses that icmpv6_error needs, which routing code will have overwritten */
|
||||
buf->src_sa.addr_type = ADDR_IPV6;
|
||||
memcpy(buf->src_sa.address, buffer_data_pointer(buf) + IPV6_HDROFF_SRC_ADDR, 16);
|
||||
buf->dst_sa.addr_type = ADDR_IPV6;
|
||||
memcpy(buf->dst_sa.address, buffer_data_pointer(buf) + IPV6_HDROFF_DST_ADDR, 16);
|
||||
return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_PACKET_TOO_BIG, 0, IPV6_MIN_LINK_MTU);
|
||||
}
|
||||
|
||||
/* Avoid an infinite loop in the event of routing code failure - never
|
||||
* let them ask for tunnelling more than once.
|
||||
*/
|
||||
|
@ -623,6 +635,7 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
|
|||
buf->options.tunnelled = true;
|
||||
|
||||
buf->options.ip_extflags = 0;
|
||||
buf->options.ipv6_use_min_mtu = -1;
|
||||
|
||||
/* Provide tunnel source, unless already set */
|
||||
if (buf->src_sa.addr_type == ADDR_NONE) {
|
||||
|
@ -1003,7 +1016,7 @@ static buffer_t *ipv6_consider_forwarding_unicast_packet(buffer_t *buf, protocol
|
|||
|
||||
/* route_info.pmtu will cover limits from both the interface and the
|
||||
* route. As a bonus, it will also cover any PMTUD we happen to have done
|
||||
* to that destination ourselves, as well as mop up any tunnelling issues.
|
||||
* to that destination ourselves. Extra limits due to tunnelling are checked on tunnel entry in ipv6_down.
|
||||
*/
|
||||
if (routing->route_info.pmtu < buffer_data_length(buf)) {
|
||||
buf->interface = cur;
|
||||
|
@ -1349,6 +1362,9 @@ buffer_t *ipv6_forwarding_up(buffer_t *buf)
|
|||
}
|
||||
} else { /* unicast */
|
||||
if (!for_us) {
|
||||
if (cur->if_common_forwarding_out_cb) {
|
||||
cur->if_common_forwarding_out_cb(cur, buf);
|
||||
}
|
||||
return ipv6_consider_forwarding_unicast_packet(buf, cur, &ll_src);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef enum ipv6_exthdr_stage {
|
|||
* If it needs to insert headers that are not present, it can force insertion
|
||||
* into a tunnel, by:
|
||||
* setting dst_sa and src_sa appropriate for the tunnel endpoints
|
||||
* XXX does this work out okay with dest cache and PMTU?
|
||||
* src_sa.addr_type can be set to ADDR_NONE to auto-select tunnel source address
|
||||
* updating route info like next hop if necessary (probably not)
|
||||
* returning IPV6_EXTHDR_MODIFY_TUNNEL
|
||||
* During new header formation for the tunnel, IPV6_EXTHDR_INSERT will be
|
||||
|
|
|
@ -33,9 +33,9 @@ int ns_monitor_clear(void);
|
|||
|
||||
void ns_monitor_timer(uint16_t seconds);
|
||||
|
||||
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical);
|
||||
int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage);
|
||||
|
||||
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
|
||||
int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage);
|
||||
|
||||
bool ns_monitor_packet_allocation_allowed(void);
|
||||
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#define SOCKET_DEFAULT_STREAM_SNDLOWAT 512
|
||||
#endif
|
||||
|
||||
#ifndef SOCKET_DEFAULT_REFERENCE_LIMIT
|
||||
#define SOCKET_DEFAULT_REFERENCE_LIMIT 512
|
||||
#endif
|
||||
|
||||
typedef enum socket_family_e {
|
||||
SOCKET_FAMILY_NONE,
|
||||
SOCKET_FAMILY_IPV6,
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef struct ns_monitor__s {
|
|||
|
||||
static ns_monitor_t *ns_monitor_ptr = NULL;
|
||||
|
||||
static uint8_t ns_dyn_mem_rate_limiting_threshold_percentage = 0; // Percentage of free memory required to allow routing
|
||||
static ns_mem_heap_size_t ns_dyn_mem_rate_limiting_threshold = 0; // amount of free memory required to allow routing 0 = disabled
|
||||
|
||||
typedef void (ns_maintenance_gc_cb)(bool full_gc);
|
||||
|
||||
|
@ -176,32 +176,75 @@ int ns_monitor_clear(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
|
||||
int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage)
|
||||
{
|
||||
if (ns_monitor_ptr && (percentage_critical <= 100) && (percentage_high < percentage_critical)) {
|
||||
if (ns_monitor_ptr && (critical_percentage <= 100) && (high_percentage < critical_percentage)) {
|
||||
ns_monitor_ptr->heap_high_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
percentage_high
|
||||
high_percentage
|
||||
);
|
||||
if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark < high_min) {
|
||||
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_min;
|
||||
}
|
||||
|
||||
if (high_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark > high_max) {
|
||||
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_max;
|
||||
}
|
||||
|
||||
ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
percentage_critical
|
||||
critical_percentage
|
||||
);
|
||||
tr_debug("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
|
||||
if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark < critical_min) {
|
||||
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_min;
|
||||
}
|
||||
|
||||
if (critical_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark > critical_max) {
|
||||
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_max;
|
||||
}
|
||||
|
||||
tr_info("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
|
||||
int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage)
|
||||
{
|
||||
if (free_heap_percentage < 100) {
|
||||
ns_dyn_mem_rate_limiting_threshold_percentage = free_heap_percentage;
|
||||
/* To make this function dynamic and useful in larger range of memories the minimum value can be given
|
||||
*
|
||||
* example limit(1024, 1)
|
||||
* 32k RAM Limit = 1024
|
||||
* 64k RAM Limit = 1024
|
||||
* 128k RAM Limit = 1280
|
||||
* 320k RAM Limit = 3200
|
||||
*/
|
||||
if (free_heap_percentage == 0 && minimum_required == 0) {
|
||||
// Disable rate limiting
|
||||
ns_dyn_mem_rate_limiting_threshold = 0;
|
||||
return 0;
|
||||
}
|
||||
if (free_heap_percentage > 100) {
|
||||
// Sanity check this should not be high at all, but dont want to limit without any good reason
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
|
||||
if (ns_dyn_mem_stat && free_heap_percentage) {
|
||||
ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * free_heap_percentage;
|
||||
}
|
||||
|
||||
if (ns_dyn_mem_rate_limiting_threshold < minimum_required) {
|
||||
ns_dyn_mem_rate_limiting_threshold = minimum_required;
|
||||
}
|
||||
|
||||
if (Maximum_allowed && ns_dyn_mem_rate_limiting_threshold > Maximum_allowed) {
|
||||
ns_dyn_mem_rate_limiting_threshold = Maximum_allowed;
|
||||
}
|
||||
tr_info("Monitor rate limit incoming packets at:%lu", (unsigned long)ns_dyn_mem_rate_limiting_threshold);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ns_monitor_packet_allocation_allowed(void)
|
||||
|
@ -212,8 +255,8 @@ bool ns_monitor_packet_allocation_allowed(void)
|
|||
|
||||
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
|
||||
|
||||
if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold_percentage) {
|
||||
if (ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_stat->heap_sector_size / 100 * (100 - ns_dyn_mem_rate_limiting_threshold_percentage)) {
|
||||
if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold) {
|
||||
if (ns_dyn_mem_stat->heap_sector_size - ns_dyn_mem_stat->heap_sector_allocated_bytes < ns_dyn_mem_rate_limiting_threshold) {
|
||||
// Packet allocation not allowed as memory is running low.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#define RANDOM_PORT_NUMBER_COUNT (RANDOM_PORT_NUMBER_END - RANDOM_PORT_NUMBER_START + 1)
|
||||
#define RANDOM_PORT_NUMBER_MAX_STEP 500
|
||||
|
||||
static bool socket_reference_limit(socket_t *socket_ptr);
|
||||
|
||||
static uint16_t port_counter;
|
||||
|
||||
static socket_t *socket_instance[SOCKETS_MAX];
|
||||
|
@ -113,6 +115,7 @@ socket_t *socket_pointer_get(int8_t socket)
|
|||
|
||||
static void socket_data_event_push(buffer_t *buf)
|
||||
{
|
||||
buf->socket = socket_reference(buf->socket);
|
||||
arm_event_s event = {
|
||||
.receiver = socket_event_handler,
|
||||
.sender = 0,
|
||||
|
@ -137,6 +140,7 @@ bool socket_data_queued_event_push(socket_t *socket)
|
|||
};
|
||||
|
||||
if (eventOS_event_send(&event) != 0) {
|
||||
socket_dereference(socket);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -167,12 +171,8 @@ static void socket_cb_event_run(const socket_cb_event_t *event)
|
|||
}
|
||||
}
|
||||
|
||||
void socket_buffer_cb_run(socket_t *socket, buffer_t *buffer)
|
||||
static void socket_buffer_cb_run(socket_t *socket, buffer_t *buffer)
|
||||
{
|
||||
if (socket->id == -1 || !socket->u.live.fptr) {
|
||||
buffer_free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
eventOS_scheduler_set_active_tasklet(socket->tasklet);
|
||||
|
||||
|
@ -222,9 +222,19 @@ void socket_tasklet_event_handler(arm_event_s *event)
|
|||
}
|
||||
case ARM_SOCKET_DATA_CB: {
|
||||
buffer_t *buf = event->data_ptr;
|
||||
/* Reference the socket here*/
|
||||
socket_t *socket = socket_reference(buf->socket);
|
||||
if (socket->flags & SOCKET_BUFFER_CB) {
|
||||
|
||||
if (!buf || !buf->socket) {
|
||||
tr_error("Socket CB: Buf or Socket pointer NULL");
|
||||
buffer_free(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
socket_t *socket = buf->socket;
|
||||
|
||||
if (socket->id == -1 || !socket->u.live.fptr) {
|
||||
//Socket is released Free just Buffer
|
||||
buffer_free(buf);
|
||||
} else if (socket->flags & SOCKET_BUFFER_CB) {
|
||||
// They just take ownership of the buffer. No read calls.
|
||||
socket_buffer_cb_run(socket, buf);
|
||||
} else {
|
||||
|
@ -243,7 +253,9 @@ void socket_tasklet_event_handler(arm_event_s *event)
|
|||
}
|
||||
case ARM_SOCKET_DATA_QUEUED_CB: {
|
||||
socket_t *socket = event->data_ptr;
|
||||
socket_cb_run(socket);
|
||||
if (socket) {
|
||||
socket_cb_run(socket);
|
||||
}
|
||||
socket_dereference(socket);
|
||||
break;
|
||||
}
|
||||
|
@ -454,6 +466,14 @@ socket_t *socket_allocate(socket_type_t type)
|
|||
return socket;
|
||||
}
|
||||
|
||||
static bool socket_reference_limit(socket_t *socket_ptr)
|
||||
{
|
||||
if (socket_ptr && socket_ptr->refcount < SOCKET_DEFAULT_REFERENCE_LIMIT) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Increase reference counter on socket, returning now-owned pointer */
|
||||
socket_t *socket_reference(socket_t *socket_ptr)
|
||||
{
|
||||
|
@ -479,7 +499,7 @@ socket_t *socket_dereference(socket_t *socket_ptr)
|
|||
}
|
||||
|
||||
if (socket_ptr->refcount == 0) {
|
||||
tr_error("ref underflow");
|
||||
tr_error("Socket %d ref underflow", socket_ptr->id);
|
||||
return NULL;
|
||||
}
|
||||
if (--socket_ptr->refcount == 0) {
|
||||
|
@ -870,6 +890,13 @@ socket_error_t socket_up(buffer_t *buf)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
//Limit here
|
||||
if (socket_reference_limit(socket)) {
|
||||
tr_error("Socket reference limit drop RX %u", socket->refcount);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
||||
if (socket->rcvq.data_byte_limit == 0) {
|
||||
// Old-style one event per buffer
|
||||
socket_data_event_push(buf);
|
||||
|
@ -1092,7 +1119,7 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr
|
|||
|
||||
#ifndef NO_TCP
|
||||
if (socket_ptr->type == SOCKET_TYPE_STREAM) {
|
||||
tcp_session_t *tcp_info = tcp_info(inet_pcb);
|
||||
tcp_session_t *tcp_info = inet_pcb->session;
|
||||
if (!tcp_info) {
|
||||
tr_warn("No TCP session for cur Socket");
|
||||
ret_val = -3;
|
||||
|
@ -1113,6 +1140,12 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr
|
|||
// Everything below this point is non-TCP
|
||||
#endif //NO_TCP
|
||||
|
||||
if (socket_reference_limit(socket_ptr)) {
|
||||
tr_error("Socket reference limit drop TX %u", socket_ptr->refcount);
|
||||
ret_val = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark Socket id to buffer meta data
|
||||
*/
|
||||
|
|
|
@ -93,7 +93,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
|
|||
//Validate Client DUID
|
||||
dhcp_link_options_params_t clientDUID;
|
||||
if (libdhcpv6_get_link_address_from_duid(replyPacket->clientDUID.duid, replyPacket->clientDUID.duid_length, replyPacket->clientDUID.type, &clientDUID) == 0) {
|
||||
dhcp_allocated_address = libdhcpv6_address_allocated_list_scan(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew);
|
||||
dhcp_allocated_address = libdhcpv6_address_allocate(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew);
|
||||
}
|
||||
if (dhcp_allocated_address) {
|
||||
address_allocated = true;
|
||||
|
@ -109,7 +109,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
|
|||
|
||||
if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) {
|
||||
address_allocated = false;
|
||||
libdhcpv6_address_rm_from_allocated_list(serverBase, dhcp_allocated_address->nonTemporalAddress);
|
||||
libdhcpv6_address_delete(serverBase, dhcp_allocated_address->nonTemporalAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,9 +299,9 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8],
|
|||
ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) {
|
||||
//Delete Server data base
|
||||
if (serverInfo->removeCb) {
|
||||
uint8_t allocated_address[16];
|
||||
libdhcpv6_allocated_address_write(allocated_address, cur, serverInfo);
|
||||
serverInfo->removeCb(interface, allocated_address, NULL);
|
||||
uint8_t ipAddress[16];
|
||||
libdhcpv6_allocated_address_write(ipAddress, cur, serverInfo);
|
||||
serverInfo->removeCb(interface, ipAddress, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,12 +327,19 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8],
|
|||
|
||||
/* Control GUA address for client by DUI.Default value is true
|
||||
*
|
||||
* Anonymous and disable address list can optimize either
|
||||
* Using 16 bit suffix to optimize data amount in network
|
||||
* and having list of assigned addresses meaning larger RAM usage at border router
|
||||
*
|
||||
* or Using SLAAC type address generation and not have a list of addresses at Border router
|
||||
* -> Less RAM usage, but more bandwidth used
|
||||
*
|
||||
* /param interface interface id of this thread instance.
|
||||
* /param guaPrefix Prefix which will be removed
|
||||
* /param mode true trig autonous mode, false define address by default suffics + client id
|
||||
* /param mode true assign addresses anonymously. false define address by Prefix + client id
|
||||
* /param disable_address_list Dont keep track of assigned Addresses (Can't be used if anonymous)
|
||||
*/
|
||||
int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list)
|
||||
int DHCPv6_server_service_set_address_generation_anonymous(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool disable_address_list)
|
||||
{
|
||||
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
|
||||
if (!serverInfo) {
|
||||
|
@ -340,12 +347,13 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu
|
|||
|
||||
}
|
||||
|
||||
serverInfo->enableAddressAutonous = mode;
|
||||
serverInfo->anonymousAddress = mode;
|
||||
if (mode) {
|
||||
serverInfo->disableAddressListAllocation = autonomous_skip_list;
|
||||
serverInfo->disableAddressList = disable_address_list;
|
||||
} else {
|
||||
serverInfo->disableAddressListAllocation = false;
|
||||
serverInfo->disableAddressList = false;
|
||||
}
|
||||
tr_info("DHCPv6 %s, address list %s", mode ? "anonymous address" : "address mode SLAAC", disable_address_list ? "Not Stored" : "Stored");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -375,6 +383,7 @@ int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static
|
|||
if (!serverInfo) {
|
||||
return -1;
|
||||
}
|
||||
tr_info("DHCPv6 duid %s", trace_array(duid_ptr, duid_length));
|
||||
|
||||
return libdhcpv6_server_duid_set(serverInfo, duid_ptr, duid_type, duid_length);
|
||||
}
|
||||
|
@ -399,6 +408,7 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_
|
|||
}
|
||||
|
||||
serverInfo->maxSupportedClients = maxClientCount;
|
||||
tr_info("DHCPv6 maximum clients %"PRIu32, serverInfo->maxSupportedClients);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -421,6 +431,7 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
|
|||
return -1;
|
||||
}
|
||||
serverInfo->validLifetime = validLifeTimne;
|
||||
tr_info("DHCPv6 Valid lifetime %"PRIu32, serverInfo->validLifetime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -510,7 +521,7 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds)
|
|||
{
|
||||
(void) timeUpdateInSeconds;
|
||||
}
|
||||
int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list)
|
||||
int DHCPv6_server_service_set_address_generation_anonymous(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list)
|
||||
{
|
||||
(void) interface;
|
||||
(void) guaPrefix;
|
||||
|
|
|
@ -62,13 +62,19 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds);
|
|||
|
||||
/* Control GUA address for client by DUI.Default value is true
|
||||
*
|
||||
* Anonymous and disable address list can optimize either
|
||||
* Using 16 bit suffix to optimize data amount in network
|
||||
* and having list of assigned addresses meaning larger RAM usage at border router
|
||||
*
|
||||
* or Using SLAAC type address generation and not have a list of addresses at Border router
|
||||
* -> Less RAM usage, but more bandwidth used
|
||||
*
|
||||
* /param interface interface id of this thread instance.
|
||||
* /param guaPrefix Prefix which will be removed
|
||||
* /param mode true trig autonous mode, false define address by default suffics + client id
|
||||
* /param autonomous_skip_list true skip address list allocation when autonous mode is selected
|
||||
* /param mode true assign addresses anonymously. false define address by Prefix + client id
|
||||
* /param disable_address_list Dont keep track of assigned Addresses (Can't be used if anonymous)
|
||||
*/
|
||||
int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list);
|
||||
int DHCPv6_server_service_set_address_generation_anonymous(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list);
|
||||
|
||||
|
||||
/* SET max accepted clients to server, Default is 200
|
||||
|
|
|
@ -139,6 +139,8 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
|
|||
|
||||
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
|
||||
|
||||
void dhcp_relay_agent_interface_id_option_enable(int8_t interface, bool enable);
|
||||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16]);
|
||||
|
||||
|
||||
|
|
|
@ -175,6 +175,16 @@ void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[sta
|
|||
dhcp_service_relay_instance_enable(dhcp_client->relay_instance, border_router_address);
|
||||
}
|
||||
|
||||
void dhcp_relay_agent_interface_id_option_enable(int8_t interface, bool enable)
|
||||
{
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_service_relay_interface_id_option_enable(dhcp_client->relay_instance, enable);
|
||||
}
|
||||
|
||||
void dhcp_client_delete(int8_t interface)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = NULL;
|
||||
|
|
|
@ -91,6 +91,13 @@ typedef struct mac_pre_build_frame {
|
|||
uint8_t csma_periods_left;
|
||||
uint8_t fhss_retry_count;
|
||||
uint8_t fhss_cca_retry_count;
|
||||
uint8_t stored_retry_cnt;
|
||||
uint8_t stored_cca_cnt;
|
||||
uint8_t cca_request_restart_cnt;
|
||||
uint8_t tx_request_restart_cnt;
|
||||
uint8_t priority;
|
||||
uint32_t blacklist_start_time_us;
|
||||
uint16_t blacklist_period_ms;
|
||||
uint16_t initial_tx_channel;
|
||||
uint32_t tx_time;
|
||||
bool upper_layer_request: 1;
|
||||
|
@ -101,7 +108,7 @@ typedef struct mac_pre_build_frame {
|
|||
bool ExtendedFrameExchange: 1;
|
||||
bool WaitResponse: 1;
|
||||
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
|
||||
unsigned priority: 2;
|
||||
unsigned stored_priority: 2;
|
||||
struct mac_pre_build_frame *next; //Pointer for queue purpose
|
||||
} mac_pre_build_frame_t;
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ typedef enum mac_event_t {
|
|||
MAC_TX_TIMEOUT,
|
||||
MAC_ACK_SECURITY_FAIL,
|
||||
MAC_UNKNOWN_DESTINATION,
|
||||
MAC_TX_PRECOND_FAIL
|
||||
MAC_TX_PRECOND_FAIL,
|
||||
MAC_RETURN_TO_QUEUE
|
||||
} mac_event_t;
|
||||
|
||||
typedef enum mac_tx_status_type_t {
|
||||
|
@ -123,6 +124,7 @@ typedef struct dev_driver_tx_buffer {
|
|||
#define MAC_CCA_MAX 8
|
||||
#define MAC_DEF_MIN_BE 3
|
||||
#define MAC_DEF_MAX_BE 5
|
||||
#define MAC_PRIORITY_EF_BACKOFF_MULTIPLIER 2
|
||||
|
||||
typedef struct mac_active_scan {
|
||||
uint8_t pan_id[2];
|
||||
|
@ -245,6 +247,10 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
uint8_t mac_sequence;
|
||||
uint8_t mac_tx_retry;
|
||||
uint8_t mac_cca_retry;
|
||||
uint8_t cca_failure_restart_max;
|
||||
uint8_t tx_failure_restart_max;
|
||||
uint16_t blacklist_min_ms;
|
||||
uint16_t blacklist_max_ms;
|
||||
uint16_t mac_ack_wait_duration;
|
||||
uint8_t mac_mlme_retry_max;
|
||||
uint8_t aUnitBackoffPeriod;
|
||||
|
@ -272,7 +278,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
int8_t bc_timer_id;
|
||||
uint32_t mlme_tick_count;
|
||||
uint32_t symbol_rate;
|
||||
uint32_t symbol_time_us;
|
||||
uint32_t symbol_time_ns;
|
||||
uint32_t datarate;
|
||||
uint8_t max_ED;
|
||||
uint16_t mlme_ED_counter;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "platform/arm_hal_interrupt.h"
|
||||
#include "common_functions.h"
|
||||
#include "Core/include/ns_monitor.h"
|
||||
#include "randLIB.h"
|
||||
|
||||
#include "MAC/IEEE802_15_4/sw_mac_internal.h"
|
||||
#include "MAC/IEEE802_15_4/mac_defines.h"
|
||||
|
@ -153,7 +154,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);
|
||||
mcps_sap_data_req_handler_ext(rf_mac_setup, data_req, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY);
|
||||
}
|
||||
|
||||
static bool mac_ie_vector_length_validate(ns_ie_iovec_t *ie_vector, uint16_t iov_length, uint16_t *length_out)
|
||||
|
@ -192,7 +193,7 @@ 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)
|
||||
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 status = MLME_SUCCESS;
|
||||
mac_pre_build_frame_t *buffer = NULL;
|
||||
|
@ -264,6 +265,27 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
|
|||
buffer->asynch_request = true;
|
||||
}
|
||||
|
||||
//Set Priority level
|
||||
switch (priority) {
|
||||
case MAC_DATA_EXPEDITE_FORWARD:
|
||||
buffer->priority = MAC_PD_DATA_EF_PRIORITY;
|
||||
// Enable FHSS expedited forwarding
|
||||
if (rf_mac_setup->fhss_api) {
|
||||
rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_EXPEDITED_FORWARDING, 0);
|
||||
}
|
||||
break;
|
||||
case MAC_DATA_HIGH_PRIORITY:
|
||||
buffer->priority = MAC_PD_DATA_HIGH_PRIOTITY;
|
||||
break;
|
||||
case MAC_DATA_MEDIUM_PRIORITY:
|
||||
buffer->priority = MAC_PD_DATA_MEDIUM_PRIORITY;
|
||||
break;
|
||||
default:
|
||||
buffer->priority = MAC_PD_DATA_NORMAL_PRIORITY;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
buffer->upper_layer_request = true;
|
||||
buffer->fcf_dsn.frametype = FC_DATA_FRAME;
|
||||
buffer->ExtendedFrameExchange = data_req->ExtendedFrameExchange;
|
||||
|
@ -353,6 +375,12 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
|
|||
buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn);
|
||||
buffer->mac_payload = data_req->msdu;
|
||||
buffer->mac_payload_length = data_req->msduLength;
|
||||
buffer->cca_request_restart_cnt = rf_mac_setup->cca_failure_restart_max;
|
||||
// Multiply number of backoffs for higher priority packets
|
||||
if (buffer->priority == MAC_PD_DATA_EF_PRIORITY) {
|
||||
buffer->cca_request_restart_cnt *= MAC_PRIORITY_EF_BACKOFF_MULTIPLIER;
|
||||
}
|
||||
buffer->tx_request_restart_cnt = rf_mac_setup->tx_failure_restart_max;
|
||||
//check that header + payload length is not bigger than MAC MTU
|
||||
|
||||
if (data_req->InDirectTx) {
|
||||
|
@ -1498,6 +1526,66 @@ static bool mcps_buffer_edfe_data_failure(protocol_interface_rf_mac_setup_s *rf_
|
|||
return false;
|
||||
}
|
||||
|
||||
static void mcps_set_packet_blacklist(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer, uint8_t number_of_restarts)
|
||||
{
|
||||
/*
|
||||
* Random min = configured blacklist min << attempt count, but never larger than configured blacklist max / 2.
|
||||
* Random max = random min * 2, but never larger than blacklist max.
|
||||
* Example:
|
||||
* blacklist_min_ms: 20ms
|
||||
* blacklist_max_ms: 300ms
|
||||
* blacklist_retry_attempts: 4
|
||||
*
|
||||
* Packet is blacklisted:
|
||||
* 20ms - 40ms after 1st failure
|
||||
* 40ms - 80ms after 2nd failure
|
||||
* 80ms - 160ms after 3rd failure
|
||||
* 150ms - 300ms after 4th failure
|
||||
*/
|
||||
uint8_t i = 0;
|
||||
uint32_t blacklist_min_ms = 0;
|
||||
while (i < number_of_restarts) {
|
||||
blacklist_min_ms = rf_ptr->blacklist_min_ms << i;
|
||||
if (blacklist_min_ms > (rf_ptr->blacklist_max_ms / 2)) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
uint32_t blacklist_max_ms = blacklist_min_ms * 2;
|
||||
if (blacklist_min_ms > (rf_ptr->blacklist_max_ms / 2)) {
|
||||
blacklist_min_ms = (rf_ptr->blacklist_max_ms / 2);
|
||||
}
|
||||
if (blacklist_max_ms > rf_ptr->blacklist_max_ms) {
|
||||
blacklist_max_ms = rf_ptr->blacklist_max_ms;
|
||||
}
|
||||
buffer->blacklist_period_ms = randLIB_get_random_in_range(blacklist_min_ms, blacklist_max_ms);
|
||||
if (!buffer->blacklist_period_ms) {
|
||||
buffer->blacklist_period_ms++;
|
||||
}
|
||||
buffer->blacklist_start_time_us = mac_mcps_sap_get_phy_timestamp(rf_ptr);
|
||||
}
|
||||
|
||||
static bool mcps_update_packet_request_restart(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
|
||||
{
|
||||
// Function returns true when buffer needs to be requeued
|
||||
if (!rf_ptr || !buffer) {
|
||||
return false;
|
||||
}
|
||||
if (rf_ptr->mac_tx_result == MAC_CCA_FAIL && buffer->cca_request_restart_cnt) {
|
||||
buffer->cca_request_restart_cnt--;
|
||||
if (buffer->priority == MAC_PD_DATA_EF_PRIORITY) {
|
||||
mcps_set_packet_blacklist(rf_ptr, buffer, (rf_ptr->cca_failure_restart_max * MAC_PRIORITY_EF_BACKOFF_MULTIPLIER) - buffer->cca_request_restart_cnt);
|
||||
} else {
|
||||
mcps_set_packet_blacklist(rf_ptr, buffer, rf_ptr->cca_failure_restart_max - buffer->cca_request_restart_cnt);
|
||||
}
|
||||
return true;
|
||||
} else if (rf_ptr->mac_tx_result == MAC_TX_FAIL && buffer->tx_request_restart_cnt) {
|
||||
buffer->tx_request_restart_cnt--;
|
||||
mcps_set_packet_blacklist(rf_ptr, buffer, rf_ptr->tx_failure_restart_max - buffer->tx_request_restart_cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer, mac_pre_parsed_frame_t *ack_buf)
|
||||
{
|
||||
|
@ -1506,12 +1594,17 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr,
|
|||
sw_mac_stats_update(rf_ptr, STAT_MAC_TX_RETRY, rf_ptr->mac_tx_status.retry);
|
||||
mcps_data_conf_t confirm;
|
||||
if (rf_ptr->fhss_api && !buffer->asynch_request) {
|
||||
// FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted
|
||||
if (!mcps_buffer_edfe_data_failure(rf_ptr, buffer) && ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL))) {
|
||||
if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), rf_ptr->mac_tx_start_channel) == true) {
|
||||
|
||||
if (!mcps_buffer_edfe_data_failure(rf_ptr, buffer) && ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL) || (rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE))) {
|
||||
// Packet has return to queue status or it needs to be blacklisted and queued
|
||||
if ((rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE) || mcps_update_packet_request_restart(rf_ptr, buffer) == true) {
|
||||
if (rf_ptr->mac_tx_result == MAC_TX_FAIL) {
|
||||
buffer->fhss_retry_count += 1 + rf_ptr->mac_tx_status.retry;
|
||||
} else if (rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE) {
|
||||
buffer->stored_retry_cnt = rf_ptr->mac_tx_retry;
|
||||
buffer->stored_cca_cnt = rf_ptr->mac_cca_retry;
|
||||
buffer->stored_priority = buffer->priority;
|
||||
// Use priority to transmit it first when proper channel is available
|
||||
buffer->priority = MAC_PD_DATA_TX_IMMEDIATELY;
|
||||
} else {
|
||||
buffer->fhss_retry_count += rf_ptr->mac_tx_status.retry;
|
||||
}
|
||||
|
@ -2135,8 +2228,16 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma
|
|||
rf_ptr->macTxRequestAck = false;
|
||||
|
||||
memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t));
|
||||
rf_ptr->mac_cca_retry = 0;
|
||||
rf_ptr->mac_tx_retry = 0;
|
||||
if (buffer->priority == MAC_PD_DATA_TX_IMMEDIATELY) {
|
||||
// Return original priority and retry/CCA counts
|
||||
buffer->priority = buffer->stored_priority;
|
||||
rf_ptr->mac_tx_retry = rf_ptr->mac_tx_status.retry = buffer->stored_retry_cnt;
|
||||
rf_ptr->mac_cca_retry = rf_ptr->mac_tx_status.cca_cnt = buffer->stored_cca_cnt;
|
||||
buffer->stored_retry_cnt = buffer->stored_cca_cnt = 0;
|
||||
} else {
|
||||
rf_ptr->mac_tx_retry = 0;
|
||||
rf_ptr->mac_cca_retry = 0;
|
||||
}
|
||||
rf_ptr->mac_tx_start_channel = rf_ptr->mac_channel;
|
||||
mac_csma_param_init(rf_ptr);
|
||||
if (mcps_generic_packet_build(rf_ptr, buffer) != 0) {
|
||||
|
@ -2198,6 +2299,17 @@ int mac_convert_frame_type_to_fhss(uint8_t frame_type)
|
|||
return FHSS_DATA_FRAME;
|
||||
}
|
||||
|
||||
static bool mcps_check_packet_blacklist(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
|
||||
{
|
||||
if (!buffer->blacklist_period_ms) {
|
||||
return false;
|
||||
}
|
||||
if ((mac_mcps_sap_get_phy_timestamp(rf_mac_setup) - buffer->blacklist_start_time_us) >= (buffer->blacklist_period_ms * 1000)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
|
||||
{
|
||||
if (!rf_mac_setup || !buffer) {
|
||||
|
@ -2216,9 +2328,9 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup
|
|||
}
|
||||
if (rf_mac_setup->fhss_api && (buffer->asynch_request == false)) {
|
||||
uint16_t frame_length = buffer->mac_payload_length + buffer->headerIeLength + buffer->payloadsIeLength;
|
||||
if (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
||||
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), frame_length,
|
||||
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == false) {
|
||||
if ((mcps_check_packet_blacklist(rf_mac_setup, buffer) == true) || rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
||||
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), frame_length,
|
||||
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == false) {
|
||||
if (buffer->ExtendedFrameExchange) {
|
||||
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||
}
|
||||
|
@ -2321,9 +2433,12 @@ static mac_pre_build_frame_t *mcps_sap_pd_req_queue_read(protocol_interface_rf_m
|
|||
// With FHSS, check TX conditions
|
||||
if (rf_mac_setup->fhss_api) {
|
||||
while (buffer) {
|
||||
if (buffer->asynch_request || (flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
||||
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length,
|
||||
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true)) {
|
||||
if (buffer->asynch_request ||
|
||||
(flush == true) ||
|
||||
((mcps_check_packet_blacklist(rf_mac_setup, buffer) == false) &&
|
||||
(rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
||||
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length,
|
||||
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true))) {
|
||||
break;
|
||||
}
|
||||
prev = buffer;
|
||||
|
|
|
@ -49,6 +49,8 @@ typedef enum {
|
|||
#define MAC_PD_DATA_NORMAL_PRIORITY 0 //Normal MCPS DATA REQ
|
||||
#define MAC_PD_DATA_MEDIUM_PRIORITY 1 //Indirect Data which is polled
|
||||
#define MAC_PD_DATA_HIGH_PRIOTITY 2 //Beacon request Beacon response
|
||||
#define MAC_PD_DATA_EF_PRIORITY 3 //Expedited forwarding
|
||||
#define MAC_PD_DATA_TX_IMMEDIATELY 4 //Only for packets whose transmission was interrupted by wrong channel type. E.g. unicast on broadcast channel.
|
||||
|
||||
#define MCPS_SAP_DATA_IND_EVENT 1
|
||||
#define MCPS_SAP_DATA_CNF_EVENT 2
|
||||
|
@ -121,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);
|
||||
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 mac_mcps_trig_buffer_from_queue(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
||||
|
||||
|
|
|
@ -449,6 +449,8 @@ int8_t mac_mlme_reset(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlm
|
|||
rf_mac_setup->macWaitingData = false;
|
||||
rf_mac_setup->macDataPollReq = false;
|
||||
rf_mac_setup->macRxDataAtPoll = false;
|
||||
rf_mac_setup->macTxProcessActive = false;
|
||||
rf_mac_setup->mac_ack_tx_active = false;
|
||||
//Clean MAC
|
||||
if (reset->SetDefaultPIB) {
|
||||
tr_debug("RESET MAC PIB");
|
||||
|
@ -596,7 +598,7 @@ static int8_t mac_mlme_8bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup,
|
|||
break;
|
||||
|
||||
case macMaxBE:
|
||||
if (value > 8 || value < 3) {
|
||||
if (value > 8 || value < 1) {
|
||||
return -1;
|
||||
}
|
||||
rf_mac_setup->macMaxBE = value;
|
||||
|
@ -652,11 +654,11 @@ void mac_extended_mac_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const
|
|||
|
||||
static uint32_t mac_calc_ack_wait_duration(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t symbols)
|
||||
{
|
||||
uint32_t AckWaitDuration = 0;
|
||||
uint32_t AckWaitDuration_us = 0;
|
||||
if (rf_mac_setup->rf_csma_extension_supported) {
|
||||
AckWaitDuration = symbols * rf_mac_setup->symbol_time_us;
|
||||
AckWaitDuration_us = (symbols * rf_mac_setup->symbol_time_ns) / 1000;
|
||||
}
|
||||
return AckWaitDuration;
|
||||
return AckWaitDuration_us;
|
||||
}
|
||||
|
||||
static int8_t mac_mlme_set_ack_wait_duration(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
|
||||
|
@ -747,6 +749,18 @@ static int8_t mac_mlme_set_multi_csma_parameters(protocol_interface_rf_mac_setup
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t mac_mlme_set_data_request_restart_config(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
|
||||
{
|
||||
mlme_request_restart_config_t request_restart_config;
|
||||
memcpy(&request_restart_config, set_req->value_pointer, sizeof(mlme_request_restart_config_t));
|
||||
rf_mac_setup->cca_failure_restart_max = request_restart_config.cca_failure_restart_max;
|
||||
rf_mac_setup->tx_failure_restart_max = request_restart_config.tx_failure_restart_max;
|
||||
rf_mac_setup->blacklist_min_ms = request_restart_config.blacklist_min_ms;
|
||||
rf_mac_setup->blacklist_max_ms = request_restart_config.blacklist_max_ms;
|
||||
tr_debug("Request restart config: CCA %u, TX %u, min %u, max %u", rf_mac_setup->cca_failure_restart_max, rf_mac_setup->tx_failure_restart_max, rf_mac_setup->blacklist_min_ms, rf_mac_setup->blacklist_max_ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
|
||||
{
|
||||
if (!set_req || !rf_mac_setup || !rf_mac_setup->dev_driver || !rf_mac_setup->dev_driver->phy_driver) {
|
||||
|
@ -816,6 +830,8 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
|||
return 0;
|
||||
case macMultiCSMAParameters:
|
||||
return mac_mlme_set_multi_csma_parameters(rf_mac_setup, set_req);
|
||||
case macRequestRestart:
|
||||
return mac_mlme_set_data_request_restart_config(rf_mac_setup, set_req);
|
||||
case macRfConfiguration:
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) set_req->value_pointer);
|
||||
mac_mlme_set_symbol_rate(rf_mac_setup);
|
||||
|
@ -1107,8 +1123,8 @@ static int mac_mlme_set_symbol_rate(protocol_interface_rf_mac_setup_s *rf_mac_se
|
|||
{
|
||||
if (rf_mac_setup->rf_csma_extension_supported) {
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_SYMBOLS_PER_SECOND, (uint8_t *) &rf_mac_setup->symbol_rate);
|
||||
rf_mac_setup->symbol_time_us = 1000000 / rf_mac_setup->symbol_rate;
|
||||
tr_debug("SW-MAC driver support rf extension %"PRIu32" symbol/seconds %"PRIu32" us symbol time length", rf_mac_setup->symbol_rate, rf_mac_setup->symbol_time_us);
|
||||
rf_mac_setup->symbol_time_ns = 1000000000 / rf_mac_setup->symbol_rate;
|
||||
tr_debug("SW-MAC driver support rf extension %"PRIu32" symbol/seconds %"PRIu32" ns symbol time length", rf_mac_setup->symbol_rate, rf_mac_setup->symbol_time_ns);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -97,7 +97,7 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
uint32_t backoff_in_us;
|
||||
//Multiple aUnitBackoffPeriod symbol time
|
||||
if (rf_mac_setup->rf_csma_extension_supported) {
|
||||
backoff_in_us = backoff * rf_mac_setup->aUnitBackoffPeriod * rf_mac_setup->symbol_time_us;
|
||||
backoff_in_us = backoff * rf_mac_setup->aUnitBackoffPeriod * (rf_mac_setup->symbol_time_ns / 1000);
|
||||
} else {
|
||||
backoff_in_us = backoff * rf_mac_setup->backoff_period_in_10us * 10;
|
||||
}
|
||||
|
@ -189,6 +189,9 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
length = tx_buf->len;
|
||||
}
|
||||
if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) {
|
||||
#ifdef TIMING_TOOL_TRACES
|
||||
tr_info("%u CSMA_start", mac_mcps_sap_get_phy_timestamp(rf_mac_setup));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -451,9 +454,13 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TIMING_TOOL_TRACES
|
||||
if ((status == PHY_LINK_CCA_FAIL) || (status == PHY_LINK_CCA_FAIL_RX) || (status == PHY_LINK_CCA_PREPARE)) {
|
||||
tr_info("%u CSMA_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == PHY_LINK_CCA_PREPARE) {
|
||||
|
||||
|
||||
if (rf_ptr->mac_ack_tx_active || rf_ptr->mac_edfe_tx_active) {
|
||||
goto VALIDATE_TX_TIME;
|
||||
}
|
||||
|
@ -485,10 +492,12 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
mac_sap_cca_fail_cb(rf_ptr, 0xffff);
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
// When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back
|
||||
// to queue by using CCA fail event
|
||||
// When FHSS TX handle returns -3, we are trying to:
|
||||
// - transmit broadcast packet on unicast channel
|
||||
// - transmit unicast packet on broadcast channel
|
||||
// Push back to queue to allow sending applicable packet
|
||||
if (tx_handle_retval == -3) {
|
||||
mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
|
||||
mac_tx_done_state_set(rf_ptr, MAC_RETURN_TO_QUEUE);
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
} else if (tx_handle_retval == -2) {
|
||||
mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION);
|
||||
|
@ -505,6 +514,9 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
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);
|
||||
#ifdef TIMING_TOOL_TRACES
|
||||
tr_info("%u CSMA_start", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||
#endif
|
||||
return PHY_RESTART_CSMA;
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +559,8 @@ VALIDATE_TX_TIME:
|
|||
|
||||
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
|
||||
// Do not update CCA count when CCA_OK is received, PHY_LINK_TX_SUCCESS will update it
|
||||
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK)) {
|
||||
// Do not update CCA count when CCA fail was because of active reception, MAC will restart CCA check in this case
|
||||
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK) && (status != PHY_LINK_CCA_FAIL_RX)) {
|
||||
/* For PHY_LINK_TX_SUCCESS and PHY_LINK_CCA_FAIL cca_retry must always be > 0.
|
||||
* PHY_LINK_TX_FAIL either happened during transmission or when waiting Ack -> we must use the CCA count given by PHY.
|
||||
*/
|
||||
|
@ -581,6 +594,9 @@ VALIDATE_TX_TIME:
|
|||
} else if (status == PHY_LINK_CCA_FAIL) {
|
||||
waiting_ack = false;
|
||||
tx_completed = false;
|
||||
} else if (status == PHY_LINK_CCA_FAIL_RX) {
|
||||
waiting_ack = false;
|
||||
tx_completed = false;
|
||||
} else if (status == PHY_LINK_CCA_OK) {
|
||||
waiting_ack = false;
|
||||
tx_completed = false;
|
||||
|
@ -608,6 +624,7 @@ VALIDATE_TX_TIME:
|
|||
break;
|
||||
|
||||
case PHY_LINK_CCA_FAIL:
|
||||
case PHY_LINK_CCA_FAIL_RX:
|
||||
mac_sap_cca_fail_cb(rf_ptr, failed_channel);
|
||||
break;
|
||||
|
||||
|
|
|
@ -600,7 +600,7 @@ void mac_sec_mib_key_device_frame_counter_set(mlme_key_descriptor_t *key_descpri
|
|||
if (key_descpription_table->KeyFrameCounterPerKey) {
|
||||
uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCounterList + attribute_index;
|
||||
*counter_ptr = frame_counter;
|
||||
} else {
|
||||
} else if (device_info) {
|
||||
device_info->FrameCounter = frame_counter;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static int8_t ns_sw_mac_api_enable_edfe_ext(mac_api_t *api, mcps_edfe_handler *e
|
|||
|
||||
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);
|
||||
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 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);
|
||||
|
@ -575,22 +575,22 @@ void mlme_req(const mac_api_t *api, mlme_primitive id, const void *data)
|
|||
}
|
||||
}
|
||||
|
||||
void mcps_req(const mac_api_t *api, const mcps_data_req_t *data)
|
||||
static void mcps_req(const mac_api_t *api, const mcps_data_req_t *data)
|
||||
{
|
||||
//TODO: Populate linked list when present
|
||||
if (mac_store.mac_api == api) {
|
||||
/* 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);
|
||||
mcps_sap_data_req_handler_ext(mac_store.setup, data, &ie_list, NULL, MAC_DATA_NORMAL_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
//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);
|
||||
mcps_sap_data_req_handler_ext(mac_store.setup, data, ie_ext, asynch_channel_list, priority);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1065,6 +1065,7 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i
|
|||
if (!domain) {
|
||||
// We will need to tunnel - do nothing on the inner packet
|
||||
*result = 0;
|
||||
buf->options.ipv6_use_min_mtu = 1;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef enum icmp_state {
|
|||
ER_BOOTSTRAP_NEW_FRAGMENT_START,
|
||||
ER_WAIT_RESTART,
|
||||
ER_RPL_LOCAL_REPAIR,
|
||||
ER_RPL_NETWORK_LEAVING,
|
||||
} icmp_state_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -447,6 +448,8 @@ struct protocol_interface_info_entry {
|
|||
br_info_t *border_router_setup;
|
||||
struct load_balance_api *lb_api;
|
||||
struct red_info_s *random_early_detection;
|
||||
struct red_info_s *llc_random_early_detection;
|
||||
struct red_info_s *llc_eapol_random_early_detection;
|
||||
neigh_cache_s neigh_cache;
|
||||
pan_blaclist_cache_s pan_blaclist_cache;
|
||||
pan_coordinator_blaclist_cache_s pan_cordinator_black_list;
|
||||
|
@ -471,6 +474,7 @@ struct protocol_interface_info_entry {
|
|||
int8_t (*if_down)(struct protocol_interface_info_entry *cur);
|
||||
int8_t (*if_up)(struct protocol_interface_info_entry *cur);
|
||||
void (*if_stack_buffer_handler)(buffer_t *);
|
||||
void (*if_common_forwarding_out_cb)(struct protocol_interface_info_entry *, buffer_t *);
|
||||
bool (*if_ns_transmit)(struct protocol_interface_info_entry *cur, ipv6_neighbour_t *neighCacheEntry, bool unicast, uint8_t seq);
|
||||
bool (*if_map_ip_to_link_addr)(struct protocol_interface_info_entry *cur, const uint8_t *ip_addr, addrtype_t *ll_type, const uint8_t **ll_addr_out);
|
||||
bool (*if_map_link_addr_to_ip)(struct protocol_interface_info_entry *cur, addrtype_t ll_type, const uint8_t *ll_addr, uint8_t *ip_addr_out);
|
||||
|
|
|
@ -265,6 +265,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
|
|||
cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, false);
|
||||
}
|
||||
etx_cache_timer(cur->id, seconds);
|
||||
lowpan_adaptation_interface_slow_timer(cur);
|
||||
}
|
||||
} else if (cur->nwk_id == IF_IPV6) {
|
||||
//Slow Pointer Update
|
||||
|
@ -461,6 +462,7 @@ static void protocol_core_base_init(protocol_interface_info_entry_t *entry, nwk_
|
|||
entry->ipv6_configure = NULL;
|
||||
entry->if_lowpan_security_params = NULL;
|
||||
entry->if_ns_transmit = NULL;
|
||||
entry->if_common_forwarding_out_cb = NULL;
|
||||
entry->if_special_forwarding = NULL;
|
||||
entry->if_snoop = NULL;
|
||||
entry->if_icmp_handler = NULL;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "RPL/rpl_downward.h"
|
||||
#include "RPL/rpl_policy.h"
|
||||
#include "RPL/rpl_control.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
|
||||
#define TRACE_GROUP "rplc"
|
||||
|
||||
|
@ -204,6 +205,12 @@ void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size)
|
|||
rpl_policy_set_mrhof_parent_set_size(parent_set_size);
|
||||
}
|
||||
|
||||
/* True Force RPL to use IPv6 tunneling when it send and forward data to Border router direction, This feature is disabled by default */
|
||||
void rpl_control_set_force_tunnel(bool requested)
|
||||
{
|
||||
rpl_policy_force_tunnel_set(requested);
|
||||
}
|
||||
|
||||
/* Send address registration to either specified address, or to non-registered address */
|
||||
void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16])
|
||||
{
|
||||
|
@ -300,6 +307,25 @@ bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interfa
|
|||
return false;
|
||||
}
|
||||
|
||||
uint16_t rpl_control_neighbor_info_get(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t *global_address)
|
||||
{
|
||||
|
||||
if (!interface->rpl_domain) {
|
||||
return 0xffff;
|
||||
}
|
||||
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
|
||||
rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id);
|
||||
if (neighbour) {
|
||||
const uint8_t *global_address_ptr = rpl_neighbour_global_address(neighbour);
|
||||
if (global_address && global_address_ptr) {
|
||||
memcpy(global_address, global_address_ptr, 16);
|
||||
}
|
||||
return rpl_instance_candidate_rank(neighbour);
|
||||
}
|
||||
}
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, rpl_instance_t *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx)
|
||||
{
|
||||
if (!interface->rpl_domain) {
|
||||
|
@ -399,6 +425,7 @@ static void rpl_control_etx_change_callback(int8_t nwk_id, uint16_t previous_et
|
|||
if (!cur || !cur->rpl_domain) {
|
||||
return;
|
||||
}
|
||||
(void) attribute_index;
|
||||
// ETX is "better" if now lower, or previous was "unknown" and new isn't infinite
|
||||
bool better = current_etx < previous_etx || (previous_etx == 0 && current_etx != 0xffff);
|
||||
|
||||
|
@ -444,6 +471,9 @@ rpl_domain_t *rpl_control_create_domain(void)
|
|||
ns_list_init(&domain->instances);
|
||||
domain->non_storing_downstream_interface = -1;
|
||||
domain->callback = NULL;
|
||||
domain->new_parent_add = NULL;
|
||||
domain->parent_dis = NULL;
|
||||
domain->prefix_cb = NULL;
|
||||
domain->cb_handle = NULL;
|
||||
domain->force_leaf = false;
|
||||
domain->process_routes = true;
|
||||
|
@ -520,12 +550,13 @@ void rpl_control_free_domain_instances_from_interface(protocol_interface_info_en
|
|||
}
|
||||
}
|
||||
|
||||
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle)
|
||||
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, rpl_parent_dis_callback_t parent_dis, void *cb_handle)
|
||||
{
|
||||
domain->callback = callback;
|
||||
domain->prefix_cb = prefix_learn_cb;
|
||||
domain->cb_handle = cb_handle;
|
||||
domain->new_parent_add = new_parent_add;
|
||||
domain->parent_dis = parent_dis;
|
||||
}
|
||||
|
||||
/* To do - this should live somewhere nicer. Basically a bootstrap
|
||||
|
@ -554,6 +585,11 @@ bool rpl_control_have_dodag(rpl_domain_t *domain)
|
|||
|
||||
typedef void rpl_control_predicate_loop_fn_t(rpl_instance_t *instance, rpl_dodag_version_t *version, void *arg);
|
||||
|
||||
typedef struct rpl_loopfn_trigger_unicast_dio_arg {
|
||||
struct protocol_interface_info_entry *interface;
|
||||
const uint8_t *dst;
|
||||
} rpl_loopfn_trigger_unicast_dio_arg_t;
|
||||
|
||||
/* Callbacks for rpl_control_predicate_loop */
|
||||
|
||||
static void rpl_loopfn_reset_dio_timer(rpl_instance_t *instance, rpl_dodag_version_t *dodag_version, void *handle)
|
||||
|
@ -562,12 +598,19 @@ static void rpl_loopfn_reset_dio_timer(rpl_instance_t *instance, rpl_dodag_versi
|
|||
(void)handle;
|
||||
|
||||
rpl_instance_inconsistency(instance);
|
||||
}
|
||||
//Check was Multicast DIS from parent
|
||||
rpl_loopfn_trigger_unicast_dio_arg_t *arg = handle;
|
||||
rpl_domain_t *domain = arg->interface->rpl_domain;
|
||||
if (domain && domain->parent_dis) {
|
||||
|
||||
typedef struct rpl_loopfn_trigger_unicast_dio_arg {
|
||||
struct protocol_interface_info_entry *interface;
|
||||
const uint8_t *dst;
|
||||
} rpl_loopfn_trigger_unicast_dio_arg_t;
|
||||
if (rpl_instance_address_is_parent(instance, arg->dst)) {
|
||||
// Call Multicast DIS parent Callback
|
||||
domain->parent_dis(arg->dst, arg->interface, instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void rpl_loopfn_trigger_unicast_dio(rpl_instance_t *instance, rpl_dodag_version_t *dodag_version, void *handle)
|
||||
{
|
||||
|
@ -879,6 +922,11 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
|
|||
uint32_t preferred = common_read_32_bit(ptr + 8);
|
||||
const uint8_t *prefix = ptr + 16;
|
||||
|
||||
if (ws_info(cur)) {
|
||||
//For Wi-SUN Interoperability force length to 64
|
||||
prefix_len = 64;
|
||||
}
|
||||
|
||||
if (rpl_upward_accept_prefix_update(dodag, neighbour, pref_parent)) {
|
||||
|
||||
/* Store prefixes for possible forwarding */
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef enum rpl_event {
|
|||
RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/
|
||||
RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */
|
||||
RPL_EVENT_DAO_PARENT_ADD, /* RPL indicate that DAO downward Parent has been added */
|
||||
RPL_EVENT_POISON_FINISHED, /* RPL have finished Dodag Poison proces */
|
||||
} rpl_event_t;
|
||||
|
||||
typedef void rpl_domain_callback_t(rpl_event_t event, void *handle);
|
||||
|
@ -44,6 +45,8 @@ typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle,
|
|||
|
||||
typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank);
|
||||
|
||||
typedef void rpl_parent_dis_callback_t(const uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance);
|
||||
|
||||
typedef struct rpl_route_info {
|
||||
uint8_t node[8]; /* IID of parent in parent child relation table */
|
||||
uint8_t parent[8]; /* IID of child in parent child relation table */
|
||||
|
@ -64,6 +67,7 @@ typedef struct rpl_domain {
|
|||
rpl_domain_callback_t *callback;
|
||||
rpl_prefix_callback_t *prefix_cb;
|
||||
rpl_new_parent_callback_t *new_parent_add;
|
||||
rpl_parent_dis_callback_t *parent_dis;
|
||||
void *cb_handle;
|
||||
} rpl_domain_t;
|
||||
|
||||
|
@ -158,7 +162,7 @@ void rpl_control_delete_domain(rpl_domain_t *domain);
|
|||
void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream);
|
||||
void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur);
|
||||
void rpl_control_free_domain_instances_from_interface(struct protocol_interface_info_entry *cur);
|
||||
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle);
|
||||
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, rpl_parent_dis_callback_t parent_dis, void *cb_handle);
|
||||
|
||||
/* Target publishing */
|
||||
void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime);
|
||||
|
@ -166,6 +170,7 @@ void rpl_control_unpublish_address(rpl_domain_t *domain, const uint8_t addr[16])
|
|||
bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
|
||||
bool rpl_control_is_dodag_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint16_t candidate_cmp_limiter);
|
||||
bool rpl_control_probe_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
|
||||
uint16_t rpl_control_neighbor_info_get(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t *global_address);
|
||||
bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx);
|
||||
uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list);
|
||||
uint16_t rpl_control_candidate_list_size(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance);
|
||||
|
@ -176,6 +181,7 @@ bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *inter
|
|||
|
||||
/* Parent link confirmation API extension */
|
||||
void rpl_control_request_parent_link_confirmation(bool requested);
|
||||
void rpl_control_set_force_tunnel(bool requested);
|
||||
void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count);
|
||||
void rpl_control_set_address_registration_timeout(uint16_t timeout_in_minutes);
|
||||
void rpl_control_set_dao_retry_count(uint8_t count);
|
||||
|
@ -200,6 +206,7 @@ const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance *
|
|||
const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global);
|
||||
uint16_t rpl_control_current_rank(const struct rpl_instance *instance);
|
||||
uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain);
|
||||
void rpl_control_instant_poison(struct protocol_interface_info_entry *cur, rpl_domain_t *domain);
|
||||
|
||||
#else /* HAVE_RPL */
|
||||
|
||||
|
@ -211,6 +218,7 @@ uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain);
|
|||
#define rpl_control_address_register_done(interface, ll_addr, status) (false)
|
||||
#define rpl_policy_mrhof_parent_set_size_get(domain) (0)
|
||||
#define rpl_control_set_mrhof_parent_set_size(parent_set_size)
|
||||
#define rpl_control_instant_poison(cur, domain) ((void) 0)
|
||||
#endif /* HAVE_RPL */
|
||||
|
||||
#endif /* RPL_CONTROL_H_ */
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "RPL/rpl_structures.h"
|
||||
#include "RPL/rpl_policy.h"
|
||||
#include "RPL/rpl_data.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
|
||||
#define TRACE_GROUP "RPLa"
|
||||
|
||||
|
@ -334,8 +335,24 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i
|
|||
|
||||
bool destination_in_instance = false;
|
||||
uint16_t ext_size = 0;
|
||||
if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) ||
|
||||
addr_ipv6_equal(buf->dst_sa.address, dodag->id)) {
|
||||
|
||||
// Limit creation of multi-hop RPL packets
|
||||
// Previous code created multi-hop RPL packets as much as possible,
|
||||
// sending direct to border router in particular.
|
||||
// This has caused WiSUN interop problems, so limit this.
|
||||
// a) When creating a basic packet, have a policy option that prevents
|
||||
// direct RPL header insertion, forcing tunnelling. This means
|
||||
// we never put a RPL header on the innermost packet. Option is
|
||||
// off by default, except for WiSUN, as it increases packet size
|
||||
// when talking to the border router (eg DAOs).
|
||||
// b) When putting a packet into a tunnel, set the tunnel exit to the
|
||||
// next hop always, rather than having a special case for exiting
|
||||
// at the border router. This is probably a net benefit to packet
|
||||
// size because of the LL addresses used on the outer header, so
|
||||
// this is an unconditional change. Exception remains for local
|
||||
// DODAGs, where the destination address must be the DODAGID.
|
||||
if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) || (!rpl_policy_force_tunnel() &&
|
||||
addr_ipv6_equal(buf->dst_sa.address, dodag->id))) {
|
||||
destination_in_instance = true;
|
||||
|
||||
if (buf->rpl_option) {
|
||||
|
@ -357,6 +374,7 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i
|
|||
case IPV6_EXTHDR_INSERT: {
|
||||
if (!destination_in_instance) {
|
||||
/* We don't add a header - we'll do it on the tunnel */
|
||||
buf->options.ipv6_use_min_mtu = 1;
|
||||
*result = 0;
|
||||
return buf;
|
||||
}
|
||||
|
@ -409,10 +427,12 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i
|
|||
rpl_data_locate_info(buf, &opt, NULL);
|
||||
if (!opt) {
|
||||
*result = IPV6_EXTHDR_MODIFY_TUNNEL;
|
||||
// Tunnel to next hop in general case, but if going to DODAGID,
|
||||
// it can tunnel all the way (and it HAS to if it is a local
|
||||
// DODAG).
|
||||
if (!addr_ipv6_equal(buf->dst_sa.address, dodag->id)) {
|
||||
// Tunnel to next hop always, even if we could tunnel all
|
||||
// the way to DODAG root (this may be better for
|
||||
// packet compression, and it was found to be necessary for
|
||||
// Wi-SUN interoperability). Except for local DODAGs the
|
||||
// destination must be the DODAGID, so retain that in dst_sa.
|
||||
if (!rpl_instance_id_is_local(instance->id)) {
|
||||
memcpy(buf->dst_sa.address, route_info->next_hop_addr, 16);
|
||||
}
|
||||
buf->src_sa.addr_type = ADDR_NONE; // force auto-selection
|
||||
|
@ -427,18 +447,20 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i
|
|||
* strictly less for Down packets and strictly greater for Up.
|
||||
*/
|
||||
sender_rank = common_read_16_bit(opt + 4);
|
||||
rpl_cmp_t cmp = rpl_rank_compare_dagrank_rank(dodag, sender_rank, instance->current_rank);
|
||||
rpl_cmp_t expected_cmp = (opt[2] & RPL_OPT_DOWN) ? RPL_CMP_LESS : RPL_CMP_GREATER;
|
||||
if (cmp != expected_cmp) {
|
||||
/* Set the Rank-Error bit; if already set, drop */
|
||||
if (opt[2] & RPL_OPT_RANK_ERROR) {
|
||||
protocol_stats_update(STATS_RPL_ROUTELOOP, 1);
|
||||
tr_info("Forwarding inconsistency R");
|
||||
rpl_instance_inconsistency(instance);
|
||||
*result = -1;
|
||||
return buf;
|
||||
} else {
|
||||
opt[2] |= RPL_OPT_RANK_ERROR;
|
||||
if (sender_rank != 0) {
|
||||
rpl_cmp_t cmp = rpl_rank_compare_dagrank_rank(dodag, sender_rank, instance->current_rank);
|
||||
rpl_cmp_t expected_cmp = (opt[2] & RPL_OPT_DOWN) ? RPL_CMP_LESS : RPL_CMP_GREATER;
|
||||
if (cmp != expected_cmp) {
|
||||
/* Set the Rank-Error bit; if already set, drop */
|
||||
if (opt[2] & RPL_OPT_RANK_ERROR) {
|
||||
protocol_stats_update(STATS_RPL_ROUTELOOP, 1);
|
||||
tr_info("Forwarding inconsistency R");
|
||||
rpl_instance_inconsistency(instance);
|
||||
*result = -1;
|
||||
return buf;
|
||||
} else {
|
||||
opt[2] |= RPL_OPT_RANK_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -944,6 +966,7 @@ static buffer_t *rpl_data_exthdr_provider_srh(buffer_t *buf, ipv6_exthdr_stage_t
|
|||
if (!buf->options.tunnelled) {
|
||||
if (stage == IPV6_EXTHDR_SIZE || stage == IPV6_EXTHDR_INSERT) {
|
||||
*result = 0;
|
||||
buf->options.ipv6_use_min_mtu = 1;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
@ -1034,6 +1057,11 @@ drop:
|
|||
|
||||
buf->options.ip_extflags |= IPEXT_SRH_RPL;
|
||||
|
||||
if (ws_info(cur)) {
|
||||
//Call SRC route header handler hook to Wi-SUN refresh border router alive
|
||||
ws_common_border_router_alive_update(cur);
|
||||
}
|
||||
|
||||
uint16_t hlen = (ptr[1] + 1) * 8;
|
||||
uint8_t segs_left = ptr[3];
|
||||
|
||||
|
|
|
@ -48,6 +48,17 @@ static uint8_t rpl_policy_mrhof_parent_set_size_conf = 3; // default parent set
|
|||
static uint16_t rpl_policy_minimum_dao_target_refresh_conf = 0; // by default follow the configuration
|
||||
static uint16_t rpl_policy_address_registration_timeout_value = 0; // Address registration timeouts in minutes 0 use address lifetime
|
||||
|
||||
static bool rpl_policy_force_tunnel_to_BR = false;
|
||||
|
||||
bool rpl_policy_force_tunnel(void)
|
||||
{
|
||||
return rpl_policy_force_tunnel_to_BR;
|
||||
}
|
||||
|
||||
void rpl_policy_force_tunnel_set(bool enable)
|
||||
{
|
||||
rpl_policy_force_tunnel_to_BR = enable;
|
||||
}
|
||||
/* TODO - application API to control when to join new instances / DODAGs
|
||||
*
|
||||
* Eg, allow application to ignore local DODAGs, or specify known instance IDs,
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include "Core/include/ns_address_internal.h"
|
||||
#include "rpl_control.h"
|
||||
|
||||
bool rpl_policy_force_tunnel(void);
|
||||
void rpl_policy_force_tunnel_set(bool enable);
|
||||
|
||||
bool rpl_policy_join_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid);
|
||||
bool rpl_policy_join_dodag(rpl_domain_t *domain, uint8_t g_mop_prf, uint8_t instance_id, const uint8_t *dodagid);
|
||||
bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, bool *leaf_only);
|
||||
|
|
|
@ -347,6 +347,14 @@ void rpl_instance_poison(rpl_instance_t *instance, uint8_t count)
|
|||
rpl_instance_inconsistency(instance);
|
||||
}
|
||||
|
||||
void rpl_control_instant_poison(protocol_interface_info_entry_t *cur, rpl_domain_t *domain)
|
||||
{
|
||||
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
|
||||
rpl_instance_poison(instance, 1);
|
||||
rpl_instance_dio_trigger(instance, cur, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void rpl_instance_force_leaf(rpl_instance_t *instance)
|
||||
{
|
||||
instance->current_rank = RPL_RANK_INFINITE;
|
||||
|
@ -363,7 +371,7 @@ void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t de
|
|||
}
|
||||
}
|
||||
if (instance->parent_selection_timer == 0 || instance->parent_selection_timer > delay) {
|
||||
instance->parent_selection_timer = randLIB_randomise_base(delay, 0x8000, 0x999A) /* Random between delay * 1.0-1.2 */;
|
||||
instance->parent_selection_timer = randLIB_randomise_base(delay, 0x8000, 0xc000) /* Random between delay * 1.0-1.5 */;
|
||||
tr_debug("Timed parent triggered %u", instance->parent_selection_timer);
|
||||
}
|
||||
}
|
||||
|
@ -1594,6 +1602,45 @@ void rpl_instance_remove_interface(rpl_instance_t *instance, int8_t if_id)
|
|||
}
|
||||
}
|
||||
|
||||
static bool rpl_instance_parent_selected(rpl_instance_t *instance)
|
||||
{
|
||||
if (rpl_instance_am_root(instance)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We don't have DAO target generated
|
||||
if (ns_list_count(&instance->dao_targets) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't have any valid parent selected
|
||||
if (!rpl_instance_parent_selection_ready(instance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rpl_instance_dao_route_registered(rpl_instance_t *instance)
|
||||
{
|
||||
if (rpl_instance_am_root(instance)) {
|
||||
//Border router is allways at stable state
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Address registrations for parent ongoing*/
|
||||
if (rpl_policy_parent_confirmation_requested() && instance->pending_neighbour_confirmation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */
|
||||
if (instance->dao_in_transit || instance->delay_dao_timer > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Trigger DIO transmission - all interfaces multicast if addr+cur are NULL, else unicast */
|
||||
void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_entry_t *cur, const uint8_t *addr)
|
||||
{
|
||||
|
@ -1620,12 +1667,23 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_
|
|||
instance->poison_count--;
|
||||
rank = RPL_RANK_INFINITE;
|
||||
tr_debug("Poison count -> set RPL_RANK_INFINITE");
|
||||
if (instance->poison_count == 0) {
|
||||
//Report RPL user that Poison message is triggered
|
||||
rpl_control_event(instance->domain, RPL_EVENT_POISON_FINISHED);
|
||||
}
|
||||
}
|
||||
|
||||
// Always send config in unicasts (as required), never in multicasts (optional)
|
||||
rpl_dodag_conf_t *conf;
|
||||
if (addr) {
|
||||
conf = &dodag->config;
|
||||
//Unicast
|
||||
if (rank != RPL_RANK_INFINITE) {
|
||||
if (!rpl_instance_parent_selected(instance)) {
|
||||
tr_debug("parent selection not ready. DIO rank INFINITE");
|
||||
rank = RPL_RANK_INFINITE;
|
||||
}
|
||||
}
|
||||
} else if (dodag->new_config_advertisment_count < rpl_policy_dio_multicast_config_advertisment_min_count()) {
|
||||
conf = &dodag->config;
|
||||
if (dodag->new_config_advertisment_count < 0xfe) {
|
||||
|
@ -1637,6 +1695,10 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_
|
|||
|
||||
rpl_control_transmit_dio(instance->domain, cur, instance->id, dodag_version->number, rank, dodag->g_mop_prf, instance->dtsn, dodag, dodag->id, conf, addr);
|
||||
|
||||
if (addr) {
|
||||
return;
|
||||
}
|
||||
|
||||
dodag_version->last_advertised_rank = rank;
|
||||
|
||||
/* When we advertise a new lowest rank, need to re-evaluate our rank limits */
|
||||
|
@ -1716,8 +1778,10 @@ void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair)
|
|||
instance->repair_dis_count = 0;
|
||||
} else {
|
||||
instance->repair_dis_timer = 0;
|
||||
instance->advertised_dodag_membership_since_last_repair = false;
|
||||
|
||||
}
|
||||
//SET False allways for guarantee reboot possibility
|
||||
instance->advertised_dodag_membership_since_last_repair = false;
|
||||
|
||||
/* When repair ends, eliminate all higher-rank neighbours (potential sub-DODAG) from table */
|
||||
if (!repair && instance->current_dodag_version) {
|
||||
|
@ -1843,21 +1907,12 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks)
|
|||
/* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */
|
||||
if (!rpl_instance_am_root(instance) && !instance->poison_count && !instance->advertised_dodag_membership_since_last_repair && rpl_policy_parent_confirmation_requested()) {
|
||||
|
||||
// We don't have DAO target generated
|
||||
if (ns_list_count(&instance->dao_targets) == 0) {
|
||||
//Validate Parent is selected and registered
|
||||
if (!rpl_instance_parent_selected(instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't have any valid parent selected
|
||||
if (!rpl_instance_parent_selection_ready(instance)) {
|
||||
return;
|
||||
}
|
||||
/* Address registrations for parent ongoing*/
|
||||
if (instance->pending_neighbour_confirmation) {
|
||||
return;
|
||||
}
|
||||
/* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */
|
||||
if (instance->dao_in_transit || instance->delay_dao_timer > 0) {
|
||||
//Verify that DAO is registered
|
||||
if (!rpl_instance_dao_route_registered(instance)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,6 +128,10 @@ void tls_server_hash_copy(uint8_t *ptr, tls_msg_t *tmp_msg, sec_suite_t *suite)
|
|||
tls_build_server_hello_msg(ptr, suite->tls_session);
|
||||
tls_handshake_copy(tmp_msg, t_heap);
|
||||
tr_debug("Pana server S-Hello,Cert hash");
|
||||
#else
|
||||
(void) ptr;
|
||||
(void) tmp_msg;
|
||||
(void) suite;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1721,6 +1721,8 @@ static void pana_client_authentication_fail(sec_suite_t *suite)
|
|||
int8_t pana_server_nvm_callback_set(pana_server_update_cb *update_cb, pana_server_session_get_cb *nvm_get, pana_server_session_get_by_id_cb *nvm_session_get, uint8_t *nvm_static_buffer)
|
||||
{
|
||||
(void)update_cb;
|
||||
(void)nvm_get;
|
||||
(void)nvm_session_get;
|
||||
(void)nvm_static_buffer;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,9 @@ static uint8_t tls_parse_server_key_exchange(uint8_t *ptr, uint16_t len, sec_sui
|
|||
|
||||
static uint8_t *tls_set_client_key_excange(uint8_t *ptr, sec_suite_t *tls_suite);
|
||||
static uint8_t tls_parse_server_hello(uint8_t *ptr, sec_suite_t *tls_suite);
|
||||
#ifdef PANA_SERVER_API
|
||||
static uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
||||
#endif
|
||||
static tls_psk_key_t *tls_get_key(uint16_t key_id);
|
||||
|
||||
tls_session_t *amr_tls_session_allocate(void)
|
||||
|
@ -171,7 +173,7 @@ void tls_finnish_copy(uint8_t *ptr, tls_heap_t *heap_ptr)
|
|||
|
||||
}
|
||||
|
||||
uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
||||
static uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
||||
{
|
||||
uint8_t ret_val = 0, i = 0;
|
||||
uint16_t tls_version;
|
||||
|
@ -548,6 +550,7 @@ uint8_t tls_parse_server_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *t
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ECC
|
||||
static uint8_t tls_parse_client_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
||||
{
|
||||
(void)len;
|
||||
|
@ -567,6 +570,7 @@ static uint8_t tls_parse_client_key_exchange(uint8_t *ptr, uint16_t len, sec_sui
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void tls_read_certi_signature(tls_heap_t *theap, uint8_t certificate)
|
||||
|
@ -589,8 +593,8 @@ void tls_read_certi_signature(tls_heap_t *theap, uint8_t certificate)
|
|||
|
||||
}
|
||||
|
||||
|
||||
uint8_t tls_parse_certificate_verify(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
||||
#ifdef ECC
|
||||
static uint8_t tls_parse_certificate_verify(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
||||
{
|
||||
(void)len;
|
||||
uint16_t sig_algh, sig_len;
|
||||
|
@ -653,7 +657,7 @@ uint8_t tls_parse_certificate_verify(uint8_t *ptr, uint16_t len, sec_suite_t *tl
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
tls_ecc_heap_t *ecc_allocate_ram(void)
|
||||
{
|
||||
|
@ -1690,6 +1694,7 @@ buffer_t *tls_server_up(buffer_t *buf, sec_suite_t *tls_suite)
|
|||
buf = tls_certificate_buffer_store(buf, certi_rx, tls_suite);
|
||||
}
|
||||
#else
|
||||
(void)tls_suite;
|
||||
if (buf) {
|
||||
buf = buffer_free(buf);
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ static uint8_t kmp_instance_identifier = 0;
|
|||
static kmp_msg_if_entry_t *kmp_api_msg_if_get(kmp_service_t *service, uint8_t msg_if_instance_id);
|
||||
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result);
|
||||
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot);
|
||||
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||
static bool kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||
static void kmp_api_sec_prot_finished(sec_prot_t *prot);
|
||||
static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||
static int8_t kmp_sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags);
|
||||
|
@ -234,10 +234,10 @@ static void kmp_api_sec_prot_create_indication(sec_prot_t *prot)
|
|||
kmp->create_ind((kmp_api_t *)kmp, kmp->type, kmp->addr);
|
||||
}
|
||||
|
||||
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
static bool kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
||||
kmp->finished_ind((kmp_api_t *)kmp, (kmp_result_e) result, sec_keys);
|
||||
return kmp->finished_ind((kmp_api_t *)kmp, (kmp_result_e) result, sec_keys);
|
||||
}
|
||||
|
||||
static void kmp_api_sec_prot_finished(sec_prot_t *prot)
|
||||
|
@ -598,8 +598,7 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, k
|
|||
int8_t ret = -1;
|
||||
if (kmp->sec_prot.receive != NULL) {
|
||||
ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size);
|
||||
}
|
||||
if (kmp->sec_prot.conn_receive != NULL) {
|
||||
} else if (kmp->sec_prot.conn_receive != NULL) {
|
||||
ret = kmp->sec_prot.conn_receive(&kmp->sec_prot, pdu, size, connection_num);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ typedef enum {
|
|||
typedef enum {
|
||||
KMP_RESULT_OK = 0, // Successful
|
||||
KMP_RESULT_ERR_NO_MEM = -1, // No memory
|
||||
KMP_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received
|
||||
KMP_RESULT_ERR_UNSPEC = -3 // Other reason
|
||||
KMP_RESULT_ERR_TX_NO_ACK = -2, // No TX acknowledge was received
|
||||
KMP_RESULT_ERR_TX_UNSPEC = -3 // Other TX reason
|
||||
} kmp_result_e;
|
||||
|
||||
typedef enum {
|
||||
|
@ -115,8 +115,10 @@ void kmp_api_create_response(kmp_api_t *kmp, kmp_result_e result);
|
|||
* \param result ok or fail
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return TRUE authentication has been completed, FALSE authentication continues
|
||||
*
|
||||
*/
|
||||
typedef void kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
typedef bool kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* kmp_api_finished will be called when KMP has finished and is ready for delete
|
||||
|
|
|
@ -89,7 +89,7 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_
|
|||
static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot);
|
||||
|
||||
static int8_t auth_eap_tls_sec_prot_message_handle(sec_prot_t *prot);
|
||||
static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state);
|
||||
static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state, bool retry);
|
||||
|
||||
static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||
static int8_t auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot);
|
||||
|
@ -247,7 +247,7 @@ static int8_t auth_eap_tls_sec_prot_message_handle(sec_prot_t *prot)
|
|||
return eap_tls_sec_prot_lib_message_handle(data_ptr, length, new_seq_id, &data->tls_send, &data->tls_recv);
|
||||
}
|
||||
|
||||
static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state)
|
||||
static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state, bool retry)
|
||||
{
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
|
||||
|
@ -275,9 +275,9 @@ static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("EAP-TLS: send %s type %s id %i flags %x len %i, eui-64: %s", eap_msg_trace[eap_code - 1],
|
||||
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size,
|
||||
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
tr_info("EAP-TLS: %s %s type %s id %i flags %x len %i, eui-64: %s", retry ? "retry" : "send",
|
||||
eap_msg_trace[eap_code - 1], eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS",
|
||||
data->eap_id_seq, flags, eapol_pdu_size, trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
|
@ -305,13 +305,13 @@ static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot)
|
|||
tls_prot->create_resp(tls_prot, SEC_RESULT_OK);
|
||||
}
|
||||
|
||||
static void auth_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
static bool auth_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
(void) sec_keys;
|
||||
|
||||
sec_prot_t *prot = tls_prot->type_get(tls_prot, SEC_PROT_TYPE_EAP_TLS);
|
||||
if (!prot) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
|
@ -333,6 +333,8 @@ static void auth_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot,
|
|||
// On fatal error terminate right away
|
||||
prot->state_machine_call(prot);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int8_t auth_eap_tls_sec_prot_tls_send(sec_prot_t *tls_prot, void *pdu, uint16_t size)
|
||||
|
@ -418,7 +420,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
auth_eap_tls_sec_prot_seq_id_update(prot);
|
||||
|
||||
// Sends EAP request, Identity
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -432,7 +434,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
// On timeout
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-sends EAP request, Identity
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -442,7 +444,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
}
|
||||
|
||||
// Sends EAP request, TLS EAP start
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -456,12 +458,13 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
// On timeout
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
|
||||
if (sec_prot_state_get(&data->common) == EAP_TLS_STATE_RESPONSE_START) {
|
||||
// Re-sends EAP request, TLS EAP start
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START, true);
|
||||
} else {
|
||||
// Re-sends EAP request, TLS EAP
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -475,7 +478,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
}
|
||||
if (result == EAP_TLS_MSG_IDENTITY) {
|
||||
// If received EAP response, Identity: re-sends EAP request, TLS EAP start
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -524,7 +527,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
data->send_pending = false;
|
||||
|
||||
// Sends EAP request, TLS EAP, TLS exchange
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -534,10 +537,10 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
// Supplicant PMK is now valid
|
||||
sec_prot_keys_pmk_mismatch_reset(prot->sec_keys);
|
||||
// Sends EAP success
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_SUCCESS, 0, EAP_TLS_EXCHANGE_NONE);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_SUCCESS, 0, EAP_TLS_EXCHANGE_NONE, false);
|
||||
} else {
|
||||
// Sends EAP failure
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_FAILURE, 0, EAP_TLS_EXCHANGE_NONE);
|
||||
auth_eap_tls_sec_prot_message_send(prot, EAP_FAILURE, 0, EAP_TLS_EXCHANGE_NONE, false);
|
||||
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||
}
|
||||
|
||||
|
|
|
@ -295,13 +295,13 @@ static void supp_eap_tls_sec_prot_tls_create_confirm(sec_prot_t *tls_prot, sec_p
|
|||
}
|
||||
}
|
||||
|
||||
static void supp_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
static bool supp_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
(void) sec_keys;
|
||||
|
||||
sec_prot_t *prot = tls_prot->type_get(tls_prot, SEC_PROT_TYPE_EAP_TLS);
|
||||
if (!prot) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||
|
@ -324,6 +324,8 @@ static void supp_eap_tls_sec_prot_tls_finished_indication(sec_prot_t *tls_prot,
|
|||
// On fatal error and on success calls state machine to sent empty EAP-TLS message
|
||||
prot->state_machine_call(prot);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int8_t supp_eap_tls_sec_prot_tls_send(sec_prot_t *tls_prot, void *pdu, uint16_t size)
|
||||
|
|
|
@ -80,7 +80,8 @@ static int8_t auth_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
static fwh_sec_prot_msg_e auth_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys);
|
||||
static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot);
|
||||
|
||||
static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg);
|
||||
static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg, bool retry);
|
||||
static int8_t auth_fwh_sec_prot_auth_completed_send(sec_prot_t *prot);
|
||||
static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||
|
||||
static int8_t auth_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *sec_keys);
|
||||
|
@ -204,7 +205,7 @@ static fwh_sec_prot_msg_e auth_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return msg;
|
||||
}
|
||||
|
||||
static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg)
|
||||
static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg, bool retry)
|
||||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
|
||||
|
@ -301,7 +302,9 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("4WH: send %s, eui-64: %s", msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
tr_info("4WH: %s %s, eui-64: %s", retry ? "retry" : "send",
|
||||
msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3",
|
||||
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
|
@ -310,6 +313,18 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t auth_fwh_sec_prot_auth_completed_send(sec_prot_t *prot)
|
||||
{
|
||||
uint8_t *eapol_pdu_frame = ns_dyn_mem_temporary_alloc(prot->header_size);
|
||||
|
||||
// Send zero length message to relay which requests LLC to remove EAPOL temporary entry based on EUI-64
|
||||
if (prot->send(prot, eapol_pdu_frame, prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||
{
|
||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||
|
@ -347,7 +362,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
// Sends 4WH Message 1
|
||||
sec_prot_lib_nonce_generate(data->nonce);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -360,7 +375,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-sends 4WH Message 1
|
||||
sec_prot_lib_nonce_generate(data->nonce);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1, true);
|
||||
} else {
|
||||
if (data->recv_msg != FWH_MESSAGE_2) {
|
||||
return;
|
||||
|
@ -375,7 +390,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
}
|
||||
|
||||
// Sends 4WH Message 3
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -388,7 +403,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
case FWH_STATE_MESSAGE_4:
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-sends 4WH Message 3
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3);
|
||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3, true);
|
||||
} else {
|
||||
if (data->recv_msg != FWH_MESSAGE_4) {
|
||||
return;
|
||||
|
@ -416,7 +431,11 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
tr_info("4WH: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
if (prot->finished_ind(prot, sec_prot_result_get(&data->common), 0)) {
|
||||
// Authentication completed (all GTKs inserted)
|
||||
auth_fwh_sec_prot_auth_completed_send(prot);
|
||||
}
|
||||
|
||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
|
||||
break;
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ static int8_t auth_gkh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
|
|||
static gkh_sec_prot_msg_e auth_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys);
|
||||
static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot);
|
||||
|
||||
static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg);
|
||||
static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg, bool retry);
|
||||
static int8_t auth_gkh_sec_prot_auth_completed_send(sec_prot_t *prot);
|
||||
static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||
static int8_t auth_gkh_sec_prot_mic_validate(sec_prot_t *prot);
|
||||
|
||||
|
@ -180,7 +181,7 @@ static gkh_sec_prot_msg_e auth_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
|
|||
return msg;
|
||||
}
|
||||
|
||||
static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg)
|
||||
static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg, bool retry)
|
||||
{
|
||||
uint16_t kde_len = 0;
|
||||
|
||||
|
@ -249,7 +250,8 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
|||
return -1;
|
||||
}
|
||||
|
||||
tr_info("GKH: send Message 1, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
tr_info("GKH: %s Message 1, eui-64: %s", retry ? "retry" : "send",
|
||||
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
|
||||
return -1;
|
||||
|
@ -258,6 +260,18 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t auth_gkh_sec_prot_auth_completed_send(sec_prot_t *prot)
|
||||
{
|
||||
uint8_t *eapol_pdu_frame = ns_dyn_mem_temporary_alloc(prot->header_size);
|
||||
|
||||
// Send zero length message to relay which requests LLC to remove EAPOL temporary entry based on EUI-64
|
||||
if (prot->send(prot, eapol_pdu_frame, prot->header_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||
{
|
||||
gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot);
|
||||
|
@ -287,7 +301,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
prot->create_conf(prot, SEC_RESULT_OK);
|
||||
|
||||
// Sends GKH Message 1
|
||||
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1);
|
||||
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1, false);
|
||||
|
||||
// Start trickle timer to re-send if no response
|
||||
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||
|
@ -303,7 +317,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
|
||||
if (sec_prot_result_timeout_check(&data->common)) {
|
||||
// Re-sends GKH Message 1
|
||||
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1);
|
||||
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1, true);
|
||||
} else {
|
||||
if (auth_gkh_sec_prot_mic_validate(prot) < 0) {
|
||||
return;
|
||||
|
@ -319,7 +333,10 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
|||
tr_info("GKH finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
if (prot->finished_ind(prot, sec_prot_result_get(&data->common), 0)) {
|
||||
// Authentication completed (all GTKs inserted)
|
||||
auth_gkh_sec_prot_auth_completed_send(prot);
|
||||
}
|
||||
|
||||
sec_prot_state_set(prot, &data->common, GKH_STATE_FINISHED);
|
||||
break;
|
||||
|
|
|
@ -324,7 +324,7 @@ static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e
|
|||
sec_prot_result_set(&data->common, SEC_RESULT_ERR_TX_NO_ACK);
|
||||
} else if (tx_status != SEC_PROT_TX_OK) {
|
||||
// Indicates other failure
|
||||
sec_prot_result_set(&data->common, SEC_RESULT_ERR_UNSPEC);
|
||||
sec_prot_result_set(&data->common, SEC_RESULT_ERR_TX_UNSPEC);
|
||||
}
|
||||
prot->state_machine_call(prot);
|
||||
return 0;
|
||||
|
|
|
@ -31,7 +31,7 @@ typedef enum {
|
|||
SEC_RESULT_OK = 0,
|
||||
SEC_RESULT_ERR_NO_MEM = -1,
|
||||
SEC_RESULT_ERR_TX_NO_ACK = -2,
|
||||
SEC_RESULT_ERR_UNSPEC = -3,
|
||||
SEC_RESULT_ERR_TX_UNSPEC = -3,
|
||||
SEC_RESULT_TIMEOUT = -4,
|
||||
SEC_RESULT_ERROR = -5,
|
||||
SEC_RESULT_CONF_ERROR = -6,
|
||||
|
@ -106,8 +106,10 @@ typedef void sec_prot_create_indication(sec_prot_t *prot);
|
|||
* \param result result
|
||||
* \param sec_keys security keys
|
||||
*
|
||||
* \return TRUE authentication has been completed, FALSE authentication continues
|
||||
*
|
||||
*/
|
||||
typedef void sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||
typedef bool sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||
|
||||
/**
|
||||
* sec_prot_finished Security protocol has finished and is ready for delete
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
typedef struct sec_prot_cfg_s {
|
||||
trickle_params_t sec_prot_trickle_params;
|
||||
uint16_t sec_prot_retry_timeout;
|
||||
uint16_t sec_max_ongoing_authentication;
|
||||
uint16_t initial_key_retry_delay;
|
||||
trickle_params_t initial_key_trickle_params;
|
||||
uint8_t initial_key_retry_cnt;
|
||||
uint8_t max_ongoing_auth_constant;
|
||||
uint16_t max_ongoing_auth_size_scaler;
|
||||
} sec_prot_cfg_t;
|
||||
|
||||
/* Security timer configuration settings */
|
||||
|
@ -53,9 +54,14 @@ typedef struct sec_radius_cfg_s {
|
|||
bool radius_addr_set : 1; /**< Radius server address is set */
|
||||
} sec_radius_cfg_t;
|
||||
|
||||
typedef struct sec_timing_cfg_s {
|
||||
uint16_t temp_eapol_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 330 */
|
||||
} sec_timing_cfg_t;
|
||||
|
||||
typedef struct sec_cfg_s {
|
||||
sec_prot_cfg_t prot_cfg;
|
||||
sec_timer_cfg_t timer_cfg;
|
||||
sec_timing_cfg_t timing_cfg;
|
||||
sec_radius_cfg_t *radius_cfg;
|
||||
} sec_cfg_t;
|
||||
|
||||
|
|
|
@ -140,6 +140,15 @@ int ns_fhss_ws_set_hop_count(const fhss_api_t *fhss_api, const uint8_t hop_count
|
|||
return fhss_ws_set_hop_count(fhss_structure, hop_count);
|
||||
}
|
||||
|
||||
int ns_fhss_ws_set_tx_allowance_level(const fhss_api_t *fhss_api, const fhss_ws_tx_allow_level global_level, const fhss_ws_tx_allow_level ef_level)
|
||||
{
|
||||
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
|
||||
if (!fhss_structure || !fhss_structure->ws) {
|
||||
return -1;
|
||||
}
|
||||
return fhss_ws_set_tx_allowance_level(fhss_structure, global_level, ef_level);
|
||||
}
|
||||
|
||||
int ns_fhss_statistics_start(const fhss_api_t *fhss_api, fhss_statistics_t *fhss_statistics)
|
||||
{
|
||||
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
|
||||
|
|
|
@ -84,6 +84,8 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure)
|
|||
static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay);
|
||||
static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay);
|
||||
static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
|
||||
static bool fhss_allow_transmitting_on_rx_slot(fhss_structure_t *fhss_structure);
|
||||
static bool fhss_allow_unicast_on_broadcast_channel(fhss_structure_t *fhss_structure);
|
||||
static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_t channel_index, uint16_t number_of_channels);
|
||||
|
||||
// This function supports rounding up
|
||||
|
@ -167,6 +169,10 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati
|
|||
fhss_ws_set_hop_count(fhss_struct, 0xff);
|
||||
fhss_struct->rx_channel = fhss_configuration->unicast_fixed_channel;
|
||||
fhss_struct->ws->min_synch_interval = DEFAULT_MIN_SYNCH_INTERVAL;
|
||||
// By default, allow transmitting unicast data only on TX slots.
|
||||
fhss_struct->ws->tx_level = WS_TX_SLOT;
|
||||
// By default, allow always transmitting unicast data in expedited forwarding mode.
|
||||
fhss_struct->ws->ef_tx_level = WS_TX_ALWAYS;
|
||||
ns_list_init(&fhss_struct->fhss_failed_tx_list);
|
||||
return fhss_struct;
|
||||
}
|
||||
|
@ -302,12 +308,13 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
if (!fhss_structure) {
|
||||
return;
|
||||
}
|
||||
|
||||
platform_enter_critical();
|
||||
if (fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval == 0 || fhss_structure->ws->fhss_configuration.fhss_broadcast_interval == 0) {
|
||||
// stop broadcast schedule
|
||||
fhss_structure->ws->is_on_bc_channel = false;
|
||||
fhss_structure->ws->synchronization_time = 0;
|
||||
fhss_structure->ws->broadcast_timer_running = false;
|
||||
platform_exit_critical();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -340,6 +347,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
fhss_structure->ws->is_on_bc_channel = false;
|
||||
}
|
||||
delay_us %= MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval);
|
||||
delay_us %= MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
|
||||
}
|
||||
|
||||
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
|
||||
|
@ -347,19 +355,22 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
}
|
||||
|
||||
if (fhss_structure->ws->is_on_bc_channel == false) {
|
||||
fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
|
||||
fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - ((int64_t) delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
|
||||
fhss_structure->ws->is_on_bc_channel = true;
|
||||
next_channel = fhss_structure->ws->bc_channel = fhss_ws_calc_bc_channel(fhss_structure);
|
||||
|
||||
/* Start timer with random timeout to trigger broadcast TX queue poll event.
|
||||
* Min random is 1/50 of the channel dwell interval.
|
||||
* Max random is 3/4 of the channel dwell interval.
|
||||
* Event timer resolution is 50us.
|
||||
*/
|
||||
uint32_t bc_dwell_us = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
|
||||
uint16_t bc_min_random = (bc_dwell_us / 50) / 50;
|
||||
uint16_t bc_max_random = (bc_dwell_us - (bc_dwell_us / 4)) / 50;
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random));
|
||||
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
|
||||
} else {
|
||||
/* Start timer with random timeout to trigger broadcast TX queue poll event.
|
||||
* Min random is 1/50 of the channel dwell interval.
|
||||
* Max random is 3/4 of the channel dwell interval.
|
||||
* Event timer resolution is 50us.
|
||||
*/
|
||||
uint32_t bc_dwell_us = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
|
||||
uint16_t bc_min_random = (bc_dwell_us / 50) / 50;
|
||||
uint16_t bc_max_random = (bc_dwell_us - (bc_dwell_us / 4)) / 50;
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random));
|
||||
}
|
||||
} else {
|
||||
fhss_structure->ws->unicast_start_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
||||
uint32_t timeout = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
|
||||
|
@ -367,27 +378,31 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
fhss_structure->ws->is_on_bc_channel = false;
|
||||
// Should return to own (unicast) listening channel after broadcast channel
|
||||
next_channel = fhss_structure->rx_channel;
|
||||
/* Start timer with random timeout to trigger unicast TX queue poll event.
|
||||
* For hops 0,1,4,5,8,9,...
|
||||
* Min random is 1/100 of the TX slot length.
|
||||
* Max random is 1/5 of the TX slot length.
|
||||
*
|
||||
* For hops 2,3,6,7,10,11,...
|
||||
* Min random is 1/100 of the TX slot length plus 0.5*TX slot length.
|
||||
* Max random is 1/10 of the TX slot length plus 0.5*TX slot length.
|
||||
* Event timer resolution is 50us.
|
||||
*/
|
||||
// returns 1 if polling of TX queue is done on latter half of the TX slot
|
||||
uint8_t own_tx_trig_slot = calc_own_tx_trig_slot(fhss_structure->own_hop);
|
||||
uint32_t txrx_slot_length_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms);
|
||||
uint16_t uc_min_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 100) / 50);
|
||||
uint16_t uc_max_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 5) / 50);
|
||||
bool tx_allowed = fhss_ws_check_tx_allowed(fhss_structure);
|
||||
if (!tx_allowed) {
|
||||
uc_min_random += (txrx_slot_length_us) / 50;
|
||||
uc_max_random += (txrx_slot_length_us) / 50;
|
||||
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
|
||||
} else {
|
||||
/* Start timer with random timeout to trigger unicast TX queue poll event.
|
||||
* For hops 0,1,4,5,8,9,...
|
||||
* Min random is 1/100 of the TX slot length.
|
||||
* Max random is 1/5 of the TX slot length.
|
||||
*
|
||||
* For hops 2,3,6,7,10,11,...
|
||||
* Min random is 1/100 of the TX slot length plus 0.5*TX slot length.
|
||||
* Max random is 1/10 of the TX slot length plus 0.5*TX slot length.
|
||||
* Event timer resolution is 50us.
|
||||
*/
|
||||
// returns 1 if polling of TX queue is done on latter half of the TX slot
|
||||
uint8_t own_tx_trig_slot = calc_own_tx_trig_slot(fhss_structure->own_hop);
|
||||
uint32_t txrx_slot_length_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms);
|
||||
uint16_t uc_min_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 100) / 50);
|
||||
uint16_t uc_max_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 5) / 50);
|
||||
bool tx_allowed = fhss_ws_check_tx_allowed(fhss_structure);
|
||||
if (!tx_allowed) {
|
||||
uc_min_random += (txrx_slot_length_us) / 50;
|
||||
uc_max_random += (txrx_slot_length_us) / 50;
|
||||
}
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(uc_min_random, uc_max_random));
|
||||
}
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(uc_min_random, uc_max_random));
|
||||
|
||||
#ifdef FHSS_CHANNEL_DEBUG
|
||||
tr_info("%"PRIu32" UC %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), fhss_structure->rx_channel);
|
||||
|
@ -409,6 +424,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
tr_info("%u BC_done", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api));
|
||||
}
|
||||
#endif
|
||||
platform_exit_critical();
|
||||
}
|
||||
|
||||
static int own_floor(float value)
|
||||
|
@ -435,19 +451,35 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
|
|||
return;
|
||||
}
|
||||
|
||||
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
|
||||
} else {
|
||||
// On unicast, start timer to trigger polling event on next TX slot
|
||||
uint32_t delay_between_tx_slots_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms) * 2;
|
||||
// Timer could drift to RX slot when broadcast interval is high. Return timer to TX slot.
|
||||
if (fhss_ws_check_tx_allowed(fhss_structure) == false) {
|
||||
delay_between_tx_slots_us -= MS_TO_US(fhss_structure->ws->txrx_slot_length_ms - (calc_own_tx_trig_slot(fhss_structure->own_hop) * (fhss_structure->ws->txrx_slot_length_ms / 2)));
|
||||
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
|
||||
if ((fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - fhss_structure->ws->expedited_forwarding_enabled_us) > S_TO_US(EXPEDITED_FORWARDING_PERIOD)) {
|
||||
fhss_structure->ws->expedited_forwarding_enabled_us = 0;
|
||||
}
|
||||
if (delay_between_tx_slots_us < get_remaining_slots_us(fhss_structure, fhss_broadcast_handler, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval))) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, delay_between_tx_slots_us / 50);
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
|
||||
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
|
||||
} else {
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
|
||||
}
|
||||
} else if ((fhss_structure->ws->unicast_timer_running == false) && (fhss_structure->ws->broadcast_timer_running == false)) {
|
||||
// No one would poll TX queue if schedule timers were not started. Start poll timer with default interval.
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, DEFAULT_POLL_PERIOD);
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
|
||||
} else {
|
||||
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
|
||||
} else {
|
||||
// On unicast, start timer to trigger polling event on next TX slot
|
||||
uint32_t delay_between_tx_slots_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms) * 2;
|
||||
// Timer could drift to RX slot when broadcast interval is high. Return timer to TX slot.
|
||||
if (fhss_ws_check_tx_allowed(fhss_structure) == false) {
|
||||
delay_between_tx_slots_us -= MS_TO_US(fhss_structure->ws->txrx_slot_length_ms - (calc_own_tx_trig_slot(fhss_structure->own_hop) * (fhss_structure->ws->txrx_slot_length_ms / 2)));
|
||||
}
|
||||
if (delay_between_tx_slots_us < get_remaining_slots_us(fhss_structure, fhss_broadcast_handler, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval))) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, delay_between_tx_slots_us / 50);
|
||||
}
|
||||
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
|
||||
}
|
||||
}
|
||||
if (queue_size) {
|
||||
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
|
||||
|
@ -526,6 +558,16 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
|
|||
if (!fhss_structure) {
|
||||
return -1;
|
||||
}
|
||||
if (fhss_state == FHSS_EXPEDITED_FORWARDING) {
|
||||
if (!fhss_structure->ws->expedited_forwarding_enabled_us) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
|
||||
}
|
||||
fhss_structure->ws->expedited_forwarding_enabled_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
||||
if (!fhss_structure->ws->expedited_forwarding_enabled_us) {
|
||||
fhss_structure->ws->expedited_forwarding_enabled_us++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (fhss_state == FHSS_SYNCHRONIZED) {
|
||||
uint32_t fhss_broadcast_interval = fhss_structure->ws->fhss_configuration.fhss_broadcast_interval;
|
||||
uint8_t fhss_bc_dwell_interval = fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval;
|
||||
|
@ -617,12 +659,15 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a
|
|||
if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == false)) {
|
||||
return -3;
|
||||
}
|
||||
// Do not allow unicast destination on broadcast channel
|
||||
// Do not allow unicast destination on broadcast channel unless it is specifically enabled
|
||||
if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) {
|
||||
return -1;
|
||||
if (fhss_allow_unicast_on_broadcast_channel(fhss_structure)) {
|
||||
return 0;
|
||||
}
|
||||
return -3;
|
||||
}
|
||||
// Check TX/RX slot
|
||||
if (!fhss_ws_check_tx_allowed(fhss_structure)) {
|
||||
if (!fhss_allow_transmitting_on_rx_slot(fhss_structure) && !fhss_ws_check_tx_allowed(fhss_structure)) {
|
||||
return -1;
|
||||
}
|
||||
if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED) {
|
||||
|
@ -737,6 +782,30 @@ static bool fhss_ws_check_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool fhss_allow_transmitting_on_rx_slot(fhss_structure_t *fhss_structure)
|
||||
{
|
||||
if (fhss_structure->ws->tx_level >= WS_TX_AND_RX_SLOT) {
|
||||
return true;
|
||||
}
|
||||
// This is allowed only for devices in expedited forwarding mode
|
||||
if (fhss_structure->ws->expedited_forwarding_enabled_us && (fhss_structure->ws->ef_tx_level >= WS_TX_AND_RX_SLOT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fhss_allow_unicast_on_broadcast_channel(fhss_structure_t *fhss_structure)
|
||||
{
|
||||
if (fhss_structure->ws->tx_level >= WS_TX_ALWAYS) {
|
||||
return true;
|
||||
}
|
||||
// This is allowed only for devices in expedited forwarding mode
|
||||
if (fhss_structure->ws->expedited_forwarding_enabled_us && (fhss_structure->ws->ef_tx_level >= WS_TX_ALWAYS)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fhss_ws_check_tx_conditions_callback(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length)
|
||||
{
|
||||
(void) frame_type;
|
||||
|
@ -748,8 +817,8 @@ static bool fhss_ws_check_tx_conditions_callback(const fhss_api_t *api, bool is_
|
|||
if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == false)) {
|
||||
return false;
|
||||
}
|
||||
// Do not allow unicast destination on broadcast channel
|
||||
if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) {
|
||||
// Do not allow unicast destination on broadcast channel unless it is specifically enabled
|
||||
if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true) && !fhss_allow_unicast_on_broadcast_channel(fhss_structure)) {
|
||||
return false;
|
||||
}
|
||||
// This condition will check that message is not sent on bad channel
|
||||
|
@ -761,7 +830,7 @@ static bool fhss_ws_check_tx_conditions_callback(const fhss_api_t *api, bool is_
|
|||
return false;
|
||||
}
|
||||
// Check TX/RX slot for unicast frames
|
||||
if (!is_broadcast_addr && !fhss_ws_check_tx_allowed(fhss_structure)) {
|
||||
if (!is_broadcast_addr && !fhss_allow_transmitting_on_rx_slot(fhss_structure) && !fhss_ws_check_tx_allowed(fhss_structure)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -923,6 +992,10 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t
|
|||
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||
return return_value;
|
||||
}
|
||||
// No need to wait until TX slot when sending on RX slot is allowed
|
||||
if (fhss_allow_transmitting_on_rx_slot(fhss_structure) == true) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
uint32_t txrx_slot_length_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms);
|
||||
uint32_t unicast_start_us = fhss_structure->ws->unicast_start_time_us;
|
||||
|
@ -955,6 +1028,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
if (!fhss_structure) {
|
||||
return;
|
||||
}
|
||||
platform_enter_critical();
|
||||
int32_t delay_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - fhss_structure->ws->next_uc_timeout;
|
||||
if (!fhss_structure->ws->uc_slot && !fhss_structure->ws->next_uc_timeout) {
|
||||
delay_us = 0;
|
||||
|
@ -974,6 +1048,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
if (!timeout) {
|
||||
fhss_stop_timer(fhss_structure, fhss_unicast_handler);
|
||||
fhss_structure->ws->unicast_timer_running = false;
|
||||
platform_exit_critical();
|
||||
return;
|
||||
}
|
||||
fhss_ws_start_timer(fhss_structure, timeout - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_unicast_handler);
|
||||
|
@ -985,6 +1060,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
|
||||
}
|
||||
}
|
||||
platform_exit_critical();
|
||||
}
|
||||
|
||||
int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure)
|
||||
|
@ -1018,6 +1094,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
|
|||
return 0;
|
||||
}
|
||||
platform_enter_critical();
|
||||
|
||||
uint16_t own_bc_slot = fhss_structure->ws->bc_slot;
|
||||
uint32_t prev_synchronization_time = fhss_structure->ws->synchronization_time;
|
||||
fhss_structure->ws->synchronization_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
||||
|
@ -1126,6 +1203,11 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
|
|||
channel_count_uc = channel_count_bc;
|
||||
}
|
||||
|
||||
// No one would poll TX queue if schedule timers were not started. Start poll timer with default interval.
|
||||
if ((fhss_structure->ws->unicast_timer_running == false) && (fhss_structure->ws->broadcast_timer_running == false)) {
|
||||
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, DEFAULT_POLL_PERIOD);
|
||||
}
|
||||
|
||||
fhss_structure->number_of_channels = fhss_configuration->channel_mask_size;
|
||||
fhss_structure->number_of_bc_channels = channel_count_bc;
|
||||
fhss_structure->number_of_uc_channels = channel_count_uc;
|
||||
|
@ -1156,4 +1238,11 @@ int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_co
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fhss_ws_set_tx_allowance_level(fhss_structure_t *fhss_structure, const fhss_ws_tx_allow_level global_level, const fhss_ws_tx_allow_level ef_level)
|
||||
{
|
||||
fhss_structure->ws->tx_level = global_level;
|
||||
fhss_structure->ws->ef_tx_level = ef_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // HAVE_WS
|
||||
|
|
|
@ -18,17 +18,23 @@
|
|||
#define FHSS_WS_H_
|
||||
|
||||
// TX slot length is optimised to this packet length
|
||||
#define OPTIMAL_PACKET_LENGTH 500
|
||||
#define OPTIMAL_PACKET_LENGTH 500
|
||||
// Max TX/RX slot length in milliseconds. Is used when datarate is not given by PHY or calculated slot length exceeds maximum allowed.
|
||||
#define WS_TXRX_SLOT_LEN_MS_MAX 100
|
||||
#define WS_TXRX_SLOT_LEN_MS_MAX 100
|
||||
// Min TX/RX slot length in milliseconds. Is used when calculated slot length is under minimum allowed.
|
||||
#define WS_TXRX_SLOT_LEN_MS_MIN 10
|
||||
#define WS_TXRX_SLOT_LEN_MS_MIN 13
|
||||
// Default minimum broadcast synchronization interval in seconds
|
||||
#define DEFAULT_MIN_SYNCH_INTERVAL 60
|
||||
#define DEFAULT_MIN_SYNCH_INTERVAL 60
|
||||
// Drift compensation allowed if at least SYNCH_COMPENSATION_MIN_INTERVAL (seconds) since last synchronization
|
||||
#define SYNCH_COMPENSATION_MIN_INTERVAL 60
|
||||
#define SYNCH_COMPENSATION_MIN_INTERVAL 60
|
||||
// MAX compensation per received synchronization info in ns
|
||||
#define MAX_DRIFT_COMPENSATION_STEP 10
|
||||
#define MAX_DRIFT_COMPENSATION_STEP 10
|
||||
// Length of expedited forwarding period in seconds
|
||||
#define EXPEDITED_FORWARDING_PERIOD 5
|
||||
// TX poll interval for expedited forwarding in 50us slots
|
||||
#define EXPEDITED_FORWARDING_POLL_PERIOD (5000 / 50)
|
||||
// TX poll interval used when channel schedules are not yet started (50us slots)
|
||||
#define DEFAULT_POLL_PERIOD (10000 / 50)
|
||||
typedef struct fhss_ws fhss_ws_t;
|
||||
|
||||
struct fhss_ws {
|
||||
|
@ -44,9 +50,12 @@ struct fhss_ws {
|
|||
uint8_t *tr51_output_table;
|
||||
uint32_t next_uc_timeout;
|
||||
uint32_t next_bc_timeout;
|
||||
uint32_t expedited_forwarding_enabled_us;
|
||||
bool unicast_timer_running;
|
||||
bool broadcast_timer_running;
|
||||
bool is_on_bc_channel;
|
||||
fhss_ws_tx_allow_level tx_level;
|
||||
fhss_ws_tx_allow_level ef_tx_level;
|
||||
struct fhss_ws_configuration fhss_configuration;
|
||||
const struct broadcast_timing_info *parent_bc_info;
|
||||
fhss_get_neighbor_info *get_neighbor_info;
|
||||
|
@ -58,6 +67,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
|
|||
int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]);
|
||||
int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration);
|
||||
int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count);
|
||||
int fhss_ws_set_tx_allowance_level(fhss_structure_t *fhss_structure, const fhss_ws_tx_allow_level global_level, const fhss_ws_tx_allow_level ef_level);
|
||||
void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure);
|
||||
|
||||
#endif /*FHSS_WS_H_*/
|
||||
|
|
|
@ -80,5 +80,14 @@ int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_co
|
|||
return -1;
|
||||
}
|
||||
|
||||
int fhss_ws_set_tx_allowance_level(fhss_structure_t *fhss_structure, const fhss_ws_tx_allow_level global_level, const fhss_ws_tx_allow_level ef_level)
|
||||
{
|
||||
(void) fhss_structure;
|
||||
(void) global_level;
|
||||
(void) ef_level;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // HAVE_WS
|
||||
|
||||
|
|
|
@ -142,9 +142,9 @@ bool nd_proxy_upstream_route_onlink(int8_t downstream_id, uint8_t *address);
|
|||
NS_DUMMY_DEFINITIONS_OK
|
||||
|
||||
#define nd_proxy_downstream_interface_register(interface_id, nd_proxy_req, bridge_state_update) -1
|
||||
#define nd_proxy_downstream_interface_unregister(interface_id) -1
|
||||
#define nd_proxy_upstream_interface_register(interface_id, route_validation_req) -1
|
||||
#define nd_proxy_upstream_interface_unregister(interface_id) -1
|
||||
#define nd_proxy_downstream_interface_unregister(interface_id) (-1)
|
||||
#define nd_proxy_upstream_interface_register(interface_id, route_validation_req) (-1)
|
||||
#define nd_proxy_upstream_interface_unregister(interface_id) (-1)
|
||||
#define nd_proxy_enabled_for_downstream(interface_id) false
|
||||
#define nd_proxy_enabled_for_upstream(interface_id) false
|
||||
#define nd_proxy_target_address_validation(upstream_id, address) false
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
|
||||
int ns_conf_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
|
||||
{
|
||||
return ns_monitor_heap_gc_threshold_set(percentage_high, percentage_critical);
|
||||
return ns_monitor_heap_gc_threshold_set(0, 0, percentage_high, 0, 0, percentage_critical);
|
||||
}
|
||||
|
||||
int ns_conf_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage)
|
||||
{
|
||||
return ns_monitor_packet_ingress_rate_limit_by_memory(free_heap_percentage);
|
||||
return ns_monitor_packet_ingress_rate_limit_by_memory(0, 0, free_heap_percentage);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ static NS_LIST_DEFINE(ipv6_routing_table, ipv6_route_t, link);
|
|||
static ipv6_destination_t *ipv6_destination_lookup(const uint8_t *address, int8_t interface_id);
|
||||
static void ipv6_destination_cache_forget_router(ipv6_neighbour_cache_t *cache, const uint8_t neighbour_addr[16]);
|
||||
static void ipv6_destination_cache_forget_neighbour(const ipv6_neighbour_t *neighbour);
|
||||
static void ipv6_destination_release(ipv6_destination_t *dest);
|
||||
static bool ipv6_destination_release(ipv6_destination_t *dest);
|
||||
static void ipv6_route_table_remove_router(int8_t interface_id, const uint8_t *addr, ipv6_route_src_t source);
|
||||
static uint16_t total_metric(const ipv6_route_t *route);
|
||||
static uint8_t ipv6_route_table_count_source(int8_t interface_id, ipv6_route_src_t source);
|
||||
|
@ -481,6 +481,16 @@ bool ipv6_neighbour_has_registered_by_eui64(ipv6_neighbour_cache_t *cache, const
|
|||
return false;
|
||||
}
|
||||
|
||||
ipv6_neighbour_t *ipv6_neighbour_get_registered_by_eui64(ipv6_neighbour_cache_t *cache, const uint8_t *eui64)
|
||||
{
|
||||
ns_list_foreach_safe(ipv6_neighbour_t, cur, &cache->list) {
|
||||
if (cur->type != IP_NEIGHBOUR_GARBAGE_COLLECTIBLE && memcmp(ipv6_neighbour_eui64(cache, cur), eui64, 8) == 0) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ipv6_neighbour_set_state(ipv6_neighbour_cache_t *cache, ipv6_neighbour_t *entry, ip_neighbour_cache_state_t state)
|
||||
{
|
||||
if (!ipv6_neighbour_state_is_probably_reachable(entry->state) &&
|
||||
|
@ -863,7 +873,7 @@ void ipv6_destination_cache_print(route_print_fn_t *print_fn)
|
|||
print_fn("Destination Cache:");
|
||||
ns_list_foreach(ipv6_destination_t, entry, &ipv6_destination_cache) {
|
||||
ROUTE_PRINT_ADDR_STR_BUFFER_INIT(addr_str);
|
||||
print_fn(" %s (life %u)", ROUTE_PRINT_ADDR_STR_FORMAT(addr_str, entry->destination), entry->lifetime);
|
||||
print_fn(" %s (%d id) (life %u)", ROUTE_PRINT_ADDR_STR_FORMAT(addr_str, entry->destination), entry->interface_id, entry->lifetime);
|
||||
#ifdef HAVE_IPV6_ND
|
||||
if (entry->redirected) {
|
||||
print_fn(" Redirect %s%%%u", ROUTE_PRINT_ADDR_STR_FORMAT(addr_str, entry->redirect_addr), entry->interface_id);
|
||||
|
@ -939,7 +949,6 @@ ipv6_destination_t *ipv6_destination_lookup_or_create(const uint8_t *address, in
|
|||
if (!entry) {
|
||||
if (count > destination_cache_config.max_entries) {
|
||||
entry = ns_list_get_last(&ipv6_destination_cache);
|
||||
ns_list_remove(&ipv6_destination_cache, entry);
|
||||
ipv6_destination_release(entry);
|
||||
}
|
||||
|
||||
|
@ -1082,18 +1091,31 @@ void ipv6_destination_cache_forced_gc(bool full_gc)
|
|||
**/
|
||||
ns_list_foreach_reverse_safe(ipv6_destination_t, entry, &ipv6_destination_cache) {
|
||||
if (entry->lifetime == 0 || gc_count > destination_cache_config.long_term_entries || full_gc) {
|
||||
ns_list_remove(&ipv6_destination_cache, entry);
|
||||
ipv6_destination_release(entry);
|
||||
gc_count--;
|
||||
if (ipv6_destination_release(entry)) {
|
||||
gc_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ipv6_destination_release(ipv6_destination_t *dest)
|
||||
void ipv6_destination_cache_clean(int8_t interface_id)
|
||||
{
|
||||
ns_list_foreach_reverse_safe(ipv6_destination_t, entry, &ipv6_destination_cache) {
|
||||
if (entry->interface_id == interface_id) {
|
||||
ipv6_destination_release(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool ipv6_destination_release(ipv6_destination_t *dest)
|
||||
{
|
||||
if (--dest->refcount == 0) {
|
||||
ns_list_remove(&ipv6_destination_cache, dest);
|
||||
tr_debug("Destination cache remove: %s", trace_ipv6(dest->destination));
|
||||
ns_dyn_mem_free(dest);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ipv6_destination_cache_gc_periodic(void)
|
||||
|
@ -1137,9 +1159,11 @@ static void ipv6_destination_cache_gc_periodic(void)
|
|||
*/
|
||||
ns_list_foreach_reverse_safe(ipv6_destination_t, entry, &ipv6_destination_cache) {
|
||||
if (entry->lifetime == 0 || gc_count > destination_cache_config.short_term_entries) {
|
||||
ns_list_remove(&ipv6_destination_cache, entry);
|
||||
ipv6_destination_release(entry);
|
||||
if (--gc_count <= destination_cache_config.long_term_entries) {
|
||||
if (ipv6_destination_release(entry)) {
|
||||
gc_count--;
|
||||
}
|
||||
|
||||
if (gc_count <= destination_cache_config.long_term_entries) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1195,17 +1219,6 @@ static const bool ipv6_route_probing[ROUTE_MAX] = {
|
|||
[ROUTE_RPL_INSTANCE] = true,
|
||||
};
|
||||
|
||||
/* Which route types get minimum link MTU by default */
|
||||
/* Makes life easier for tunnel-based systems like RPL */
|
||||
static const bool ipv6_route_min_mtu[ROUTE_MAX] = {
|
||||
[ROUTE_RPL_DAO] = true,
|
||||
[ROUTE_RPL_DAO_SR] = true,
|
||||
[ROUTE_RPL_DIO] = true,
|
||||
[ROUTE_RPL_ROOT] = true,
|
||||
[ROUTE_RPL_INSTANCE] = true,
|
||||
[ROUTE_MPL] = true,
|
||||
};
|
||||
|
||||
// Remember when a route source has deleted an entry - allows buffers still in
|
||||
// event queue to have their route info invalidated.
|
||||
static bool ipv6_route_source_invalidated[ROUTE_MAX];
|
||||
|
@ -1647,7 +1660,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i
|
|||
route->info.info = info;
|
||||
route->info.source_id = source_id;
|
||||
route->info.interface_id = interface_id;
|
||||
route->info.pmtu = ipv6_route_min_mtu[source] ? IPV6_MIN_LINK_MTU : 0xFFFF;
|
||||
route->info.pmtu = 0xFFFF;
|
||||
if (next_hop) {
|
||||
route->on_link = false;
|
||||
memcpy(route->info.next_hop_addr, next_hop, 16);
|
||||
|
|
|
@ -162,6 +162,7 @@ extern bool ipv6_neighbour_ll_addr_match(const ipv6_neighbour_t *entry, addrtype
|
|||
extern void ipv6_neighbour_invalidate_ll_addr(ipv6_neighbour_cache_t *cache, addrtype_t ll_type, const uint8_t *ll_address);
|
||||
extern void ipv6_neighbour_delete_registered_by_eui64(ipv6_neighbour_cache_t *cache, const uint8_t *eui64);
|
||||
extern bool ipv6_neighbour_has_registered_by_eui64(ipv6_neighbour_cache_t *cache, const uint8_t *eui64);
|
||||
extern ipv6_neighbour_t *ipv6_neighbour_get_registered_by_eui64(ipv6_neighbour_cache_t *cache, const uint8_t *eui64);
|
||||
extern void ipv6_neighbour_entry_update_unsolicited(ipv6_neighbour_cache_t *cache, ipv6_neighbour_t *entry, addrtype_t type, const uint8_t *ll_address/*, bool tentative*/);
|
||||
extern ipv6_neighbour_t *ipv6_neighbour_update_unsolicited(ipv6_neighbour_cache_t *cache, const uint8_t *ip_address, addrtype_t ll_type, const uint8_t *ll_address);
|
||||
extern void ipv6_neighbour_reachability_confirmation(const uint8_t ip_address[__static 16], int8_t interface_id);
|
||||
|
@ -223,6 +224,7 @@ void ipv6_destination_cache_timer(uint8_t ticks);
|
|||
void ipv6_destination_redirect(const uint8_t *dest_addr, const uint8_t *sender_addr, const uint8_t *redirect_addr, int8_t interface_id, addrtype_t ll_type, const uint8_t *ll_address);
|
||||
#endif
|
||||
void ipv6_destination_cache_forced_gc(bool full_gc);
|
||||
void ipv6_destination_cache_clean(int8_t interface_id);
|
||||
|
||||
/* Combined Routing Table (RFC 4191) and Prefix List (RFC 4861) */
|
||||
/* On-link prefixes have the on_link flag set and next_hop is unset */
|
||||
|
|
|
@ -60,6 +60,7 @@ typedef struct {
|
|||
int8_t interface_id;
|
||||
uint8_t server_address[16];
|
||||
bool relay_activated;
|
||||
bool add_interface_id_option;
|
||||
ns_list_link_t link;
|
||||
} relay_instance_t;
|
||||
typedef NS_LIST_HEAD(relay_instance_t, link) relay_instance_list_t;
|
||||
|
@ -83,6 +84,8 @@ typedef struct {
|
|||
uint8_t *msg_ptr;
|
||||
uint16_t msg_len;
|
||||
uint8_t *relay_start;
|
||||
uint8_t *opt_interface_id;
|
||||
uint16_t opt_interface_id_length;
|
||||
ns_list_link_t link;
|
||||
} msg_tr_t;
|
||||
typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t;
|
||||
|
@ -335,6 +338,8 @@ void recv_dhcp_server_msg(void *cb_res)
|
|||
}
|
||||
//Update Source and data
|
||||
msg_tr_ptr->relay_start = msg_ptr;
|
||||
msg_tr_ptr->opt_interface_id = relay_msg.relay_interface_id.msg_ptr;
|
||||
msg_tr_ptr->opt_interface_id_length = relay_msg.relay_interface_id.len;
|
||||
memcpy(msg_tr_ptr->addr.address, relay_msg.peer_address, 16);
|
||||
msg_ptr = relay_msg.relay_options.msg_ptr;
|
||||
msg_len = relay_msg.relay_options.len;
|
||||
|
@ -408,35 +413,37 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
}
|
||||
ns_address_t src_address;
|
||||
|
||||
uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4];
|
||||
ns_iovec_t msg_iov[2];
|
||||
msg_iov[0].iov_base = relay_frame;
|
||||
msg_iov[0].iov_len = 34;
|
||||
msg_iov[1].iov_base = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
|
||||
msg_iov[1].iov_len = sckt_data->d_len;
|
||||
if (msg_iov[1].iov_base == NULL) {
|
||||
//Relay vector added space for relay frame + Interface ID
|
||||
uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4 + 5];
|
||||
|
||||
|
||||
uint8_t *socket_data = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
|
||||
|
||||
if (socket_data == NULL) {
|
||||
// read actual message
|
||||
tr_error("Out of resources");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
ns_msghdr_t msghdr;
|
||||
ns_iovec_t msg_data;
|
||||
msg_data.iov_base = socket_data;
|
||||
msg_data.iov_len = sckt_data->d_len;
|
||||
//Set messages name buffer
|
||||
msghdr.msg_name = &src_address;
|
||||
msghdr.msg_namelen = sizeof(src_address);
|
||||
msghdr.msg_iov = &msg_iov[1];
|
||||
msghdr.msg_iov = &msg_data;
|
||||
msghdr.msg_iovlen = 1;
|
||||
msghdr.msg_control = NULL;
|
||||
msghdr.msg_controllen = 0;
|
||||
|
||||
msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
|
||||
|
||||
|
||||
tr_debug("dhcp Relay recv msg");
|
||||
|
||||
//Parse type
|
||||
uint8_t *ptr = msg_iov[1].iov_base;
|
||||
uint8_t msg_type = *ptr;
|
||||
uint8_t msg_type = *socket_data;
|
||||
|
||||
int16_t tc = 0;
|
||||
if (msg_type == DHCPV6_RELAY_FORWARD) {
|
||||
|
@ -446,7 +453,7 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
} else if (msg_type == DHCPV6_RELAY_REPLY) {
|
||||
//Parse and validate Relay
|
||||
dhcpv6_relay_msg_t relay_msg;
|
||||
if (!libdhcpv6_relay_msg_read(ptr, msg_len, &relay_msg)) {
|
||||
if (!libdhcpv6_relay_msg_read(socket_data, msg_len, &relay_msg)) {
|
||||
tr_error("Not valid relay");
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -458,14 +465,14 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
memcpy(src_address.address, relay_msg.peer_address, 16);
|
||||
src_address.type = ADDRESS_IPV6;
|
||||
src_address.identifier = DHCPV6_CLIENT_PORT;
|
||||
msghdr.msg_iov = &msg_iov[0];
|
||||
msghdr.msg_iov = &msg_data;
|
||||
msghdr.msg_iovlen = 1;
|
||||
msg_iov[0].iov_base = relay_msg.relay_options.msg_ptr;
|
||||
msg_iov[0].iov_len = relay_msg.relay_options.len;
|
||||
msg_data.iov_base = relay_msg.relay_options.msg_ptr;
|
||||
msg_data.iov_len = relay_msg.relay_options.len;
|
||||
tr_debug("Forward Original relay msg to client");
|
||||
|
||||
} else {
|
||||
if (0 != libdhcpv6_message_malformed_check(ptr, msg_len)) {
|
||||
if (0 != libdhcpv6_message_malformed_check(socket_data, msg_len)) {
|
||||
tr_error("Malformed packet");
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -476,10 +483,24 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
tr_error("No GP address");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ns_iovec_t msg_iov[2];
|
||||
uint8_t *ptr = relay_frame;
|
||||
//Build
|
||||
libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
|
||||
libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len);
|
||||
//ADD relay frame vector front of original data
|
||||
msghdr.msg_iov = &msg_iov[0];
|
||||
msg_iov[0].iov_base = relay_frame;
|
||||
msghdr.msg_iovlen = 2;
|
||||
//SET Original Data
|
||||
msg_iov[1].iov_base = socket_data;
|
||||
msg_iov[1].iov_len = msg_len;
|
||||
|
||||
ptr = libdhcpv6_dhcp_relay_msg_write(ptr, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
|
||||
if (relay_srv->add_interface_id_option) {
|
||||
ptr = libdhcpv6_option_interface_id_write(ptr, sckt_data->interface_id);
|
||||
}
|
||||
ptr = libdhcpv6_dhcp_option_header_write(ptr, DHCPV6_OPTION_RELAY, msg_len);
|
||||
//Update length of relay vector
|
||||
msg_iov[0].iov_len = ptr - relay_frame;
|
||||
|
||||
//Update Neighbour table if necessary
|
||||
relay_notify_t *neigh_notify = dhcp_service_notify_find(sckt_data->interface_id);
|
||||
|
@ -491,12 +512,6 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
memcpy(src_address.address, relay_srv->server_address, 16);
|
||||
src_address.type = ADDRESS_IPV6;
|
||||
src_address.identifier = DHCPV6_SERVER_PORT;
|
||||
//ADD relay frame vector front of original data
|
||||
msghdr.msg_iov = &msg_iov[0];
|
||||
msghdr.msg_iovlen = 2;
|
||||
msg_iov[0].iov_base = relay_frame;
|
||||
msg_iov[0].iov_len = 38;
|
||||
msg_iov[1].iov_len = msg_len;
|
||||
tr_debug("Forward Client msg to server");
|
||||
tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
|
||||
|
@ -504,7 +519,7 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
socket_setsockopt(sckt_data->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
|
||||
cleanup:
|
||||
ns_dyn_mem_free(msg_iov[1].iov_base);
|
||||
ns_dyn_mem_free(socket_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -635,6 +650,7 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
|
|||
relay_srv->instance_id = id;
|
||||
relay_srv->interface_id = interface_id;
|
||||
relay_srv->relay_activated = false;
|
||||
relay_srv->add_interface_id_option = false;
|
||||
|
||||
}
|
||||
|
||||
|
@ -655,6 +671,14 @@ void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_addre
|
|||
}
|
||||
}
|
||||
|
||||
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable)
|
||||
{
|
||||
relay_instance_t *relay_srv = dhcp_service_relay_find(instance);
|
||||
if (relay_srv) {
|
||||
relay_srv->add_interface_id_option = enable;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *dhcp_service_relay_global_addres_get(uint16_t instance)
|
||||
{
|
||||
relay_instance_t *relay_srv = dhcp_service_relay_find(instance);
|
||||
|
@ -851,30 +875,42 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
|
|||
//Build Relay Reply only server do this
|
||||
int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
ns_iovec_t data_vector[2];
|
||||
ns_iovec_t data_vector[4];
|
||||
uint8_t relay_header[4];
|
||||
libdhcpv6_dhcp_option_header_write(relay_header, DHCPV6_OPTION_RELAY, msg_tr_ptr->msg_len);
|
||||
ns_msghdr_t msghdr;
|
||||
msghdr.msg_iovlen = 0;
|
||||
memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16);
|
||||
msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT;
|
||||
//SET IOV vectors
|
||||
//Relay Reply
|
||||
data_vector[0].iov_base = (void *) msg_tr_ptr->relay_start;
|
||||
data_vector[0].iov_len = DHCPV6_RELAY_LENGTH + 4;
|
||||
data_vector[msghdr.msg_iovlen].iov_base = (void *) msg_tr_ptr->relay_start;
|
||||
data_vector[msghdr.msg_iovlen].iov_len = DHCPV6_RELAY_LENGTH;
|
||||
msghdr.msg_iovlen++;
|
||||
if (msg_tr_ptr->opt_interface_id) {
|
||||
data_vector[msghdr.msg_iovlen].iov_base = (void *)(msg_tr_ptr->opt_interface_id - 4);
|
||||
data_vector[msghdr.msg_iovlen].iov_len = msg_tr_ptr->opt_interface_id_length + 4;
|
||||
msghdr.msg_iovlen++;
|
||||
}
|
||||
//Relay reply header
|
||||
data_vector[msghdr.msg_iovlen].iov_base = (void *) relay_header;
|
||||
data_vector[msghdr.msg_iovlen].iov_len = 4;
|
||||
msghdr.msg_iovlen++;
|
||||
//DHCPV normal message vector
|
||||
data_vector[1].iov_base = (void *) msg_tr_ptr->msg_ptr;
|
||||
data_vector[1].iov_len = msg_tr_ptr->msg_len;
|
||||
data_vector[msghdr.msg_iovlen].iov_base = (void *) msg_tr_ptr->msg_ptr;
|
||||
data_vector[msghdr.msg_iovlen].iov_len = msg_tr_ptr->msg_len;
|
||||
msghdr.msg_iovlen++;
|
||||
|
||||
//Set message name
|
||||
msghdr.msg_name = (void *) &msg_tr_ptr->addr;
|
||||
msghdr.msg_namelen = sizeof(ns_address_t);
|
||||
msghdr.msg_iov = &data_vector[0];
|
||||
msghdr.msg_iovlen = 2;
|
||||
//No ancillary data
|
||||
msghdr.msg_control = NULL;
|
||||
msghdr.msg_controllen = 0;
|
||||
|
||||
uint8_t *ptr = msg_tr_ptr->relay_start;
|
||||
*ptr = DHCPV6_RELAY_REPLY;
|
||||
libdhcpv6_dhcp_option_header_write(ptr + 34, msg_tr_ptr->msg_len);
|
||||
retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0);
|
||||
|
||||
} else {
|
||||
|
@ -972,6 +1008,12 @@ void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_addre
|
|||
(void)server_address;
|
||||
}
|
||||
|
||||
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable)
|
||||
{
|
||||
(void)instance;
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
|
||||
{
|
||||
(void)msg_tr_id;
|
||||
|
|
|
@ -859,9 +859,16 @@ uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_
|
|||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length)
|
||||
uint8_t *libdhcpv6_option_interface_id_write(uint8_t *ptr, int8_t interface_id)
|
||||
{
|
||||
ptr = common_write_16_bit(DHCPV6_OPTION_RELAY, ptr);
|
||||
ptr = libdhcpv6_dhcp_option_header_write(ptr, DHCPV6_OPTION_INTERFACE_ID, 1);
|
||||
*ptr++ = interface_id;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t option_type, uint16_t length)
|
||||
{
|
||||
ptr = common_write_16_bit(option_type, ptr);
|
||||
ptr = common_write_16_bit(length, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
@ -878,6 +885,11 @@ bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t
|
|||
relay_msg->peer_address = ptr + 16;
|
||||
ptr += 32;
|
||||
//Discover
|
||||
if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_INTERFACE_ID, &relay_msg->relay_interface_id) != 0) {
|
||||
relay_msg->relay_interface_id.len = 0;
|
||||
relay_msg->relay_interface_id.msg_ptr = NULL;
|
||||
}
|
||||
|
||||
if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_RELAY, &relay_msg->relay_options) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue