Bluetooth: Mesh: Transport SAR Configuration
Add support for: - SAR Configuration Client and Server models - Transport SAR configuration states - Using SAR Transmitter/Receiver states in segmentation and reassembly process. Bsim tests fixes: - Fix failing replay attack test. The replay attack test doesn't consider retransmission attempts at the transport layer. When retransmission happens, SeqNums get increased and the test logic doesn't work anymore. The simplest fix would be to disable retransmissions at the transport layer. - Add device synchronization API to synchronize transport va test. Device configuration may take different time on transmitter and receiver. Add synchronisation barrier between devices. - Fix msg_frnd test. Timing in transport sar behavior has been changed, which affected test_friend_msg test. Now acknowledgments are sent much faster and this needs to be considered in the test. - Fix unicast_low_lat test. Increase number of retransmission attempts when long segmented message is sent. - Reduce timeout in kr_old_key test. - Relax SAR RX state configuration in DFU and BLOB tests. Co-authored-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no> Co-authored-by: Anders Storrø <anders.storro@nordicsemi.no> Co-authored-by: Ingar Kulbrandstad <ingar.kulbrandstad@nordicsemi.no> Signed-off-by: Michał Narajowski <michal.narajowski@codecoup.pl> Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
2c1abb61b3
commit
dd59a45c65
30 changed files with 3215 additions and 125 deletions
|
@ -34,6 +34,8 @@
|
||||||
#include <zephyr/bluetooth/mesh/cdb.h>
|
#include <zephyr/bluetooth/mesh/cdb.h>
|
||||||
#include <zephyr/bluetooth/mesh/rpr_cli.h>
|
#include <zephyr/bluetooth/mesh/rpr_cli.h>
|
||||||
#include <zephyr/bluetooth/mesh/rpr_srv.h>
|
#include <zephyr/bluetooth/mesh/rpr_srv.h>
|
||||||
|
#include <zephyr/bluetooth/mesh/sar_cfg_srv.h>
|
||||||
|
#include <zephyr/bluetooth/mesh/sar_cfg_cli.h>
|
||||||
#include <zephyr/bluetooth/mesh/large_comp_data_srv.h>
|
#include <zephyr/bluetooth/mesh/large_comp_data_srv.h>
|
||||||
#include <zephyr/bluetooth/mesh/large_comp_data_cli.h>
|
#include <zephyr/bluetooth/mesh/large_comp_data_cli.h>
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ struct bt_mesh_elem {
|
||||||
#define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003
|
#define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003
|
||||||
#define BT_MESH_MODEL_ID_REMOTE_PROV_SRV 0x0004
|
#define BT_MESH_MODEL_ID_REMOTE_PROV_SRV 0x0004
|
||||||
#define BT_MESH_MODEL_ID_REMOTE_PROV_CLI 0x0005
|
#define BT_MESH_MODEL_ID_REMOTE_PROV_CLI 0x0005
|
||||||
|
#define BT_MESH_MODEL_ID_SAR_CFG_SRV 0x000e
|
||||||
|
#define BT_MESH_MODEL_ID_SAR_CFG_CLI 0x000f
|
||||||
#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_SRV 0x0012
|
#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_SRV 0x0012
|
||||||
#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_CLI 0x0013
|
#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_CLI 0x0013
|
||||||
|
|
||||||
|
|
69
include/zephyr/bluetooth/mesh/sar_cfg.h
Normal file
69
include/zephyr/bluetooth/mesh/sar_cfg.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @defgroup bt_mesh_sar_cfg SAR Configuration common header
|
||||||
|
* @{
|
||||||
|
* @brief Definitions for the SAR Configuration models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BT_MESH_SAR_CFG_H__
|
||||||
|
#define BT_MESH_SAR_CFG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** SAR Transmitter Configuration state structure */
|
||||||
|
struct bt_mesh_sar_tx {
|
||||||
|
/** SAR Segment Interval Step state */
|
||||||
|
uint8_t seg_int_step;
|
||||||
|
|
||||||
|
/** SAR Unicast Retransmissions Count state */
|
||||||
|
uint8_t unicast_retrans_count;
|
||||||
|
|
||||||
|
/** SAR Unicast Retransmissions Without Progress Count state */
|
||||||
|
uint8_t unicast_retrans_without_prog_count;
|
||||||
|
|
||||||
|
/* SAR Unicast Retransmissions Interval Step state */
|
||||||
|
uint8_t unicast_retrans_int_step;
|
||||||
|
|
||||||
|
/** SAR Unicast Retransmissions Interval Increment state */
|
||||||
|
uint8_t unicast_retrans_int_inc;
|
||||||
|
|
||||||
|
/** SAR Multicast Retransmissions Count state */
|
||||||
|
uint8_t multicast_retrans_count;
|
||||||
|
|
||||||
|
/** SAR Multicast Retransmissions Interval state */
|
||||||
|
uint8_t multicast_retrans_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** SAR Receiver Configuration state structure */
|
||||||
|
struct bt_mesh_sar_rx {
|
||||||
|
/** SAR Segments Threshold state */
|
||||||
|
uint8_t seg_thresh;
|
||||||
|
|
||||||
|
/** SAR Acknowledgment Delay Increment state */
|
||||||
|
uint8_t ack_delay_inc;
|
||||||
|
|
||||||
|
/** SAR Discard Timeout state */
|
||||||
|
uint8_t discard_timeout;
|
||||||
|
|
||||||
|
/** SAR Receiver Segment Interval Step state */
|
||||||
|
uint8_t rx_seg_int_step;
|
||||||
|
|
||||||
|
/** SAR Acknowledgment Retransmissions Count state */
|
||||||
|
uint8_t ack_retrans_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BT_MESH_SAR_CFG_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
123
include/zephyr/bluetooth/mesh/sar_cfg_cli.h
Normal file
123
include/zephyr/bluetooth/mesh/sar_cfg_cli.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Bluetooth Mesh SAR Configuration Client Model APIs.
|
||||||
|
*/
|
||||||
|
#ifndef BT_MESH_SAR_CFG_CLI_H__
|
||||||
|
#define BT_MESH_SAR_CFG_CLI_H__
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/mesh/sar_cfg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bluetooth Mesh
|
||||||
|
* @defgroup bt_mesh_sar_cfg_cli Bluetooth Mesh SAR Configuration Client Model
|
||||||
|
* @ingroup bt_mesh
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Mesh SAR Configuration Client Model Context */
|
||||||
|
struct bt_mesh_sar_cfg_cli {
|
||||||
|
/** Access model pointer. */
|
||||||
|
struct bt_mesh_model *model;
|
||||||
|
|
||||||
|
/* Publication structure instance */
|
||||||
|
struct bt_mesh_model_pub pub;
|
||||||
|
|
||||||
|
/* Synchronous message timeout in milliseconds. */
|
||||||
|
int32_t timeout;
|
||||||
|
|
||||||
|
/* Internal parameters for tracking message responses. */
|
||||||
|
struct bt_mesh_msg_ack_ctx ack_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @brief SAR Configuration Client model composition data entry.
|
||||||
|
*
|
||||||
|
* @param[in] _cli Pointer to a @ref bt_mesh_sar_cfg_cli instance.
|
||||||
|
*/
|
||||||
|
#define BT_MESH_MODEL_SAR_CFG_CLI(_cli) \
|
||||||
|
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_SAR_CFG_CLI, \
|
||||||
|
_bt_mesh_sar_cfg_cli_op, _cli.pub, _cli, \
|
||||||
|
&_bt_mesh_sar_cfg_cli_cb)
|
||||||
|
|
||||||
|
/** @brief Get the SAR Transmitter state of the target node.
|
||||||
|
*
|
||||||
|
* @param net_idx Network index to encrypt with.
|
||||||
|
* @param addr Target node address.
|
||||||
|
* @param rsp Status response parameter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or (negative) error code on failure.
|
||||||
|
*/
|
||||||
|
int bt_mesh_sar_cfg_cli_transmitter_get(uint16_t net_idx, uint16_t addr,
|
||||||
|
struct bt_mesh_sar_tx *rsp);
|
||||||
|
|
||||||
|
/** @brief Set the SAR Transmitter state of the target node.
|
||||||
|
*
|
||||||
|
* @param net_idx Network index to encrypt with.
|
||||||
|
* @param addr Target node address.
|
||||||
|
* @param set New SAR Transmitter state to set on the target node.
|
||||||
|
* @param rsp Status response parameter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or (negative) error code on failure.
|
||||||
|
*/
|
||||||
|
int bt_mesh_sar_cfg_cli_transmitter_set(uint16_t net_idx, uint16_t addr,
|
||||||
|
const struct bt_mesh_sar_tx *set,
|
||||||
|
struct bt_mesh_sar_tx *rsp);
|
||||||
|
|
||||||
|
/** @brief Get the SAR Receiver state of the target node.
|
||||||
|
*
|
||||||
|
* @param net_idx Network index to encrypt with.
|
||||||
|
* @param addr Target node address.
|
||||||
|
* @param rsp Status response parameter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or (negative) error code on failure.
|
||||||
|
*/
|
||||||
|
int bt_mesh_sar_cfg_cli_receiver_get(uint16_t net_idx, uint16_t addr,
|
||||||
|
struct bt_mesh_sar_rx *rsp);
|
||||||
|
|
||||||
|
/** @brief Set the SAR Receiver state of the target node.
|
||||||
|
*
|
||||||
|
* @param net_idx Network index to encrypt with.
|
||||||
|
* @param addr Target node address.
|
||||||
|
* @param set New SAR Receiver state to set on the target node.
|
||||||
|
* @param rsp Status response parameter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or (negative) error code on failure.
|
||||||
|
*/
|
||||||
|
int bt_mesh_sar_cfg_cli_receiver_set(uint16_t net_idx, uint16_t addr,
|
||||||
|
const struct bt_mesh_sar_rx *set,
|
||||||
|
struct bt_mesh_sar_rx *rsp);
|
||||||
|
|
||||||
|
/** @brief Get the current transmission timeout value.
|
||||||
|
*
|
||||||
|
* @return The configured transmission timeout in milliseconds.
|
||||||
|
*/
|
||||||
|
int32_t bt_mesh_sar_cfg_cli_timeout_get(void);
|
||||||
|
|
||||||
|
/** @brief Set the transmission timeout value.
|
||||||
|
*
|
||||||
|
* @param timeout The new transmission timeout.
|
||||||
|
*/
|
||||||
|
void bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout);
|
||||||
|
|
||||||
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
extern const struct bt_mesh_model_op _bt_mesh_sar_cfg_cli_op[];
|
||||||
|
extern const struct bt_mesh_model_cb _bt_mesh_sar_cfg_cli_cb;
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BT_MESH_SAR_CFG_CLI_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
47
include/zephyr/bluetooth/mesh/sar_cfg_srv.h
Normal file
47
include/zephyr/bluetooth/mesh/sar_cfg_srv.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Bluetooth Mesh SAR Configuration Server Model APIs.
|
||||||
|
*/
|
||||||
|
#ifndef BT_MESH_SAR_CFG_SRV_H__
|
||||||
|
#define BT_MESH_SAR_CFG_SRV_H__
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/mesh/sar_cfg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bluetooth Mesh
|
||||||
|
* @defgroup bt_mesh_sar_cfg_srv Bluetooth Mesh SAR Configuration Server Model
|
||||||
|
* @ingroup bt_mesh
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @brief Transport SAR Configuration Server model composition data entry.
|
||||||
|
*/
|
||||||
|
#define BT_MESH_MODEL_SAR_CFG_SRV \
|
||||||
|
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_SAR_CFG_SRV, bt_mesh_sar_cfg_srv_op, \
|
||||||
|
NULL, NULL, &bt_mesh_sar_cfg_srv_cb)
|
||||||
|
|
||||||
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
extern const struct bt_mesh_model_op bt_mesh_sar_cfg_srv_op[];
|
||||||
|
extern const struct bt_mesh_model_cb bt_mesh_sar_cfg_srv_cb;
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BT_MESH_SAR_CFG_SRV_H__ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
|
@ -11,7 +11,6 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH
|
||||||
net.c
|
net.c
|
||||||
subnet.c
|
subnet.c
|
||||||
app_keys.c
|
app_keys.c
|
||||||
transport.c
|
|
||||||
heartbeat.c
|
heartbeat.c
|
||||||
crypto.c
|
crypto.c
|
||||||
access.c
|
access.c
|
||||||
|
@ -20,6 +19,12 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH
|
||||||
health_srv.c
|
health_srv.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (CONFIG_BT_MESH_V1d1)
|
||||||
|
zephyr_library_sources(transport.c)
|
||||||
|
else()
|
||||||
|
zephyr_library_sources(transport_legacy.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_LEGACY adv_legacy.c)
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_LEGACY adv_legacy.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_EXT adv_ext.c)
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_EXT adv_ext.c)
|
||||||
|
@ -58,6 +63,12 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH_CFG_CLI cfg_cli.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_HEALTH_CLI health_cli.c)
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_HEALTH_CLI health_cli.c)
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SAR_CFG_CLI sar_cfg_cli.c)
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SAR_CFG_SRV sar_cfg_srv.c)
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SAR_CFG sar_cfg.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV large_comp_data_srv.c)
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV large_comp_data_srv.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI large_comp_data_cli.c)
|
zephyr_library_sources_ifdef(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI large_comp_data_cli.c)
|
||||||
|
|
|
@ -620,28 +620,6 @@ config BT_MESH_LOOPBACK_BUFS
|
||||||
The number of buffers allocated for the network loopback mechanism.
|
The number of buffers allocated for the network loopback mechanism.
|
||||||
Loopback is used when the device sends messages to itself.
|
Loopback is used when the device sends messages to itself.
|
||||||
|
|
||||||
config BT_MESH_TX_SEG_RETRANS_COUNT
|
|
||||||
int "Transport message segment retransmit attempts"
|
|
||||||
default 4
|
|
||||||
range 1 8
|
|
||||||
help
|
|
||||||
Maximum number of transport message segment retransmit attempts
|
|
||||||
for outgoing segment message.
|
|
||||||
|
|
||||||
config BT_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST
|
|
||||||
int "Transport message segment retransmit interval for unicast messages"
|
|
||||||
default 400
|
|
||||||
range 200 500
|
|
||||||
help
|
|
||||||
Maximum time of retransmit segment message to unicast address.
|
|
||||||
|
|
||||||
config BT_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP
|
|
||||||
int "Transport message segment retransmit interval for group messages"
|
|
||||||
default 50
|
|
||||||
range 20 200
|
|
||||||
help
|
|
||||||
Maximum time of retransmit segment message to group address.
|
|
||||||
|
|
||||||
config BT_MESH_NETWORK_TRANSMIT_COUNT
|
config BT_MESH_NETWORK_TRANSMIT_COUNT
|
||||||
int "Network Transmit Count"
|
int "Network Transmit Count"
|
||||||
default 2
|
default 2
|
||||||
|
@ -1209,6 +1187,21 @@ config BT_MESH_RPR_SRV_AD_DATA_MAX
|
||||||
extended scanning.
|
extended scanning.
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config BT_MESH_SAR_CFG
|
||||||
|
bool
|
||||||
|
|
||||||
|
config BT_MESH_SAR_CFG_SRV
|
||||||
|
bool "Support for SAR Configuration Server model"
|
||||||
|
select BT_MESH_SAR_CFG
|
||||||
|
help
|
||||||
|
Enable support for the SAR configuration server model.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_CFG_CLI
|
||||||
|
bool "Support for SAR Configuration Client Model"
|
||||||
|
select BT_MESH_SAR_CFG
|
||||||
|
help
|
||||||
|
Enable support for the SAR configuration client model.
|
||||||
|
|
||||||
config BT_MESH_LARGE_COMP_DATA_SRV
|
config BT_MESH_LARGE_COMP_DATA_SRV
|
||||||
bool "Support for Large Composition Data Server Model"
|
bool "Support for Large Composition Data Server Model"
|
||||||
help
|
help
|
||||||
|
@ -1219,8 +1212,159 @@ config BT_MESH_LARGE_COMP_DATA_CLI
|
||||||
help
|
help
|
||||||
Enable support for the Large Composition Data Client model.
|
Enable support for the Large Composition Data Client model.
|
||||||
|
|
||||||
|
menu "Transport SAR configuration"
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_SEG_INT_STEP
|
||||||
|
hex "Interval between sending two consecutive segments"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x01
|
||||||
|
help
|
||||||
|
This value controls the interval between sending two consecutive
|
||||||
|
segments in a segmented message. The interval is measured in
|
||||||
|
milliseconds and calculated using the following formula:
|
||||||
|
(CONFIG_BT_MESH_SAR_TX_SEG_INT_STEP + 1) * 10 ms.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_UNICAST_RETRANS_COUNT
|
||||||
|
hex "Maximum number of retransmissions to unicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x02
|
||||||
|
help
|
||||||
|
This value controls the maximum number of retransmissions of a
|
||||||
|
segmented message to a unicast address before giving up the transfer.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_UNICAST_RETRANS_WITHOUT_PROG_COUNT
|
||||||
|
hex "Maximum number of retransmissions without progress to a unicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x02
|
||||||
|
help
|
||||||
|
This value defines the maximum number of retransmissions of a
|
||||||
|
segmented message to a unicast address that the stack will send if no
|
||||||
|
acknowledgment was received during timeout, or if an
|
||||||
|
acknowledgment with already confirmed segments was received.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP
|
||||||
|
hex "Retransmissions interval step of missing segments to unicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x07
|
||||||
|
help
|
||||||
|
This value controls the interval step used for delaying the
|
||||||
|
retransmissions of unacknowledged segments of a segmented message to
|
||||||
|
a unicast address. The interval step is measured in milliseconds and
|
||||||
|
calculated using the following formula:
|
||||||
|
(CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP + 1) * 25 ms.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC
|
||||||
|
hex "Retransmissions interval increment of missing segments to unicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x01
|
||||||
|
help
|
||||||
|
This value controls the interval increment used for delaying the
|
||||||
|
retransmissions of unacknowledged segments of a segmented message to
|
||||||
|
a unicast address. The increment is measured in milliseconds and
|
||||||
|
calculated using the following formula:
|
||||||
|
(CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC + 1) * 25 ms.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_MULTICAST_RETRANS_COUNT
|
||||||
|
hex "Total number of retransmissions to multicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x02
|
||||||
|
help
|
||||||
|
This value controls the total number of retransmissions of a segmented
|
||||||
|
message to a multicast address.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_TX_MULTICAST_RETRANS_INT
|
||||||
|
hex "Interval between retransmissions to multicast address"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x03
|
||||||
|
help
|
||||||
|
This value controls the interval between retransmissions of all
|
||||||
|
segments in a segmented message to a multicast address. The
|
||||||
|
interval is measured in milliseconds and calculated using the
|
||||||
|
following formula:
|
||||||
|
(CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_INT + 1) * 25 ms.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_RX_SEG_THRESHOLD
|
||||||
|
hex "Acknowledgments retransmission threshold"
|
||||||
|
range 0x00 0x1F
|
||||||
|
default 0x03
|
||||||
|
help
|
||||||
|
This value defines a threshold in number of segments of a segmented
|
||||||
|
message for acknowledgment retransmissions. When the number of
|
||||||
|
segments of a segmented message is above this threshold, the stack
|
||||||
|
will additionally retransmit every acknowledgment message the
|
||||||
|
number of times given by value of CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_RX_ACK_DELAY_INC
|
||||||
|
hex "Acknowledgment delay increment"
|
||||||
|
range 0x00 0x07
|
||||||
|
default 0x02
|
||||||
|
help
|
||||||
|
This value controls the delay increment of an interval used for
|
||||||
|
delaying the transmission of an acknowledgment message after
|
||||||
|
receiving a new segment. The increment is measured in segments
|
||||||
|
and calculated using the following formula:
|
||||||
|
CONFIG_BT_MESH_SAR_RX_ACK_DELAY_INC + 1.5.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_RX_SEG_INT_STEP
|
||||||
|
hex "Segments reception interval step"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x01
|
||||||
|
help
|
||||||
|
This value defines the segments reception interval step used for
|
||||||
|
delaying the transmission of an acknowledgment message after
|
||||||
|
receiving a new segmnet. The interval is measured in milliseconds
|
||||||
|
and calculated using the following formula:
|
||||||
|
(CONFIG_BT_MESH_SAR_RX_SEG_INT_STEP + 1) * 10 ms
|
||||||
|
|
||||||
|
config BT_MESH_SAR_RX_DISCARD_TIMEOUT
|
||||||
|
hex "Discard timeout for reception of a segmented message"
|
||||||
|
range 0x00 0x0F
|
||||||
|
default 0x01
|
||||||
|
help
|
||||||
|
This value defines the time since the last successfully received
|
||||||
|
segment before giving up the reception of a segmented message.
|
||||||
|
|
||||||
|
config BT_MESH_SAR_RX_ACK_RETRANS_COUNT
|
||||||
|
hex "Total number of acknowledgment message retransmission"
|
||||||
|
range 0x00 0x03
|
||||||
|
default 0x01
|
||||||
|
help
|
||||||
|
This value defines the total number of retranmissions of an
|
||||||
|
acknowledgment message that the stack will additionally send when the
|
||||||
|
size of segments in a segmented message is above the
|
||||||
|
CONFIG_BT_MESH_SAR_RX_SEG_THRESHOLD value.
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
endif # BT_MESH_V1d1
|
endif # BT_MESH_V1d1
|
||||||
|
|
||||||
|
# Configuration options for 1.0.1 transport layer
|
||||||
|
if !BT_MESH_V1d1
|
||||||
|
|
||||||
|
config BT_MESH_TX_SEG_RETRANS_COUNT
|
||||||
|
int "Transport message segment retransmit attempts"
|
||||||
|
default 4
|
||||||
|
range 1 8
|
||||||
|
help
|
||||||
|
Maximum number of transport message segment retransmit attempts
|
||||||
|
for outgoing segment message.
|
||||||
|
|
||||||
|
config BT_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST
|
||||||
|
int "Transport message segment retransmit interval for unicast messages"
|
||||||
|
default 400
|
||||||
|
range 200 500
|
||||||
|
help
|
||||||
|
Maximum time of retransmit segment message to unicast address.
|
||||||
|
|
||||||
|
config BT_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP
|
||||||
|
int "Transport message segment retransmit interval for group messages"
|
||||||
|
default 50
|
||||||
|
range 20 200
|
||||||
|
help
|
||||||
|
Maximum time of retransmit segment message to group address.
|
||||||
|
|
||||||
|
endif #!BT_MESH_V1d1
|
||||||
|
|
||||||
rsource "shell/Kconfig"
|
rsource "shell/Kconfig"
|
||||||
|
|
||||||
config BT_MESH_MODEL_EXTENSIONS
|
config BT_MESH_MODEL_EXTENSIONS
|
||||||
|
|
|
@ -91,6 +91,12 @@
|
||||||
#define OP_VND_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4d)
|
#define OP_VND_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4d)
|
||||||
#define OP_VND_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4e)
|
#define OP_VND_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4e)
|
||||||
|
|
||||||
|
#define OP_SAR_CFG_TX_GET BT_MESH_MODEL_OP_2(0x80, 0x6c)
|
||||||
|
#define OP_SAR_CFG_TX_SET BT_MESH_MODEL_OP_2(0x80, 0x6d)
|
||||||
|
#define OP_SAR_CFG_TX_STATUS BT_MESH_MODEL_OP_2(0x80, 0x6e)
|
||||||
|
#define OP_SAR_CFG_RX_GET BT_MESH_MODEL_OP_2(0x80, 0x6f)
|
||||||
|
#define OP_SAR_CFG_RX_SET BT_MESH_MODEL_OP_2(0x80, 0x70)
|
||||||
|
#define OP_SAR_CFG_RX_STATUS BT_MESH_MODEL_OP_2(0x80, 0x71)
|
||||||
#define OP_LARGE_COMP_DATA_GET BT_MESH_MODEL_OP_2(0x80, 0x74)
|
#define OP_LARGE_COMP_DATA_GET BT_MESH_MODEL_OP_2(0x80, 0x74)
|
||||||
#define OP_LARGE_COMP_DATA_STATUS BT_MESH_MODEL_OP_2(0x80, 0x75)
|
#define OP_LARGE_COMP_DATA_STATUS BT_MESH_MODEL_OP_2(0x80, 0x75)
|
||||||
#define OP_MODELS_METADATA_GET BT_MESH_MODEL_OP_2(0x80, 0x76)
|
#define OP_MODELS_METADATA_GET BT_MESH_MODEL_OP_2(0x80, 0x76)
|
||||||
|
|
|
@ -37,6 +37,10 @@
|
||||||
#include "prov.h"
|
#include "prov.h"
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_MESH_V1d1
|
||||||
|
#include "sar_cfg_internal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LOG_LEVEL CONFIG_BT_MESH_NET_LOG_LEVEL
|
#define LOG_LEVEL CONFIG_BT_MESH_NET_LOG_LEVEL
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(bt_mesh_net);
|
LOG_MODULE_REGISTER(bt_mesh_net);
|
||||||
|
@ -88,6 +92,10 @@ static uint16_t msg_cache_next;
|
||||||
/* Singleton network context (the implementation only supports one) */
|
/* Singleton network context (the implementation only supports one) */
|
||||||
struct bt_mesh_net bt_mesh = {
|
struct bt_mesh_net bt_mesh = {
|
||||||
.local_queue = SYS_SLIST_STATIC_INIT(&bt_mesh.local_queue),
|
.local_queue = SYS_SLIST_STATIC_INIT(&bt_mesh.local_queue),
|
||||||
|
#ifdef CONFIG_BT_MESH_V1d1
|
||||||
|
.sar_tx = BT_MESH_SAR_TX_INIT,
|
||||||
|
.sar_rx = BT_MESH_SAR_RX_INIT,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mesh Profile Specification 3.10.6
|
/* Mesh Profile Specification 3.10.6
|
||||||
|
|
|
@ -224,6 +224,8 @@ struct bt_mesh_net {
|
||||||
#if defined(CONFIG_BT_MESH_RPR_SRV)
|
#if defined(CONFIG_BT_MESH_RPR_SRV)
|
||||||
uint8_t dev_key_cand[16];
|
uint8_t dev_key_cand[16];
|
||||||
#endif
|
#endif
|
||||||
|
struct bt_mesh_sar_tx sar_tx; /* Transport SAR Transmitter configuration */
|
||||||
|
struct bt_mesh_sar_rx sar_rx; /* Transport SAR Receiver configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Network interface */
|
/* Network interface */
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <zephyr/bluetooth/hci.h>
|
#include <zephyr/bluetooth/hci.h>
|
||||||
#include <zephyr/bluetooth/mesh/rpr_srv.h>
|
#include <zephyr/bluetooth/mesh/rpr_srv.h>
|
||||||
#include <common/bt_str.h>
|
#include <common/bt_str.h>
|
||||||
|
#include <zephyr/bluetooth/mesh/sar_cfg.h>
|
||||||
#include "access.h"
|
#include "access.h"
|
||||||
#include "adv.h"
|
#include "adv.h"
|
||||||
#include "host/ecc.h"
|
#include "host/ecc.h"
|
||||||
|
|
70
subsys/bluetooth/mesh/sar_cfg.c
Normal file
70
subsys/bluetooth/mesh/sar_cfg.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/net/buf.h>
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
#include <zephyr/bluetooth/gatt.h>
|
||||||
|
#include <zephyr/bluetooth/mesh.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "sar_cfg_internal.h"
|
||||||
|
|
||||||
|
void bt_mesh_sar_tx_encode(struct net_buf_simple *buf,
|
||||||
|
const struct bt_mesh_sar_tx *tx)
|
||||||
|
{
|
||||||
|
net_buf_simple_add_u8(buf, (tx->seg_int_step & 0xf) |
|
||||||
|
(tx->unicast_retrans_count << 4));
|
||||||
|
net_buf_simple_add_u8(buf, (tx->unicast_retrans_without_prog_count &
|
||||||
|
0xf) | (tx->unicast_retrans_int_step << 4));
|
||||||
|
net_buf_simple_add_u8(buf, (tx->unicast_retrans_int_inc & 0xf) |
|
||||||
|
(tx->multicast_retrans_count << 4));
|
||||||
|
net_buf_simple_add_u8(buf, tx->multicast_retrans_int & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_mesh_sar_rx_encode(struct net_buf_simple *buf,
|
||||||
|
const struct bt_mesh_sar_rx *rx)
|
||||||
|
{
|
||||||
|
net_buf_simple_add_u8(buf, (rx->seg_thresh & 0x1f) |
|
||||||
|
(rx->ack_delay_inc << 5));
|
||||||
|
net_buf_simple_add_u8(buf, (rx->discard_timeout & 0xf) |
|
||||||
|
((rx->rx_seg_int_step & 0xf) << 4));
|
||||||
|
net_buf_simple_add_u8(buf, (rx->ack_retrans_count & 0x3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_mesh_sar_tx_decode(struct net_buf_simple *buf,
|
||||||
|
struct bt_mesh_sar_tx *tx)
|
||||||
|
{
|
||||||
|
uint8_t val;
|
||||||
|
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
tx->seg_int_step = (val & 0xf);
|
||||||
|
tx->unicast_retrans_count = (val >> 4);
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
tx->unicast_retrans_without_prog_count = (val & 0xf);
|
||||||
|
tx->unicast_retrans_int_step = (val >> 4);
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
tx->unicast_retrans_int_inc = (val & 0xf);
|
||||||
|
tx->multicast_retrans_count = (val >> 4);
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
tx->multicast_retrans_int = (val & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_mesh_sar_rx_decode(struct net_buf_simple *buf,
|
||||||
|
struct bt_mesh_sar_rx *rx)
|
||||||
|
{
|
||||||
|
uint8_t val;
|
||||||
|
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
rx->seg_thresh = (val & 0x1f);
|
||||||
|
rx->ack_delay_inc = (val >> 5);
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
rx->discard_timeout = (val & 0xf);
|
||||||
|
rx->rx_seg_int_step = (val >> 4);
|
||||||
|
val = net_buf_simple_pull_u8(buf);
|
||||||
|
rx->ack_retrans_count = (val & 0x3);
|
||||||
|
}
|
246
subsys/bluetooth/mesh/sar_cfg_cli.c
Normal file
246
subsys/bluetooth/mesh/sar_cfg_cli.c
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/mesh.h>
|
||||||
|
#include <zephyr/bluetooth/mesh/access.h>
|
||||||
|
|
||||||
|
#include <common/bt_str.h>
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "access.h"
|
||||||
|
#include "foundation.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "sar_cfg_internal.h"
|
||||||
|
|
||||||
|
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(bt_mesh_sar_cfg_cli);
|
||||||
|
|
||||||
|
static struct bt_mesh_sar_cfg_cli *cli;
|
||||||
|
|
||||||
|
static int transmitter_status(struct bt_mesh_model *model,
|
||||||
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
struct bt_mesh_sar_tx *rsp;
|
||||||
|
|
||||||
|
if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS,
|
||||||
|
ctx->addr, (void **)&rsp)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_sar_tx_decode(buf, rsp);
|
||||||
|
|
||||||
|
LOG_DBG("SAR TX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}",
|
||||||
|
rsp->seg_int_step, rsp->unicast_retrans_count,
|
||||||
|
rsp->unicast_retrans_without_prog_count,
|
||||||
|
rsp->unicast_retrans_int_step, rsp->unicast_retrans_int_inc,
|
||||||
|
rsp->multicast_retrans_count, rsp->multicast_retrans_int);
|
||||||
|
|
||||||
|
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int receiver_status(struct bt_mesh_model *model,
|
||||||
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
struct bt_mesh_sar_rx *rsp;
|
||||||
|
|
||||||
|
LOG_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||||
|
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
||||||
|
bt_hex(buf->data, buf->len));
|
||||||
|
|
||||||
|
if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS,
|
||||||
|
ctx->addr, (void **)&rsp)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_sar_rx_decode(buf, rsp);
|
||||||
|
|
||||||
|
LOG_DBG("SAR RX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}", rsp->seg_thresh,
|
||||||
|
rsp->ack_delay_inc, rsp->discard_timeout, rsp->rx_seg_int_step,
|
||||||
|
rsp->ack_retrans_count);
|
||||||
|
|
||||||
|
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bt_mesh_model_op _bt_mesh_sar_cfg_cli_op[] = {
|
||||||
|
{ OP_SAR_CFG_TX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_TX_LEN), transmitter_status },
|
||||||
|
{ OP_SAR_CFG_RX_STATUS, BT_MESH_LEN_EXACT(BT_MESH_SAR_RX_LEN), receiver_status },
|
||||||
|
BT_MESH_MODEL_OP_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t bt_mesh_sar_cfg_cli_timeout_get(void)
|
||||||
|
{
|
||||||
|
return cli->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_mesh_sar_cfg_cli_timeout_set(int32_t timeout)
|
||||||
|
{
|
||||||
|
cli->timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bt_mesh_sar_cfg_cli_init(struct bt_mesh_model *model)
|
||||||
|
{
|
||||||
|
if (!bt_mesh_model_in_primary(model)) {
|
||||||
|
LOG_ERR("SAR Configuration Client only allowed in primary element");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!model->user_data) {
|
||||||
|
LOG_ERR("No SAR Configuration Client context provided");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cli = model->user_data;
|
||||||
|
cli->model = model;
|
||||||
|
cli->timeout = 2 * MSEC_PER_SEC;
|
||||||
|
|
||||||
|
model->keys[0] = BT_MESH_KEY_DEV_ANY;
|
||||||
|
model->flags |= BT_MESH_MOD_DEVKEY_ONLY;
|
||||||
|
|
||||||
|
bt_mesh_msg_ack_ctx_init(&cli->ack_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_mesh_sar_cfg_cli_reset(struct bt_mesh_model *model)
|
||||||
|
{
|
||||||
|
struct bt_mesh_sar_cfg_cli *cli;
|
||||||
|
|
||||||
|
cli = model->user_data;
|
||||||
|
|
||||||
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bt_mesh_model_cb _bt_mesh_sar_cfg_cli_cb = {
|
||||||
|
.init = bt_mesh_sar_cfg_cli_init,
|
||||||
|
.reset = bt_mesh_sar_cfg_cli_reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
int bt_mesh_sar_cfg_cli_transmitter_get(uint16_t net_idx, uint16_t addr,
|
||||||
|
struct bt_mesh_sar_tx *rsp)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_GET, 0);
|
||||||
|
struct bt_mesh_msg_ctx ctx = {
|
||||||
|
.net_idx = net_idx,
|
||||||
|
.app_idx = BT_MESH_KEY_DEV,
|
||||||
|
.addr = addr,
|
||||||
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_GET);
|
||||||
|
|
||||||
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("model_send() failed (err %d)", err);
|
||||||
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_mesh_sar_cfg_cli_transmitter_set(uint16_t net_idx, uint16_t addr,
|
||||||
|
const struct bt_mesh_sar_tx *set,
|
||||||
|
struct bt_mesh_sar_tx *rsp)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_SET, BT_MESH_SAR_TX_LEN);
|
||||||
|
struct bt_mesh_msg_ctx ctx = {
|
||||||
|
.net_idx = net_idx,
|
||||||
|
.app_idx = BT_MESH_KEY_DEV,
|
||||||
|
.addr = addr,
|
||||||
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_TX_STATUS, addr, rsp);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_SET);
|
||||||
|
bt_mesh_sar_tx_encode(&msg, set);
|
||||||
|
|
||||||
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("model_send() failed (err %d)", err);
|
||||||
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_mesh_sar_cfg_cli_receiver_get(uint16_t net_idx, uint16_t addr,
|
||||||
|
struct bt_mesh_sar_rx *rsp)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_GET, 0);
|
||||||
|
struct bt_mesh_msg_ctx ctx = {
|
||||||
|
.net_idx = net_idx,
|
||||||
|
.app_idx = BT_MESH_KEY_DEV,
|
||||||
|
.addr = addr,
|
||||||
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_GET);
|
||||||
|
|
||||||
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("model_send() failed (err %d)", err);
|
||||||
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_mesh_sar_cfg_cli_receiver_set(uint16_t net_idx, uint16_t addr,
|
||||||
|
const struct bt_mesh_sar_rx *set,
|
||||||
|
struct bt_mesh_sar_rx *rsp)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_SET, BT_MESH_SAR_RX_LEN);
|
||||||
|
struct bt_mesh_msg_ctx ctx = {
|
||||||
|
.net_idx = net_idx,
|
||||||
|
.app_idx = BT_MESH_KEY_DEV,
|
||||||
|
.addr = addr,
|
||||||
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, OP_SAR_CFG_RX_STATUS, addr, rsp);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_SET);
|
||||||
|
bt_mesh_sar_rx_encode(&msg, set);
|
||||||
|
|
||||||
|
err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("model_send() failed (err %d)", err);
|
||||||
|
bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(cli->timeout));
|
||||||
|
}
|
79
subsys/bluetooth/mesh/sar_cfg_internal.h
Normal file
79
subsys/bluetooth/mesh/sar_cfg_internal.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Internal Transport SAR Configuration API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_SAR_CFG_INTERNAL_H__
|
||||||
|
#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_SAR_CFG_INTERNAL_H__
|
||||||
|
|
||||||
|
/** SAR Transmitter Configuraion state encoded length */
|
||||||
|
#define BT_MESH_SAR_TX_LEN 4
|
||||||
|
/** SAR Receiver Configuraion state encoded length */
|
||||||
|
#define BT_MESH_SAR_RX_LEN 3
|
||||||
|
|
||||||
|
/** SAR Transmitter Configuration state initializer */
|
||||||
|
#define BT_MESH_SAR_TX_INIT \
|
||||||
|
{ \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_SEG_INT_STEP, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_COUNT, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_WITHOUT_PROG_COUNT, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_COUNT, \
|
||||||
|
CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_INT, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** SAR Receiver Configuration state initializer */
|
||||||
|
#define BT_MESH_SAR_RX_INIT \
|
||||||
|
{ \
|
||||||
|
CONFIG_BT_MESH_SAR_RX_SEG_THRESHOLD, \
|
||||||
|
CONFIG_BT_MESH_SAR_RX_ACK_DELAY_INC, \
|
||||||
|
CONFIG_BT_MESH_SAR_RX_DISCARD_TIMEOUT, \
|
||||||
|
CONFIG_BT_MESH_SAR_RX_SEG_INT_STEP, \
|
||||||
|
CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BT_MESH_SAR_TX_SEG_INT_MS ((bt_mesh.sar_tx.seg_int_step + 1) * 10)
|
||||||
|
#define BT_MESH_SAR_TX_RETRANS_COUNT(addr) \
|
||||||
|
(BT_MESH_ADDR_IS_UNICAST(addr) ? \
|
||||||
|
(bt_mesh.sar_tx.unicast_retrans_count + 1) : \
|
||||||
|
(bt_mesh.sar_tx.multicast_retrans_count + 1))
|
||||||
|
#define BT_MESH_SAR_TX_RETRANS_NO_PROGRESS \
|
||||||
|
(bt_mesh.sar_tx.unicast_retrans_without_prog_count + 1)
|
||||||
|
#define BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP_MS \
|
||||||
|
((bt_mesh.sar_tx.unicast_retrans_int_step + 1) * 25)
|
||||||
|
#define BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC_MS \
|
||||||
|
((bt_mesh.sar_tx.unicast_retrans_int_inc + 1) * 25)
|
||||||
|
#define BT_MESH_SAR_TX_UNICAST_RETRANS_TIMEOUT_MS(ttl) \
|
||||||
|
((ttl > 0) ? (BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP_MS + \
|
||||||
|
BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC_MS * (ttl - 1)) : \
|
||||||
|
BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP_MS)
|
||||||
|
#define BT_MESH_SAR_TX_MULTICAST_RETRANS_TIMEOUT_MS \
|
||||||
|
((bt_mesh.sar_tx.multicast_retrans_int + 1) * 25)
|
||||||
|
#define BT_MESH_SAR_TX_RETRANS_TIMEOUT_MS(addr, ttl) \
|
||||||
|
(BT_MESH_ADDR_IS_UNICAST(addr) ? \
|
||||||
|
BT_MESH_SAR_TX_UNICAST_RETRANS_TIMEOUT_MS(ttl) : \
|
||||||
|
BT_MESH_SAR_TX_MULTICAST_RETRANS_TIMEOUT_MS)
|
||||||
|
|
||||||
|
#define BT_MESH_SAR_RX_SEG_THRESHOLD (bt_mesh.sar_rx.seg_thresh)
|
||||||
|
#define BT_MESH_SAR_RX_ACK_DELAY_INC_X2 (bt_mesh.sar_rx.ack_delay_inc * 2 + 3)
|
||||||
|
#define BT_MESH_SAR_RX_ACK_RETRANS_COUNT (bt_mesh.sar_rx.ack_retrans_count + 1)
|
||||||
|
#define BT_MESH_SAR_RX_SEG_INT_MS ((bt_mesh.sar_rx.rx_seg_int_step + 1) * 10)
|
||||||
|
#define BT_MESH_SAR_RX_DISCARD_TIMEOUT_MS \
|
||||||
|
((bt_mesh.sar_rx.discard_timeout + 1) * 5 * MSEC_PER_SEC)
|
||||||
|
|
||||||
|
void bt_mesh_sar_tx_encode(struct net_buf_simple *buf,
|
||||||
|
const struct bt_mesh_sar_tx *tx);
|
||||||
|
void bt_mesh_sar_rx_encode(struct net_buf_simple *buf,
|
||||||
|
const struct bt_mesh_sar_rx *rx);
|
||||||
|
void bt_mesh_sar_tx_decode(struct net_buf_simple *buf,
|
||||||
|
struct bt_mesh_sar_tx *tx);
|
||||||
|
void bt_mesh_sar_rx_decode(struct net_buf_simple *buf,
|
||||||
|
struct bt_mesh_sar_rx *rx);
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_SAR_CFG_INTERNAL_H__ */
|
140
subsys/bluetooth/mesh/sar_cfg_srv.c
Normal file
140
subsys/bluetooth/mesh/sar_cfg_srv.c
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
#include <zephyr/bluetooth/mesh.h>
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "access.h"
|
||||||
|
#include "foundation.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "sar_cfg_internal.h"
|
||||||
|
|
||||||
|
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(bt_mesh_sar_cfg_srv);
|
||||||
|
|
||||||
|
static void transmitter_status(struct bt_mesh_model *model,
|
||||||
|
struct bt_mesh_msg_ctx *ctx)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_TX_STATUS, BT_MESH_SAR_TX_LEN);
|
||||||
|
const struct bt_mesh_sar_tx *tx = &bt_mesh.sar_tx;
|
||||||
|
|
||||||
|
LOG_DBG("SAR TX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}",
|
||||||
|
tx->seg_int_step, tx->unicast_retrans_count,
|
||||||
|
tx->unicast_retrans_without_prog_count,
|
||||||
|
tx->unicast_retrans_int_step, tx->unicast_retrans_int_inc,
|
||||||
|
tx->multicast_retrans_count, tx->multicast_retrans_int);
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_TX_STATUS);
|
||||||
|
bt_mesh_sar_tx_encode(&msg, tx);
|
||||||
|
|
||||||
|
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
|
||||||
|
LOG_ERR("Unable to send Transmitter Status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void receiver_status(struct bt_mesh_model *model,
|
||||||
|
struct bt_mesh_msg_ctx *ctx)
|
||||||
|
{
|
||||||
|
BT_MESH_MODEL_BUF_DEFINE(msg, OP_SAR_CFG_RX_STATUS, BT_MESH_SAR_RX_LEN);
|
||||||
|
const struct bt_mesh_sar_rx *rx = &bt_mesh.sar_rx;
|
||||||
|
|
||||||
|
LOG_DBG("SAR RX {0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}", rx->seg_thresh,
|
||||||
|
rx->ack_delay_inc, rx->discard_timeout, rx->rx_seg_int_step,
|
||||||
|
rx->ack_retrans_count);
|
||||||
|
|
||||||
|
bt_mesh_model_msg_init(&msg, OP_SAR_CFG_RX_STATUS);
|
||||||
|
bt_mesh_sar_rx_encode(&msg, rx);
|
||||||
|
|
||||||
|
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
|
||||||
|
LOG_ERR("Unable to send Receiver Status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transmitter_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
LOG_DBG("src 0x%04x", ctx->addr);
|
||||||
|
|
||||||
|
transmitter_status(model, ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transmitter_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
struct bt_mesh_sar_tx *tx = &bt_mesh.sar_tx;
|
||||||
|
|
||||||
|
LOG_DBG("src 0x%04x", ctx->addr);
|
||||||
|
|
||||||
|
bt_mesh_sar_tx_decode(buf, tx);
|
||||||
|
transmitter_status(model, ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int receiver_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
LOG_DBG("src 0x%04x", ctx->addr);
|
||||||
|
|
||||||
|
receiver_status(model, ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int receiver_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
struct bt_mesh_sar_rx *rx = &bt_mesh.sar_rx;
|
||||||
|
|
||||||
|
LOG_DBG("src 0x%04x", ctx->addr);
|
||||||
|
|
||||||
|
bt_mesh_sar_rx_decode(buf, rx);
|
||||||
|
receiver_status(model, ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bt_mesh_model_op bt_mesh_sar_cfg_srv_op[] = {
|
||||||
|
{ OP_SAR_CFG_TX_GET, BT_MESH_LEN_EXACT(0), transmitter_get },
|
||||||
|
{ OP_SAR_CFG_TX_SET, BT_MESH_LEN_EXACT(BT_MESH_SAR_TX_LEN), transmitter_set },
|
||||||
|
{ OP_SAR_CFG_RX_GET, BT_MESH_LEN_EXACT(0), receiver_get },
|
||||||
|
{ OP_SAR_CFG_RX_SET, BT_MESH_LEN_EXACT(BT_MESH_SAR_RX_LEN), receiver_set },
|
||||||
|
BT_MESH_MODEL_OP_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sar_cfg_srv_init(struct bt_mesh_model *model)
|
||||||
|
{
|
||||||
|
if (!bt_mesh_model_in_primary(model)) {
|
||||||
|
LOG_ERR("Configuration Server only allowed in primary element");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SAR Configuration Model security is device-key based and only the local
|
||||||
|
* device-key is allowed to access this model.
|
||||||
|
*/
|
||||||
|
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
|
||||||
|
model->flags |= BT_MESH_MOD_DEVKEY_ONLY;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bt_mesh_model_cb bt_mesh_sar_cfg_srv_cb = {
|
||||||
|
.init = sar_cfg_srv_init,
|
||||||
|
};
|
|
@ -31,6 +31,7 @@
|
||||||
#include "friend.h"
|
#include "friend.h"
|
||||||
#include "access.h"
|
#include "access.h"
|
||||||
#include "foundation.h"
|
#include "foundation.h"
|
||||||
|
#include "sar_cfg_internal.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "heartbeat.h"
|
#include "heartbeat.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
@ -55,26 +56,6 @@ LOG_MODULE_REGISTER(bt_mesh_transport);
|
||||||
|
|
||||||
#define SEQ_AUTH(iv_index, seq) (((uint64_t)iv_index) << 24 | (uint64_t)seq)
|
#define SEQ_AUTH(iv_index, seq) (((uint64_t)iv_index) << 24 | (uint64_t)seq)
|
||||||
|
|
||||||
/* Number of retransmit attempts (after the initial transmit) per segment */
|
|
||||||
#define SEG_RETRANSMIT_ATTEMPTS CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT
|
|
||||||
|
|
||||||
/* "This timer shall be set to a minimum of 200 + 50 * TTL milliseconds.".
|
|
||||||
* We use 400 since 300 is a common send duration for standard HCI, and we
|
|
||||||
* need to have a timeout that's bigger than that.
|
|
||||||
*/
|
|
||||||
#define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) \
|
|
||||||
(CONFIG_BT_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST + 50 * (tx)->ttl)
|
|
||||||
|
|
||||||
/* When sending to a group, the messages are not acknowledged, and there's no
|
|
||||||
* reason to delay the repetitions significantly. Delaying by more than 0 ms
|
|
||||||
* to avoid flooding the network.
|
|
||||||
*/
|
|
||||||
#define SEG_RETRANSMIT_TIMEOUT_GROUP CONFIG_BT_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP
|
|
||||||
|
|
||||||
#define SEG_RETRANSMIT_TIMEOUT(tx) \
|
|
||||||
(BT_MESH_ADDR_IS_UNICAST(tx->dst) ? \
|
|
||||||
SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \
|
|
||||||
SEG_RETRANSMIT_TIMEOUT_GROUP)
|
|
||||||
/* How long to wait for available buffers before giving up */
|
/* How long to wait for available buffers before giving up */
|
||||||
#define BUF_TIMEOUT K_NO_WAIT
|
#define BUF_TIMEOUT K_NO_WAIT
|
||||||
|
|
||||||
|
@ -92,10 +73,18 @@ struct va_val {
|
||||||
uint8_t uuid[16];
|
uint8_t uuid[16];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define ACK_DELAY(seg_n) \
|
||||||
|
(MIN(2 * seg_n + 1, BT_MESH_SAR_RX_ACK_DELAY_INC_X2) * \
|
||||||
|
BT_MESH_SAR_RX_SEG_INT_MS / 2)
|
||||||
|
|
||||||
|
#define SEQAUTH_ALREADY_PROCESSED_TIMEOUT \
|
||||||
|
(BT_MESH_SAR_RX_ACK_DELAY_INC_X2 * BT_MESH_SAR_RX_SEG_INT_MS / 2)
|
||||||
|
|
||||||
static struct seg_tx {
|
static struct seg_tx {
|
||||||
struct bt_mesh_subnet *sub;
|
struct bt_mesh_subnet *sub;
|
||||||
void *seg[BT_MESH_TX_SEG_MAX];
|
void *seg[BT_MESH_TX_SEG_MAX];
|
||||||
uint64_t seq_auth;
|
uint64_t seq_auth;
|
||||||
|
int64_t adv_start_timestamp; /* Calculate adv duration and adjust intervals*/
|
||||||
uint16_t src;
|
uint16_t src;
|
||||||
uint16_t dst;
|
uint16_t dst;
|
||||||
uint16_t ack_src;
|
uint16_t ack_src;
|
||||||
|
@ -105,14 +94,16 @@ static struct seg_tx {
|
||||||
uint8_t seg_n; /* Last segment index */
|
uint8_t seg_n; /* Last segment index */
|
||||||
uint8_t seg_o; /* Segment being sent */
|
uint8_t seg_o; /* Segment being sent */
|
||||||
uint8_t nack_count; /* Number of unacked segs */
|
uint8_t nack_count; /* Number of unacked segs */
|
||||||
uint8_t attempts; /* Remaining tx attempts */
|
uint8_t attempts_left;
|
||||||
|
uint8_t attempts_left_without_progress;
|
||||||
uint8_t ttl; /* Transmitted TTL value */
|
uint8_t ttl; /* Transmitted TTL value */
|
||||||
uint8_t blocked:1, /* Blocked by ongoing tx */
|
uint8_t blocked:1, /* Blocked by ongoing tx */
|
||||||
ctl:1, /* Control packet */
|
ctl:1, /* Control packet */
|
||||||
aszmic:1, /* MIC size */
|
aszmic:1, /* MIC size */
|
||||||
started:1, /* Start cb called */
|
started:1, /* Start cb called */
|
||||||
friend_cred:1, /* Using Friend credentials */
|
friend_cred:1, /* Using Friend credentials */
|
||||||
seg_send_started:1; /* Used to check if seg_send_start cb is called */
|
seg_send_started:1, /* Used to check if seg_send_start cb is called */
|
||||||
|
ack_received:1; /* Ack received during seg message transmission. */
|
||||||
const struct bt_mesh_send_cb *cb;
|
const struct bt_mesh_send_cb *cb;
|
||||||
void *cb_data;
|
void *cb_data;
|
||||||
struct k_work_delayable retransmit; /* Retransmit timer */
|
struct k_work_delayable retransmit; /* Retransmit timer */
|
||||||
|
@ -131,9 +122,11 @@ static struct seg_rx {
|
||||||
in_use:1,
|
in_use:1,
|
||||||
obo:1;
|
obo:1;
|
||||||
uint8_t ttl;
|
uint8_t ttl;
|
||||||
|
uint8_t attempts_left;
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint32_t last;
|
uint32_t last_ack;
|
||||||
struct k_work_delayable ack;
|
struct k_work_delayable ack;
|
||||||
|
struct k_work_delayable discard;
|
||||||
} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
|
} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
|
||||||
|
|
||||||
K_MEM_SLAB_DEFINE(segs, BT_MESH_APP_SEG_SDU_MAX, CONFIG_BT_MESH_SEG_BUFS, 4);
|
K_MEM_SLAB_DEFINE(segs, BT_MESH_APP_SEG_SDU_MAX, CONFIG_BT_MESH_SEG_BUFS, 4);
|
||||||
|
@ -301,20 +294,28 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void schedule_retransmit(struct seg_tx *tx)
|
static void schedule_transmit_continue(struct seg_tx *tx, uint32_t delta)
|
||||||
{
|
{
|
||||||
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
if (!tx->nack_count) {
|
if (!tx->nack_count) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
/* If we haven't gone through all the segments for this attempt yet,
|
if (delta < BT_MESH_SAR_TX_SEG_INT_MS) {
|
||||||
* (likely because of a buffer allocation failure or because we
|
timeout = BT_MESH_SAR_TX_SEG_INT_MS - delta;
|
||||||
* called this from inside bt_mesh_net_send), we should continue the
|
}
|
||||||
* retransmit immediately, as we just freed up a tx buffer.
|
|
||||||
|
/* If it is not the last segment then continue transmission after Segment Interval,
|
||||||
|
* otherwise continue immediately as the callback will finish this transmission and
|
||||||
|
* progress into retransmission.
|
||||||
*/
|
*/
|
||||||
k_work_reschedule(&tx->retransmit, K_NO_WAIT);
|
k_work_reschedule(&tx->retransmit,
|
||||||
|
(tx->seg_o <= tx->seg_n) ?
|
||||||
|
K_MSEC(timeout) :
|
||||||
|
K_NO_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seg_send_start(uint16_t duration, int err, void *user_data)
|
static void seg_send_start(uint16_t duration, int err, void *user_data)
|
||||||
|
@ -327,25 +328,27 @@ static void seg_send_start(uint16_t duration, int err, void *user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx->seg_send_started = 1U;
|
tx->seg_send_started = 1U;
|
||||||
|
tx->adv_start_timestamp = k_uptime_get();
|
||||||
|
|
||||||
/* If there's an error in transmitting the 'sent' callback will never
|
/* If there's an error in transmitting the 'sent' callback will never
|
||||||
* be called. Make sure that we kick the retransmit timer also in this
|
* be called. Make sure that we kick the retransmit timer also in this
|
||||||
* case since otherwise we risk the transmission of becoming stale.
|
* case since otherwise we risk the transmission of becoming stale.
|
||||||
*/
|
*/
|
||||||
if (err) {
|
if (err) {
|
||||||
schedule_retransmit(tx);
|
schedule_transmit_continue(tx, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seg_sent(int err, void *user_data)
|
static void seg_sent(int err, void *user_data)
|
||||||
{
|
{
|
||||||
struct seg_tx *tx = user_data;
|
struct seg_tx *tx = user_data;
|
||||||
|
uint32_t delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp);
|
||||||
|
|
||||||
if (!tx->seg_send_started) {
|
if (!tx->seg_send_started) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_retransmit(tx);
|
schedule_transmit_continue(tx, delta_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct bt_mesh_send_cb seg_sent_cb = {
|
static const struct bt_mesh_send_cb seg_sent_cb = {
|
||||||
|
@ -372,6 +375,8 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t delta_ms;
|
||||||
|
uint32_t timeout;
|
||||||
struct bt_mesh_msg_ctx ctx = {
|
struct bt_mesh_msg_ctx ctx = {
|
||||||
.net_idx = tx->sub->net_idx,
|
.net_idx = tx->sub->net_idx,
|
||||||
/* App idx only used by network to detect control messages: */
|
/* App idx only used by network to detect control messages: */
|
||||||
|
@ -389,7 +394,14 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
|
||||||
.aid = tx->hdr & AID_MASK,
|
.aid = tx->hdr & AID_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!tx->attempts) {
|
if (BT_MESH_ADDR_IS_UNICAST(tx->dst) &&
|
||||||
|
!tx->attempts_left_without_progress) {
|
||||||
|
LOG_ERR("Ran out of retransmit without progress attempts");
|
||||||
|
seg_tx_complete(tx, -ETIMEDOUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tx->attempts_left) {
|
||||||
if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
|
if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
|
||||||
LOG_ERR("Ran out of retransmit attempts");
|
LOG_ERR("Ran out of retransmit attempts");
|
||||||
seg_tx_complete(tx, -ETIMEDOUT);
|
seg_tx_complete(tx, -ETIMEDOUT);
|
||||||
|
@ -403,8 +415,8 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("SeqZero: 0x%04x Attempts: %u", (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK),
|
LOG_DBG("SeqZero: 0x%04x Attempts: %u",
|
||||||
tx->attempts);
|
(uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts_left);
|
||||||
|
|
||||||
while (tx->seg_o <= tx->seg_n) {
|
while (tx->seg_o <= tx->seg_n) {
|
||||||
struct net_buf *seg;
|
struct net_buf *seg;
|
||||||
|
@ -437,11 +449,21 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
|
||||||
/* Move on to the next segment */
|
/* Move on to the next segment */
|
||||||
tx->seg_o++;
|
tx->seg_o++;
|
||||||
|
|
||||||
|
tx->ack_received = 0U;
|
||||||
|
|
||||||
|
/* Return here to let the advertising layer process the message.
|
||||||
|
* This function will be called again after Segment Interval.
|
||||||
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* All segments have been sent */
|
||||||
tx->seg_o = 0U;
|
tx->seg_o = 0U;
|
||||||
tx->attempts--;
|
tx->attempts_left--;
|
||||||
|
if (BT_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->ack_received) {
|
||||||
|
tx->attempts_left_without_progress--;
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
|
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
|
||||||
|
@ -449,7 +471,23 @@ end:
|
||||||
bt_mesh_lpn_poll();
|
bt_mesh_lpn_poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
k_work_reschedule(&tx->retransmit, K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
|
delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp);
|
||||||
|
if (tx->ack_received) {
|
||||||
|
/* Schedule retransmission immediately but keep SAR segment interval time if
|
||||||
|
* SegAck was received while sending last segment.
|
||||||
|
*/
|
||||||
|
timeout = BT_MESH_SAR_TX_SEG_INT_MS;
|
||||||
|
tx->ack_received = 0U;
|
||||||
|
} else {
|
||||||
|
timeout = BT_MESH_SAR_TX_RETRANS_TIMEOUT_MS(tx->dst, tx->ttl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta_ms < timeout) {
|
||||||
|
timeout -= delta_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedule a retransmission */
|
||||||
|
k_work_reschedule(&tx->retransmit, K_MSEC(timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seg_retransmit(struct k_work *work)
|
static void seg_retransmit(struct k_work *work)
|
||||||
|
@ -504,7 +542,8 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
|
||||||
tx->sub = net_tx->sub;
|
tx->sub = net_tx->sub;
|
||||||
tx->cb = cb;
|
tx->cb = cb;
|
||||||
tx->cb_data = cb_data;
|
tx->cb_data = cb_data;
|
||||||
tx->attempts = SEG_RETRANSMIT_ATTEMPTS;
|
tx->attempts_left = BT_MESH_SAR_TX_RETRANS_COUNT(tx->dst);
|
||||||
|
tx->attempts_left_without_progress = BT_MESH_SAR_TX_RETRANS_NO_PROGRESS;
|
||||||
tx->xmit = net_tx->xmit;
|
tx->xmit = net_tx->xmit;
|
||||||
tx->aszmic = net_tx->aszmic;
|
tx->aszmic = net_tx->aszmic;
|
||||||
tx->friend_cred = net_tx->friend_cred;
|
tx->friend_cred = net_tx->friend_cred;
|
||||||
|
@ -806,6 +845,7 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t add
|
||||||
static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
|
static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
|
||||||
struct net_buf_simple *buf, uint64_t *seq_auth)
|
struct net_buf_simple *buf, uint64_t *seq_auth)
|
||||||
{
|
{
|
||||||
|
bool new_seg_ack = false;
|
||||||
struct seg_tx *tx;
|
struct seg_tx *tx;
|
||||||
unsigned int bit;
|
unsigned int bit;
|
||||||
uint32_t ack;
|
uint32_t ack;
|
||||||
|
@ -834,7 +874,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
|
||||||
|
|
||||||
tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr);
|
tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr);
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
LOG_WRN("No matching TX context for ack");
|
LOG_DBG("No matching TX context for ack");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,20 +900,42 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
|
||||||
if (tx->seg[bit - 1]) {
|
if (tx->seg[bit - 1]) {
|
||||||
LOG_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
|
LOG_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
|
||||||
seg_tx_done(tx, bit - 1);
|
seg_tx_done(tx, bit - 1);
|
||||||
|
new_seg_ack = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ack &= ~BIT(bit - 1);
|
ack &= ~BIT(bit - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_seg_ack) {
|
||||||
|
tx->attempts_left_without_progress =
|
||||||
|
BT_MESH_SAR_TX_RETRANS_NO_PROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (tx->nack_count) {
|
if (tx->nack_count) {
|
||||||
/* According to the Bluetooth Mesh Profile specification,
|
/* If transmission is not in progress it means
|
||||||
* section 3.5.3.3, we should reset the retransmit timer and
|
* that Retransmission Timer is running
|
||||||
* retransmit immediately when receiving a valid ack message.
|
|
||||||
* Don't reset the retransmit timer if we didn't finish sending
|
|
||||||
* segments.
|
|
||||||
*/
|
*/
|
||||||
if (tx->seg_o == 0) {
|
if (new_seg_ack) {
|
||||||
k_work_reschedule(&tx->retransmit, K_NO_WAIT);
|
if (tx->seg_o == 0) {
|
||||||
|
uint32_t delta_ms = (uint32_t)(k_uptime_get() -
|
||||||
|
tx->adv_start_timestamp);
|
||||||
|
k_timeout_t timeout = K_NO_WAIT;
|
||||||
|
|
||||||
|
/* According to the Bluetooth Mesh Profile specification,
|
||||||
|
* section 3.5.3.3, we should reset the retransmit timer and
|
||||||
|
* retransmit immediately when receiving a valid ack message
|
||||||
|
* while Retransmisison timer is running. However, transport should
|
||||||
|
* still keep segment transmission interval time between
|
||||||
|
* transmission of each segment.
|
||||||
|
*/
|
||||||
|
if (delta_ms < BT_MESH_SAR_TX_SEG_INT_MS) {
|
||||||
|
timeout = K_MSEC(BT_MESH_SAR_TX_SEG_INT_MS - delta_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_work_reschedule(&tx->retransmit, timeout);
|
||||||
|
} else {
|
||||||
|
tx->ack_received = 1U;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_DBG("SDU TX complete");
|
LOG_DBG("SDU TX complete");
|
||||||
|
@ -984,33 +1046,6 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
|
||||||
return sdu_recv(rx, hdr, 0, buf, &sdu, NULL);
|
return sdu_recv(rx, hdr, 0, buf, &sdu, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t ack_timeout(struct seg_rx *rx)
|
|
||||||
{
|
|
||||||
int32_t to;
|
|
||||||
uint8_t ttl;
|
|
||||||
|
|
||||||
if (rx->ttl == BT_MESH_TTL_DEFAULT) {
|
|
||||||
ttl = bt_mesh_default_ttl_get();
|
|
||||||
} else {
|
|
||||||
ttl = rx->ttl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The acknowledgment timer shall be set to a minimum of
|
|
||||||
* 150 + 50 * TTL milliseconds.
|
|
||||||
*/
|
|
||||||
to = CONFIG_BT_MESH_SEG_ACK_BASE_TIMEOUT +
|
|
||||||
(ttl * (int32_t)CONFIG_BT_MESH_SEG_ACK_PER_HOP_TIMEOUT);
|
|
||||||
|
|
||||||
/* Add timeout for evenry not yet received segment. */
|
|
||||||
to += ((rx->seg_n + 1) - POPCOUNT(rx->block)) *
|
|
||||||
(int32_t)CONFIG_BT_MESH_SEG_ACK_PER_SEGMENT_TIMEOUT;
|
|
||||||
|
|
||||||
/* Make sure we don't send more frequently than the duration for
|
|
||||||
* each packet (default is 400ms).
|
|
||||||
*/
|
|
||||||
return MAX(to, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
|
int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
|
||||||
size_t data_len,
|
size_t data_len,
|
||||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||||
|
@ -1099,6 +1134,7 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
|
||||||
* it checks rx->in_use.
|
* it checks rx->in_use.
|
||||||
*/
|
*/
|
||||||
(void)k_work_cancel_delayable(&rx->ack);
|
(void)k_work_cancel_delayable(&rx->ack);
|
||||||
|
(void)k_work_cancel_delayable(&rx->discard);
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo &&
|
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo &&
|
||||||
rx->block != BLOCK_COMPLETE(rx->seg_n)) {
|
rx->block != BLOCK_COMPLETE(rx->seg_n)) {
|
||||||
|
@ -1130,11 +1166,23 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void seg_discard(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, discard);
|
||||||
|
|
||||||
|
LOG_WRN("SAR Discard timeout expired");
|
||||||
|
seg_rx_reset(rx, false);
|
||||||
|
rx->block = 0U;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_BT_TESTING)) {
|
||||||
|
bt_test_mesh_trans_incomp_timer_exp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void seg_ack(struct k_work *work)
|
static void seg_ack(struct k_work *work)
|
||||||
{
|
{
|
||||||
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
|
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
|
||||||
struct seg_rx *rx = CONTAINER_OF(dwork, struct seg_rx, ack);
|
struct seg_rx *rx = CONTAINER_OF(dwork, struct seg_rx, ack);
|
||||||
int32_t timeout;
|
|
||||||
|
|
||||||
if (!rx->in_use || rx->block == BLOCK_COMPLETE(rx->seg_n)) {
|
if (!rx->in_use || rx->block == BLOCK_COMPLETE(rx->seg_n)) {
|
||||||
/* Cancellation of this timer may have failed. If it fails as
|
/* Cancellation of this timer may have failed. If it fails as
|
||||||
|
@ -1148,22 +1196,20 @@ static void seg_ack(struct k_work *work)
|
||||||
|
|
||||||
LOG_DBG("rx %p", rx);
|
LOG_DBG("rx %p", rx);
|
||||||
|
|
||||||
if (k_uptime_get_32() - rx->last > (60 * MSEC_PER_SEC)) {
|
|
||||||
LOG_WRN("Incomplete timer expired");
|
|
||||||
seg_rx_reset(rx, false);
|
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_TESTING)) {
|
|
||||||
bt_test_mesh_trans_incomp_timer_exp();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
|
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
|
||||||
rx->block, rx->obo);
|
rx->block, rx->obo);
|
||||||
|
|
||||||
timeout = ack_timeout(rx);
|
rx->last_ack = k_uptime_get_32();
|
||||||
k_work_schedule(&rx->ack, K_MSEC(timeout));
|
|
||||||
|
if (rx->attempts_left == 0) {
|
||||||
|
LOG_DBG("Ran out of retransmit attempts");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx->seg_n > BT_MESH_SAR_RX_SEG_THRESHOLD) {
|
||||||
|
--rx->attempts_left;
|
||||||
|
k_work_schedule(&rx->ack, K_MSEC(BT_MESH_SAR_RX_SEG_INT_MS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
|
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
|
||||||
|
@ -1351,9 +1397,18 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
|
||||||
if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
|
if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
|
||||||
LOG_DBG("Got segment for already complete SDU");
|
LOG_DBG("Got segment for already complete SDU");
|
||||||
|
|
||||||
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
|
/* We should not send more than one Segment Acknowledgment message
|
||||||
net_rx->ctx.addr, net_rx->ctx.send_ttl,
|
* for the same SeqAuth in a period of:
|
||||||
seq_auth, rx->block, rx->obo);
|
* [acknowledgment delay increment * segment transmission interval]
|
||||||
|
* milliseconds
|
||||||
|
*/
|
||||||
|
if (k_uptime_get_32() - rx->last_ack >
|
||||||
|
SEQAUTH_ALREADY_PROCESSED_TIMEOUT) {
|
||||||
|
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
|
||||||
|
net_rx->ctx.addr, net_rx->ctx.send_ttl,
|
||||||
|
seq_auth, rx->block, rx->obo);
|
||||||
|
rx->last_ack = k_uptime_get_32();
|
||||||
|
}
|
||||||
|
|
||||||
if (rpl) {
|
if (rpl) {
|
||||||
bt_mesh_rpl_update(rpl, net_rx);
|
bt_mesh_rpl_update(rpl, net_rx);
|
||||||
|
@ -1460,13 +1515,14 @@ found_rx:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the Incomplete Timer */
|
LOG_DBG("discard timeout %u", BT_MESH_SAR_RX_DISCARD_TIMEOUT_MS);
|
||||||
rx->last = k_uptime_get_32();
|
k_work_schedule(&rx->discard,
|
||||||
|
K_MSEC(BT_MESH_SAR_RX_DISCARD_TIMEOUT_MS));
|
||||||
|
rx->attempts_left = BT_MESH_SAR_RX_ACK_RETRANS_COUNT;
|
||||||
|
|
||||||
if (!bt_mesh_lpn_established()) {
|
if (!bt_mesh_lpn_established() && BT_MESH_ADDR_IS_UNICAST(rx->dst)) {
|
||||||
int32_t timeout = ack_timeout(rx);
|
LOG_DBG("ack delay %u", ACK_DELAY(rx->seg_n));
|
||||||
/* Should only start ack timer if it isn't running already: */
|
k_work_reschedule(&rx->ack, K_MSEC(ACK_DELAY(rx->seg_n)));
|
||||||
k_work_schedule(&rx->ack, K_MSEC(timeout));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocated segment here */
|
/* Allocated segment here */
|
||||||
|
@ -1506,8 +1562,10 @@ found_rx:
|
||||||
* block is fully received, or rx->in_use is false.
|
* block is fully received, or rx->in_use is false.
|
||||||
*/
|
*/
|
||||||
(void)k_work_cancel_delayable(&rx->ack);
|
(void)k_work_cancel_delayable(&rx->ack);
|
||||||
|
|
||||||
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
|
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
|
||||||
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
|
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
|
||||||
|
rx->last_ack = k_uptime_get_32();
|
||||||
|
|
||||||
if (net_rx->ctl) {
|
if (net_rx->ctl) {
|
||||||
NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_RX_CTL_MAX);
|
NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_RX_CTL_MAX);
|
||||||
|
@ -1666,6 +1724,7 @@ void bt_mesh_trans_init(void)
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
|
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
|
||||||
k_work_init_delayable(&seg_rx[i].ack, seg_ack);
|
k_work_init_delayable(&seg_rx[i].ack, seg_ack);
|
||||||
|
k_work_init_delayable(&seg_rx[i].discard, seg_discard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1866
subsys/bluetooth/mesh/transport_legacy.c
Normal file
1866
subsys/bluetooth/mesh/transport_legacy.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@ CONFIG_BT_MESH_MODEL_GROUP_COUNT=2
|
||||||
CONFIG_BT_MESH_CDB_NODE_COUNT=3
|
CONFIG_BT_MESH_CDB_NODE_COUNT=3
|
||||||
CONFIG_BT_MESH_CDB_SUBNET_COUNT=2
|
CONFIG_BT_MESH_CDB_SUBNET_COUNT=2
|
||||||
CONFIG_BT_MESH_SUBNET_COUNT=2
|
CONFIG_BT_MESH_SUBNET_COUNT=2
|
||||||
CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT=1
|
|
||||||
CONFIG_BT_MESH_SEQ_STORE_RATE=1
|
CONFIG_BT_MESH_SEQ_STORE_RATE=1
|
||||||
CONFIG_BT_MESH_RPL_STORE_TIMEOUT=1
|
CONFIG_BT_MESH_RPL_STORE_TIMEOUT=1
|
||||||
CONFIG_BT_MESH_STORE_TIMEOUT=1
|
CONFIG_BT_MESH_STORE_TIMEOUT=1
|
||||||
|
CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT=1
|
||||||
|
|
|
@ -46,6 +46,8 @@ CONFIG_BT_MESH_CDB_NODE_COUNT=4
|
||||||
CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y
|
CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y
|
||||||
CONFIG_BT_MESH_MODEL_EXTENSIONS=y
|
CONFIG_BT_MESH_MODEL_EXTENSIONS=y
|
||||||
CONFIG_BT_MESH_SUBNET_COUNT=5
|
CONFIG_BT_MESH_SUBNET_COUNT=5
|
||||||
|
CONFIG_BT_MESH_SAR_CFG_CLI=y
|
||||||
|
CONFIG_BT_MESH_SAR_CFG_SRV=y
|
||||||
CONFIG_BT_MESH_BLOB_SRV=y
|
CONFIG_BT_MESH_BLOB_SRV=y
|
||||||
CONFIG_BT_MESH_BLOB_CLI=y
|
CONFIG_BT_MESH_BLOB_CLI=y
|
||||||
CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MIN=256
|
CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MIN=256
|
||||||
|
|
|
@ -42,3 +42,44 @@ int lost_targets_rem(void)
|
||||||
{
|
{
|
||||||
return lost_targets.rem_cnt;
|
return lost_targets.rem_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void common_sar_conf(uint16_t addr)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Reconfigure SAR Transmitter state to change compile-time configuration to default
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
struct bt_mesh_sar_tx tx_set = {
|
||||||
|
.seg_int_step = 1,
|
||||||
|
.unicast_retrans_count = 2,
|
||||||
|
.unicast_retrans_without_prog_count = 2,
|
||||||
|
.unicast_retrans_int_step = 7,
|
||||||
|
.unicast_retrans_int_inc = 1,
|
||||||
|
.multicast_retrans_count = 2,
|
||||||
|
.multicast_retrans_int = 3,
|
||||||
|
};
|
||||||
|
struct bt_mesh_sar_tx tx_rsp;
|
||||||
|
|
||||||
|
err = bt_mesh_sar_cfg_cli_transmitter_set(0, addr, &tx_set, &tx_rsp);
|
||||||
|
if (err) {
|
||||||
|
FAIL("Failed to configure SAR Transmitter state (err %d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reconfigure SAR Receiver state so that the transport layer doesn't generate SegAcks too
|
||||||
|
* frequently.
|
||||||
|
*/
|
||||||
|
struct bt_mesh_sar_rx rx_set = {
|
||||||
|
.seg_thresh = 0x1f,
|
||||||
|
.ack_delay_inc = 7,
|
||||||
|
.discard_timeout = 1,
|
||||||
|
.rx_seg_int_step = 0xf,
|
||||||
|
.ack_retrans_count = 1,
|
||||||
|
};
|
||||||
|
struct bt_mesh_sar_rx rx_rsp;
|
||||||
|
|
||||||
|
err = bt_mesh_sar_cfg_cli_receiver_set(0, addr, &rx_set, &rx_rsp);
|
||||||
|
if (err) {
|
||||||
|
FAIL("Failed to configure SAR Receiver state (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <zephyr/bluetooth/mesh.h>
|
||||||
|
|
||||||
bool lost_target_find_and_remove(uint16_t addr);
|
bool lost_target_find_and_remove(uint16_t addr);
|
||||||
void lost_target_add(uint16_t addr);
|
void lost_target_add(uint16_t addr);
|
||||||
int lost_targets_rem(void);
|
int lost_targets_rem(void);
|
||||||
|
|
||||||
|
void common_sar_conf(uint16_t addr);
|
||||||
|
|
|
@ -159,11 +159,19 @@ static struct bt_mesh_model_pub health_pub = {
|
||||||
.msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX),
|
.msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
static struct bt_mesh_sar_cfg_cli sar_cfg_cli;
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct bt_mesh_model models[] = {
|
static struct bt_mesh_model models[] = {
|
||||||
BT_MESH_MODEL_CFG_SRV,
|
BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
BT_MESH_MODEL_CB(TEST_MOD_ID, model_op, &pub, NULL, &test_model_cb),
|
BT_MESH_MODEL_CB(TEST_MOD_ID, model_op, &pub, NULL, &test_model_cb),
|
||||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bt_mesh_model *test_model = &models[2];
|
struct bt_mesh_model *test_model = &models[2];
|
||||||
|
@ -254,6 +262,11 @@ void bt_mesh_test_setup(void)
|
||||||
{
|
{
|
||||||
static struct bt_mesh_prov prov;
|
static struct bt_mesh_prov prov;
|
||||||
|
|
||||||
|
/* Ensure those test devices will not drift more than
|
||||||
|
* 100ms for each other in emulated time
|
||||||
|
*/
|
||||||
|
tm_set_phy_max_resync_offset(100000);
|
||||||
|
|
||||||
net_buf_simple_init(pub.msg, 0);
|
net_buf_simple_init(pub.msg, 0);
|
||||||
net_buf_simple_init(vnd_pub.msg, 0);
|
net_buf_simple_init(vnd_pub.msg, 0);
|
||||||
|
|
||||||
|
@ -569,3 +582,28 @@ uint16_t bt_mesh_test_own_addr_get(uint16_t start_addr)
|
||||||
{
|
{
|
||||||
return start_addr + get_device_nbr();
|
return start_addr + get_device_nbr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
void bt_mesh_test_sar_conf_set(struct bt_mesh_sar_tx *tx_set, struct bt_mesh_sar_rx *rx_set)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (tx_set) {
|
||||||
|
struct bt_mesh_sar_tx tx_rsp;
|
||||||
|
|
||||||
|
err = bt_mesh_sar_cfg_cli_transmitter_set(0, cfg->addr, tx_set, &tx_rsp);
|
||||||
|
if (err) {
|
||||||
|
FAIL("Failed to configure SAR Transmitter state (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_set) {
|
||||||
|
struct bt_mesh_sar_rx rx_rsp;
|
||||||
|
|
||||||
|
err = bt_mesh_sar_cfg_cli_receiver_set(0, cfg->addr, rx_set, &rx_rsp);
|
||||||
|
if (err) {
|
||||||
|
FAIL("Failed to configure SAR Receiver state (err %d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* defined(CONFIG_BT_MESH_SAR_CFG) */
|
||||||
|
|
|
@ -163,4 +163,8 @@ bool bt_mesh_test_sync(uint32_t channel_id, uint16_t wait_sec);
|
||||||
|
|
||||||
uint16_t bt_mesh_test_own_addr_get(uint16_t start_addr);
|
uint16_t bt_mesh_test_own_addr_get(uint16_t start_addr);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
void bt_mesh_test_sar_conf_set(struct bt_mesh_sar_tx *tx_set, struct bt_mesh_sar_rx *rx_set);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ZEPHYR_TESTS_BLUETOOTH_BSIM_BT_BSIM_TEST_MESH_MESH_TEST_H_ */
|
#endif /* ZEPHYR_TESTS_BLUETOOTH_BSIM_BT_BSIM_TEST_MESH_MESH_TEST_H_ */
|
||||||
|
|
|
@ -623,7 +623,7 @@ static void test_rx_kr_old_key(void)
|
||||||
{ .phase = BT_MESH_KR_NORMAL, .ivu = false, .ivi = 1 },
|
{ .phase = BT_MESH_KR_NORMAL, .ivu = false, .ivi = 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
k_sleep(K_SECONDS(10));
|
k_sleep(K_SECONDS(8));
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
||||||
status = bt_mesh_subnet_kr_phase_get(0, &phase);
|
status = bt_mesh_subnet_kr_phase_get(0, &phase);
|
||||||
|
|
|
@ -201,6 +201,7 @@ static const struct bt_mesh_blob_cli_cb blob_cli_handlers = {
|
||||||
static struct bt_mesh_blob_srv blob_srv = { .cb = &blob_srv_cb };
|
static struct bt_mesh_blob_srv blob_srv = { .cb = &blob_srv_cb };
|
||||||
static struct bt_mesh_blob_cli blob_cli = { .cb = &blob_cli_handlers };
|
static struct bt_mesh_blob_cli blob_cli = { .cb = &blob_cli_handlers };
|
||||||
static struct bt_mesh_cfg_cli cfg_cli;
|
static struct bt_mesh_cfg_cli cfg_cli;
|
||||||
|
static struct bt_mesh_sar_cfg_cli sar_cfg_cli;
|
||||||
|
|
||||||
static const struct bt_mesh_comp srv_comp = {
|
static const struct bt_mesh_comp srv_comp = {
|
||||||
.elem =
|
.elem =
|
||||||
|
@ -208,6 +209,8 @@ static const struct bt_mesh_comp srv_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
|
BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
},
|
},
|
||||||
|
@ -220,6 +223,8 @@ static const struct bt_mesh_comp cli_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_BLOB_CLI(&blob_cli)),
|
BT_MESH_MODEL_BLOB_CLI(&blob_cli)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
},
|
},
|
||||||
|
@ -246,6 +251,8 @@ static const struct bt_mesh_comp none_rsp_srv_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_BLOB_SRV,
|
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_BLOB_SRV,
|
||||||
model_op1, NULL, NULL, NULL)),
|
model_op1, NULL, NULL, NULL)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
|
@ -298,6 +305,8 @@ static void blob_srv_prov_and_conf(uint16_t addr)
|
||||||
err, status);
|
err, status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_sar_conf(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blob_cli_prov_and_conf(uint16_t addr)
|
static void blob_cli_prov_and_conf(uint16_t addr)
|
||||||
|
@ -314,6 +323,8 @@ static void blob_cli_prov_and_conf(uint16_t addr)
|
||||||
status);
|
status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_sar_conf(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blob_cli_inputs_prepare(uint16_t group)
|
static void blob_cli_inputs_prepare(uint16_t group)
|
||||||
|
@ -1310,6 +1321,8 @@ static const struct bt_mesh_comp srv_broken_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
||||||
model_op2, NULL, NULL, NULL),
|
model_op2, NULL, NULL, NULL),
|
||||||
BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
|
BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
|
||||||
|
|
|
@ -45,6 +45,7 @@ static struct bt_mesh_dfu_img dfu_imgs[] = { {
|
||||||
} };
|
} };
|
||||||
|
|
||||||
static struct bt_mesh_cfg_cli cfg_cli;
|
static struct bt_mesh_cfg_cli cfg_cli;
|
||||||
|
static struct bt_mesh_sar_cfg_cli sar_cfg_cli;
|
||||||
|
|
||||||
static int dfu_targets_cnt;
|
static int dfu_targets_cnt;
|
||||||
static bool dfu_fail_confirm;
|
static bool dfu_fail_confirm;
|
||||||
|
@ -245,6 +246,8 @@ static const struct bt_mesh_comp dist_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
|
BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
},
|
},
|
||||||
|
@ -257,6 +260,8 @@ static const struct bt_mesh_comp dist_comp_self_update = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
|
BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
BT_MESH_ELEM(2,
|
BT_MESH_ELEM(2,
|
||||||
|
@ -272,6 +277,8 @@ static const struct bt_mesh_comp target_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
|
BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
},
|
},
|
||||||
|
@ -328,6 +335,7 @@ static void dist_prov_and_conf(uint16_t addr)
|
||||||
};
|
};
|
||||||
|
|
||||||
common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
|
common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
|
||||||
|
common_sar_conf(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dist_self_update_prov_and_conf(uint16_t addr)
|
static void dist_self_update_prov_and_conf(uint16_t addr)
|
||||||
|
@ -343,6 +351,7 @@ static void dist_self_update_prov_and_conf(uint16_t addr)
|
||||||
};
|
};
|
||||||
|
|
||||||
common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
|
common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
|
||||||
|
common_sar_conf(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void target_prov_and_conf(uint16_t addr, struct bind_params *params, size_t len)
|
static void target_prov_and_conf(uint16_t addr, struct bind_params *params, size_t len)
|
||||||
|
@ -352,6 +361,7 @@ static void target_prov_and_conf(uint16_t addr, struct bind_params *params, size
|
||||||
common_configure(addr);
|
common_configure(addr);
|
||||||
|
|
||||||
common_app_bind(addr, params, len);
|
common_app_bind(addr, params, len);
|
||||||
|
common_sar_conf(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void target_prov_and_conf_default(void)
|
static void target_prov_and_conf_default(void)
|
||||||
|
@ -634,6 +644,8 @@ static const struct bt_mesh_comp cli_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_DFU_CLI(&dfu_cli)),
|
BT_MESH_MODEL_DFU_CLI(&dfu_cli)),
|
||||||
BT_MESH_MODEL_NONE),
|
BT_MESH_MODEL_NONE),
|
||||||
},
|
},
|
||||||
|
@ -772,6 +784,8 @@ static const struct bt_mesh_comp srv_caps_broken_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
||||||
model_caps_op1, NULL, NULL, NULL),
|
model_caps_op1, NULL, NULL, NULL),
|
||||||
BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
|
BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
|
||||||
|
@ -802,6 +816,8 @@ static const struct bt_mesh_comp srv_update_get_broken_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
||||||
model_update_get_op1, NULL, NULL,
|
model_update_get_op1, NULL, NULL,
|
||||||
NULL),
|
NULL),
|
||||||
|
@ -833,6 +849,8 @@ static const struct bt_mesh_comp srv_update_apply_broken_comp = {
|
||||||
BT_MESH_ELEM(1,
|
BT_MESH_ELEM(1,
|
||||||
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
|
||||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||||
|
BT_MESH_MODEL_SAR_CFG_SRV,
|
||||||
|
BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
|
||||||
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
|
||||||
model_update_apply_op1, NULL,
|
model_update_apply_op1, NULL,
|
||||||
NULL, NULL),
|
NULL, NULL),
|
||||||
|
|
|
@ -269,9 +269,13 @@ static void test_friend_msg(void)
|
||||||
/* Receive a segmented message from the LPN. LPN should poll for the ack
|
/* Receive a segmented message from the LPN. LPN should poll for the ack
|
||||||
* after sending the segments.
|
* after sending the segments.
|
||||||
*/
|
*/
|
||||||
ASSERT_OK_MSG(bt_mesh_test_recv(15, cfg->addr, K_SECONDS(10)),
|
ASSERT_OK(bt_mesh_test_recv(15, cfg->addr, K_SECONDS(10)));
|
||||||
"Receive from LPN failed");
|
/* 4 polls (2 if legacy transport layer is used):
|
||||||
friend_wait_for_polls(2);
|
* - The first one triggered manually by transport when sending segmented message;
|
||||||
|
* - 2 for each SegAck (SegAcks are sent faster than Friend Poll messages);
|
||||||
|
* - The last one with MD == 0;
|
||||||
|
*/
|
||||||
|
friend_wait_for_polls(IS_ENABLED(CONFIG_BT_MESH_V1d1) ? 4 : 2);
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,57 @@ static void rx_ended(uint8_t *data, size_t len)
|
||||||
LOG_INF("Receiving succeeded");
|
LOG_INF("Receiving succeeded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tx_sar_conf(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_BT_MESH_V1d1
|
||||||
|
/* Reconfigure SAR Transmitter state so that the transport layer doesn't
|
||||||
|
* retransmit.
|
||||||
|
*/
|
||||||
|
struct bt_mesh_sar_tx tx_set = {
|
||||||
|
.seg_int_step = CONFIG_BT_MESH_SAR_TX_SEG_INT_STEP,
|
||||||
|
.unicast_retrans_count = 0,
|
||||||
|
.unicast_retrans_without_prog_count = 0,
|
||||||
|
.unicast_retrans_int_step = CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_STEP,
|
||||||
|
.unicast_retrans_int_inc = CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_INT_INC,
|
||||||
|
.multicast_retrans_count = CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_COUNT,
|
||||||
|
.multicast_retrans_int = CONFIG_BT_MESH_SAR_TX_MULTICAST_RETRANS_INT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
bt_mesh_test_sar_conf_set(&tx_set, NULL);
|
||||||
|
#else
|
||||||
|
bt_mesh.sar_tx = tx_set;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rx_sar_conf(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_BT_MESH_V1d1
|
||||||
|
/* Reconfigure SAR Receiver state so that the transport layer does
|
||||||
|
* generate Segmented Acks as rarely as possible.
|
||||||
|
*/
|
||||||
|
struct bt_mesh_sar_rx rx_set = {
|
||||||
|
.seg_thresh = 0x1f,
|
||||||
|
.ack_delay_inc = 0x7,
|
||||||
|
.discard_timeout = CONFIG_BT_MESH_SAR_RX_DISCARD_TIMEOUT,
|
||||||
|
.rx_seg_int_step = 0xf,
|
||||||
|
.ack_retrans_count = CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
bt_mesh_test_sar_conf_set(NULL, &rx_set);
|
||||||
|
#else
|
||||||
|
bt_mesh.sar_rx = rx_set;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void test_tx_immediate_replay_attack(void)
|
static void test_tx_immediate_replay_attack(void)
|
||||||
{
|
{
|
||||||
settings_test_backend_clear();
|
settings_test_backend_clear();
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
tx_sar_conf();
|
||||||
|
|
||||||
static const struct bt_mesh_send_cb send_cb = {
|
static const struct bt_mesh_send_cb send_cb = {
|
||||||
.start = tx_started,
|
.start = tx_started,
|
||||||
|
@ -129,6 +176,7 @@ static void test_rx_immediate_replay_attack(void)
|
||||||
{
|
{
|
||||||
settings_test_backend_clear();
|
settings_test_backend_clear();
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
rx_sar_conf();
|
||||||
bt_mesh_test_ra_cb_setup(rx_ended);
|
bt_mesh_test_ra_cb_setup(rx_ended);
|
||||||
|
|
||||||
k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));
|
k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));
|
||||||
|
@ -142,6 +190,7 @@ static void test_tx_power_replay_attack(void)
|
||||||
{
|
{
|
||||||
settings_test_backend_clear();
|
settings_test_backend_clear();
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
tx_sar_conf();
|
||||||
|
|
||||||
static const struct bt_mesh_send_cb send_cb = {
|
static const struct bt_mesh_send_cb send_cb = {
|
||||||
.start = tx_started,
|
.start = tx_started,
|
||||||
|
@ -185,6 +234,7 @@ static void test_tx_power_replay_attack(void)
|
||||||
static void test_rx_power_replay_attack(void)
|
static void test_rx_power_replay_attack(void)
|
||||||
{
|
{
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
rx_sar_conf();
|
||||||
bt_mesh_test_ra_cb_setup(rx_ended);
|
bt_mesh_test_ra_cb_setup(rx_ended);
|
||||||
|
|
||||||
k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));
|
k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));
|
||||||
|
|
|
@ -30,6 +30,9 @@ void assert_post_action(const char *file, unsigned int line)
|
||||||
|
|
||||||
#define GROUP_ADDR 0xc000
|
#define GROUP_ADDR 0xc000
|
||||||
#define WAIT_TIME 70 /*seconds*/
|
#define WAIT_TIME 70 /*seconds*/
|
||||||
|
#define SYNC_CHAN 0
|
||||||
|
#define CLI_DEV 0
|
||||||
|
#define SRV1_DEV 1
|
||||||
|
|
||||||
extern enum bst_result_t bst_result;
|
extern enum bst_result_t bst_result;
|
||||||
|
|
||||||
|
@ -67,6 +70,28 @@ static void async_send_end(int err, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rx_sar_conf(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_BT_MESH_V1d1
|
||||||
|
/* Reconfigure SAR Receiver state so that the transport layer does
|
||||||
|
* generate Segmented Acks as rarely as possible.
|
||||||
|
*/
|
||||||
|
struct bt_mesh_sar_rx rx_set = {
|
||||||
|
.seg_thresh = 0x1f,
|
||||||
|
.ack_delay_inc = CONFIG_BT_MESH_SAR_RX_ACK_DELAY_INC,
|
||||||
|
.discard_timeout = CONFIG_BT_MESH_SAR_RX_DISCARD_TIMEOUT,
|
||||||
|
.rx_seg_int_step = CONFIG_BT_MESH_SAR_RX_SEG_INT_STEP,
|
||||||
|
.ack_retrans_count = CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MESH_SAR_CFG)
|
||||||
|
bt_mesh_test_sar_conf_set(NULL, &rx_set);
|
||||||
|
#else
|
||||||
|
bt_mesh.sar_rx = rx_set;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static const struct bt_mesh_send_cb async_send_cb = {
|
static const struct bt_mesh_send_cb async_send_cb = {
|
||||||
.end = async_send_end,
|
.end = async_send_end,
|
||||||
};
|
};
|
||||||
|
@ -127,12 +152,20 @@ static void test_tx_va(void)
|
||||||
{
|
{
|
||||||
uint16_t virtual_addr;
|
uint16_t virtual_addr;
|
||||||
int err;
|
int err;
|
||||||
|
struct bt_mesh_test_sync_ctx sync = {
|
||||||
|
.chan_nmbr = (uint32_t[]){ SYNC_CHAN },
|
||||||
|
.dev_nmbr = (uint32_t[]){ SRV1_DEV },
|
||||||
|
.cnt = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
bt_mesh_test_sync_init(&sync);
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
|
||||||
err = bt_mesh_va_add(test_va_uuid, &virtual_addr);
|
err = bt_mesh_va_add(test_va_uuid, &virtual_addr);
|
||||||
ASSERT_OK_MSG(err, "Virtual addr add failed (err %d)", err);
|
ASSERT_OK_MSG(err, "Virtual addr add failed (err %d)", err);
|
||||||
|
|
||||||
|
ASSERT_TRUE(bt_mesh_test_sync(sync.chan_id[0], 4));
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
||||||
err = bt_mesh_test_send(virtual_addr, test_vector[i].len,
|
err = bt_mesh_test_send(virtual_addr, test_vector[i].len,
|
||||||
test_vector[i].flags, K_SECONDS(20));
|
test_vector[i].flags, K_SECONDS(20));
|
||||||
|
@ -365,6 +398,7 @@ static void test_rx_unicast(void)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
rx_sar_conf();
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
||||||
err = bt_mesh_test_recv(test_vector[i].len, cfg->addr,
|
err = bt_mesh_test_recv(test_vector[i].len, cfg->addr,
|
||||||
|
@ -404,13 +438,21 @@ static void test_rx_va(void)
|
||||||
uint16_t virtual_addr;
|
uint16_t virtual_addr;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
int err;
|
int err;
|
||||||
|
struct bt_mesh_test_sync_ctx sync = {
|
||||||
|
.chan_nmbr = (uint32_t[]){ SYNC_CHAN },
|
||||||
|
.dev_nmbr = (uint32_t[]){ CLI_DEV },
|
||||||
|
.cnt = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
bt_mesh_test_sync_init(&sync);
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
|
||||||
err = bt_mesh_cfg_cli_mod_sub_va_add(0, cfg->addr, cfg->addr, test_va_uuid,
|
err = bt_mesh_cfg_cli_mod_sub_va_add(0, cfg->addr, cfg->addr, test_va_uuid,
|
||||||
TEST_MOD_ID, &virtual_addr, &status);
|
TEST_MOD_ID, &virtual_addr, &status);
|
||||||
ASSERT_OK_MSG(err || status, "Sub add failed (err %d, status %u)", err, status);
|
ASSERT_OK_MSG(err || status, "Sub add failed (err %d, status %u)", err, status);
|
||||||
|
|
||||||
|
ASSERT_TRUE(bt_mesh_test_sync(sync.chan_id[0], 4));
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
|
||||||
err = bt_mesh_test_recv(test_vector[i].len, virtual_addr,
|
err = bt_mesh_test_recv(test_vector[i].len, virtual_addr,
|
||||||
K_SECONDS(20));
|
K_SECONDS(20));
|
||||||
|
@ -479,6 +521,7 @@ static void test_rx_seg_concurrent(void)
|
||||||
static void test_rx_seg_ivu(void)
|
static void test_rx_seg_ivu(void)
|
||||||
{
|
{
|
||||||
bt_mesh_test_setup();
|
bt_mesh_test_setup();
|
||||||
|
rx_sar_conf();
|
||||||
|
|
||||||
ASSERT_OK_MSG(bt_mesh_test_recv(255, cfg->addr, K_SECONDS(5)), "RX fail");
|
ASSERT_OK_MSG(bt_mesh_test_recv(255, cfg->addr, K_SECONDS(5)), "RX fail");
|
||||||
ASSERT_OK_MSG(bt_mesh_test_recv(255, cfg->addr, K_SECONDS(5)), "RX fail");
|
ASSERT_OK_MSG(bt_mesh_test_recv(255, cfg->addr, K_SECONDS(5)), "RX fail");
|
||||||
|
|
|
@ -51,7 +51,6 @@ CONFIG_BT_MESH_PROVISIONER=y
|
||||||
CONFIG_BT_MESH_CDB=y
|
CONFIG_BT_MESH_CDB=y
|
||||||
CONFIG_BT_MESH_CDB_NODE_COUNT=3
|
CONFIG_BT_MESH_CDB_NODE_COUNT=3
|
||||||
CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y
|
CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y
|
||||||
CONFIG_BT_MESH_TX_SEG_RETRANS_COUNT=5
|
|
||||||
CONFIG_BT_MESH_MSG_CACHE_SIZE=10
|
CONFIG_BT_MESH_MSG_CACHE_SIZE=10
|
||||||
|
|
||||||
CONFIG_BT_TINYCRYPT_ECC=y
|
CONFIG_BT_TINYCRYPT_ECC=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue