Skip to content

Commit 722028a

Browse files
silabs-borislrzr
authored andcommitted
uic: zpc: Pull request #2845: UIC-3335: Add failsafe to tx queue so it doesn't get blocked
Merge in UIC/uic from fix/UIC-3335-zpc-prevent-tx-queue-to-be-blocked to develop (cherry picked from commit ec2e855d5d7053e51f388acc15e7fc870d25807d) Forwarded: #11 Signed-off-by: Philippe Coval <philippe.coval@silabs.com>
1 parent 96fc24d commit 722028a

File tree

2 files changed

+95
-9
lines changed

2 files changed

+95
-9
lines changed

applications/zpc/components/zwave/zwave_tx/src/zwave_tx.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ sl_status_t
141141

142142
sl_log_error(LOG_TAG, "Tx Queue rejected new frame request.");
143143
tx_queue.log(true);
144+
// Add a failsafe in case the queue is getting blocked
145+
// This prevents one faulty device to block the whole queue
146+
// The subsequent frames will most likely be discarded since they timed out by now
147+
if (tx_queue.size() >= ZWAVE_TX_QUEUE_BUFFER_SIZE) {
148+
sl_log_info(
149+
LOG_TAG,
150+
"Abort transmission of first frame in queue due to full Tx Queue.");
151+
auto tx_session_id = tx_queue.first_in_queue()->zwave_tx_session_id;
152+
if (zwave_tx_process_abort_transmission(tx_session_id) != SL_STATUS_OK) {
153+
sl_log_critical(LOG_TAG,
154+
"Failed to abort transmission of tx session ID : %d.",
155+
tx_session_id);
156+
}
157+
}
144158
return SL_STATUS_FAIL;
145159
}
146160

applications/zpc/components/zwave/zwave_tx/test/zwave_tx_test.c

+81-9
Original file line numberDiff line numberDiff line change
@@ -2063,7 +2063,7 @@ void test_full_zwave_tx_queue()
20632063
(void *)&my_user_pointer,
20642064
&test_tx_session_id_2));
20652065
contiki_test_helper_run(0);
2066-
2066+
// Fill the queue
20672067
for (int i = 1; i < ZWAVE_TX_QUEUE_BUFFER_SIZE; ++i) {
20682068
TEST_ASSERT_EQUAL(SL_STATUS_OK,
20692069
zwave_tx_send_data(&test_connection_1,
@@ -2074,9 +2074,14 @@ void test_full_zwave_tx_queue()
20742074
(void *)&my_user_pointer,
20752075
&test_tx_session_id));
20762076
}
2077+
zwave_tx_session_id_t second_message_id = test_tx_session_id;
20772078

20782079
TEST_ASSERT_EQUAL(ZWAVE_TX_QUEUE_BUFFER_SIZE, zwave_tx_get_queue_size());
20792080

2081+
zwave_controller_transport_abort_send_data_ExpectAndReturn(
2082+
test_tx_session_id_2,
2083+
SL_STATUS_FAIL);
2084+
20802085
// Now there is no more queue space:
20812086
TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
20822087
zwave_tx_send_data(&test_connection_1,
@@ -2087,16 +2092,13 @@ void test_full_zwave_tx_queue()
20872092
(void *)&my_user_pointer,
20882093
&test_tx_session_id));
20892094

2090-
// Get one free slot
2091-
on_zwave_transport_send_data_complete(TRANSMIT_COMPLETE_OK,
2092-
NULL,
2093-
test_tx_session_id_2);
2094-
2095+
// Process events
20952096
contiki_test_helper_run(0);
20962097
TEST_ASSERT_EQUAL(1, send_done_count);
2097-
TEST_ASSERT_EQUAL(TRANSMIT_COMPLETE_OK, send_done_status);
2098+
TEST_ASSERT_EQUAL(TRANSMIT_COMPLETE_FAIL, send_done_status);
20982099

2099-
// Now queueing should work again:
2100+
2101+
// The first frame should be discarded no matter it's timestamp since the queue is full
21002102
TEST_ASSERT_EQUAL(SL_STATUS_OK,
21012103
zwave_tx_send_data(&test_connection_1,
21022104
sizeof(test_expected_frame_data_1),
@@ -2106,7 +2108,56 @@ void test_full_zwave_tx_queue()
21062108
(void *)&my_user_pointer,
21072109
&test_tx_session_id));
21082110

2109-
// And now we are full again:
2111+
zwave_controller_transport_abort_send_data_ExpectAndReturn(
2112+
second_message_id,
2113+
SL_STATUS_FAIL);
2114+
2115+
// Check that we only discarded one frame and that the other frames are still here
2116+
TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
2117+
zwave_tx_send_data(&test_connection_1,
2118+
sizeof(test_expected_frame_data_1),
2119+
test_expected_frame_data_1,
2120+
&test_tx_options_1,
2121+
send_data_callback,
2122+
(void *)&my_user_pointer,
2123+
&test_tx_session_id));
2124+
}
2125+
2126+
void test_full_zwave_tx_queue_with_timeouts()
2127+
{
2128+
// We do not care about interactions with the transports for this test.
2129+
zwave_controller_transport_send_data_IgnoreAndReturn(SL_STATUS_OK);
2130+
2131+
// Queue a first element:
2132+
TEST_ASSERT_EQUAL(SL_STATUS_OK,
2133+
zwave_tx_send_data(&test_connection_2,
2134+
sizeof(test_expected_frame_data_2),
2135+
test_expected_frame_data_2,
2136+
&test_tx_options_2,
2137+
send_data_callback,
2138+
(void *)&my_user_pointer,
2139+
&test_tx_session_id_2));
2140+
contiki_test_helper_run(0);
2141+
2142+
// Fill the queue with elements that will time out after 400 ms
2143+
for (int i = 1; i < ZWAVE_TX_QUEUE_BUFFER_SIZE; ++i) {
2144+
TEST_ASSERT_EQUAL(SL_STATUS_OK,
2145+
zwave_tx_send_data(&test_connection_2,
2146+
sizeof(test_expected_frame_data_2),
2147+
test_expected_frame_data_2,
2148+
&test_tx_options_2,
2149+
send_data_callback,
2150+
(void *)&my_user_pointer,
2151+
&test_tx_session_id));
2152+
}
2153+
2154+
TEST_ASSERT_EQUAL(ZWAVE_TX_QUEUE_BUFFER_SIZE, zwave_tx_get_queue_size());
2155+
2156+
zwave_controller_transport_abort_send_data_ExpectAndReturn(
2157+
test_tx_session_id_2,
2158+
SL_STATUS_FAIL);
2159+
2160+
// Now there is no more queue space:
21102161
TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
21112162
zwave_tx_send_data(&test_connection_1,
21122163
sizeof(test_expected_frame_data_1),
@@ -2115,8 +2166,29 @@ void test_full_zwave_tx_queue()
21152166
send_data_callback,
21162167
(void *)&my_user_pointer,
21172168
&test_tx_session_id));
2169+
2170+
// We advance the internal contiki clock by 1000 ms so that the Tx Queue
2171+
// discard the frames that should have timed out by now.
2172+
contiki_test_helper_run(1000);
2173+
TEST_ASSERT_EQUAL(ZWAVE_TX_QUEUE_BUFFER_SIZE, send_done_count);
2174+
TEST_ASSERT_EQUAL(TRANSMIT_COMPLETE_FAIL, send_done_status);
2175+
2176+
2177+
// We filling the queue again and check if everything works as expected
2178+
// By now the queue should be empty since all the frames should have timed out
2179+
for (int i = 1; i < ZWAVE_TX_QUEUE_BUFFER_SIZE; ++i) {
2180+
TEST_ASSERT_EQUAL(SL_STATUS_OK,
2181+
zwave_tx_send_data(&test_connection_2,
2182+
sizeof(test_expected_frame_data_2),
2183+
test_expected_frame_data_2,
2184+
&test_tx_options_2,
2185+
send_data_callback,
2186+
(void *)&my_user_pointer,
2187+
&test_tx_session_id));
2188+
}
21182189
}
21192190

2191+
21202192
void test_additional_back_off()
21212193
{
21222194
zwave_node_id_t chatty_node_id = 23;

0 commit comments

Comments
 (0)