diff --git a/subsys/bluetooth/mesh/lpn.c b/subsys/bluetooth/mesh/lpn.c index 35169a6ca4c..d7cd864c930 100644 --- a/subsys/bluetooth/mesh/lpn.c +++ b/subsys/bluetooth/mesh/lpn.c @@ -279,12 +279,12 @@ static void friend_req_sent(uint16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - if (err) { - BT_ERR("Sending Friend Request failed (err %d)", err); + if (lpn->state != BT_MESH_LPN_ENABLED) { return; } - if (lpn->state == BT_MESH_LPN_DISABLED) { + if (err) { + BT_ERR("Sending Friend Request failed (err %d)", err); return; } @@ -348,6 +348,10 @@ static void req_sent(uint16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + if (lpn->state == BT_MESH_LPN_DISABLED) { + return; + } + #if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER) BT_DBG("req 0x%02x duration %u err %d state %s", lpn->sent_req, duration, err, state2str(lpn->state)); diff --git a/tests/bluetooth/bsim_bt/bsim_test_mesh/src/test_friendship.c b/tests/bluetooth/bsim_bt/bsim_test_mesh/src/test_friendship.c index 420ec6d0fa5..a629eb96dd6 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_mesh/src/test_friendship.c +++ b/tests/bluetooth/bsim_bt/bsim_test_mesh/src/test_friendship.c @@ -361,6 +361,23 @@ static void test_friend_group(void) PASS(); } + +/* Friend no-establish test functions */ + +/** Initialize as a friend and no friendships to be established. + */ +static void test_friend_no_est(void) +{ + bt_mesh_test_setup(); + bt_mesh_friend_set(BT_MESH_FEATURE_ENABLED); + + if (!evt_wait(FRIEND_ESTABLISHED, K_SECONDS(30))) { + FAIL("Friendship established unexpectedly"); + } + + PASS(); +} + /* LPN test functions */ /** Enable the LPN role, and verify that the friendship is established. @@ -815,33 +832,51 @@ static void test_other_group(void) PASS(); } -#define TEST_CASE(role, name, description) \ - { \ - .test_id = "friendship_" #role "_" #name, \ - .test_descr = description, \ - .test_post_init_f = test_##role##_init, \ - .test_tick_f = bt_mesh_test_timeout, \ - .test_main_f = test_##role##_##name, \ +/** LPN disable test. + * + * Check that toggling lpn_set() results in correct disabled state + */ +static void test_lpn_disable(void) +{ + bt_mesh_test_setup(); + + bt_mesh_lpn_set(true); + bt_mesh_lpn_set(false); + + if (!evt_wait(LPN_POLLED, K_SECONDS(30))) { + FAIL("LPN connection polled unexpectedly"); + } + + PASS(); +} + +#define TEST_CASE(role, name, description) \ + { \ + .test_id = "friendship_" #role "_" #name, .test_descr = description, \ + .test_post_init_f = test_##role##_init, .test_tick_f = bt_mesh_test_timeout, \ + .test_main_f = test_##role##_##name, \ } static const struct bst_test_instance test_connect[] = { - TEST_CASE(friend, est, "Friend: establish friendship"), - TEST_CASE(friend, est_multi, "Friend: establish multiple friendships"), - TEST_CASE(friend, msg, "Friend: message exchange"), - TEST_CASE(friend, overflow, "Friend: message queue overflow"), - TEST_CASE(friend, group, "Friend: send to group addrs"), + TEST_CASE(friend, est, "Friend: establish friendship"), + TEST_CASE(friend, est_multi, "Friend: establish multiple friendships"), + TEST_CASE(friend, msg, "Friend: message exchange"), + TEST_CASE(friend, overflow, "Friend: message queue overflow"), + TEST_CASE(friend, group, "Friend: send to group addrs"), + TEST_CASE(friend, no_est, "Friend: do not establish friendship"), - TEST_CASE(lpn, est, "LPN: establish friendship"), - TEST_CASE(lpn, msg_frnd, "LPN: message exchange with friend"), - TEST_CASE(lpn, msg_mesh, "LPN: message exchange with mesh"), - TEST_CASE(lpn, re_est, "LPN: re-establish friendship"), - TEST_CASE(lpn, poll, "LPN: poll before timeout"), - TEST_CASE(lpn, overflow, "LPN: message queue overflow"), - TEST_CASE(lpn, group, "LPN: receive on group addrs"), - TEST_CASE(lpn, loopback, "LPN: send to loopback addrs"), + TEST_CASE(lpn, est, "LPN: establish friendship"), + TEST_CASE(lpn, msg_frnd, "LPN: message exchange with friend"), + TEST_CASE(lpn, msg_mesh, "LPN: message exchange with mesh"), + TEST_CASE(lpn, re_est, "LPN: re-establish friendship"), + TEST_CASE(lpn, poll, "LPN: poll before timeout"), + TEST_CASE(lpn, overflow, "LPN: message queue overflow"), + TEST_CASE(lpn, group, "LPN: receive on group addrs"), + TEST_CASE(lpn, loopback, "LPN: send to loopback addrs"), + TEST_CASE(lpn, disable, "LPN: disable LPN"), - TEST_CASE(other, msg, "Other mesh device: message exchange"), - TEST_CASE(other, group, "Other mesh device: send to group addrs"), + TEST_CASE(other, msg, "Other mesh device: message exchange"), + TEST_CASE(other, group, "Other mesh device: send to group addrs"), BSTEST_END_MARKER }; diff --git a/tests/bluetooth/bsim_bt/bsim_test_mesh/tests_scripts/friendship/lpn_disable.sh b/tests/bluetooth/bsim_bt/bsim_test_mesh/tests_scripts/friendship/lpn_disable.sh new file mode 100755 index 00000000000..15d1b62d87b --- /dev/null +++ b/tests/bluetooth/bsim_bt/bsim_test_mesh/tests_scripts/friendship/lpn_disable.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# Copyright 2022 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Check that disabling LPN gives correct behaviour. +# +# In this test the lpn node will enable the lpn feature, and then immediatley +# disables it again. Then we check that that the lpn node is actually in a +# disabled state. This test ensures that a lpn disable call is not overwritten +# by a subsequent lpn enable call, since the enable call is associated with +# internal callback structures that might produce incorrect internal state +# of the LPN module +RunTest mesh_lpn_disable_check \ + friendship_friend_no_est \ + friendship_lpn_disable