Skip to content

Commit 31ba50d

Browse files
simensrostadjorgenmk
authored andcommitted
net: lib: fota_download: add ENETDOWN to retryable errors
Add `-ENETDOWN` to the list of socket errors that trigger automatic retry in the FOTA download client. This error indicates the network is down and is recoverable, similar to `-ECONNRESET` and `-EAGAIN`. Update the downloader callback to retry on `-ENETDOWN` errors when retries are available. Signed-off-by: Simen S. Røstad <simen.rostad@nordicsemi.no>
1 parent 0cec693 commit 31ba50d

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

subsys/net/lib/fota_download/src/fota_download.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,9 @@ static int downloader_callback(const struct downloader_evt *event)
302302
* or non-zero to stop
303303
*/
304304
if ((socket_retries_left)
305-
&& ((event->error == -ECONNRESET) || (event->error == -EAGAIN))) {
305+
&& ((event->error == -ECONNRESET) ||
306+
(event->error == -EAGAIN) ||
307+
(event->error == -ENETDOWN))) {
306308
LOG_WRN("Download socket error. %d retries left...",
307309
socket_retries_left);
308310
socket_retries_left--;

tests/subsys/net/lib/fota_download/src/test_fota_download.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <string.h>
88
#include <zephyr/types.h>
99
#include <stdbool.h>
10+
#include <errno.h>
1011
#include <zephyr/ztest.h>
1112
#include <downloader.h>
1213
#include <fw_info.h>
@@ -85,6 +86,7 @@ int dfu_target_schedule_update(int img_num)
8586

8687
int downloader_file_size_get(struct downloader *client, size_t *size)
8788
{
89+
*size = 4096;
8890
return 0;
8991
}
9092

@@ -429,6 +431,63 @@ ZTEST(fota_download_tests, test_download_with_offset)
429431
zassert_equal(err, -EAGAIN);
430432
}
431433

434+
ZTEST(fota_download_tests, test_socket_retries)
435+
{
436+
int err;
437+
int retryable_errors[] = {-ECONNRESET, -EAGAIN, -ENETDOWN};
438+
439+
for (int i = 0; i < ARRAY_SIZE(retryable_errors); i++) {
440+
/* Init */
441+
init();
442+
443+
uint8_t fragment_buf[1] = {0};
444+
size_t fragment_len = 1;
445+
const struct downloader_evt fragment_evt = {
446+
.id = DOWNLOADER_EVT_FRAGMENT,
447+
.fragment = {
448+
.buf = fragment_buf,
449+
.len = fragment_len,
450+
}
451+
};
452+
const struct downloader_evt error_evt = {
453+
.id = DOWNLOADER_EVT_ERROR,
454+
.error = retryable_errors[i],
455+
};
456+
const struct downloader_evt stopped_evt = {
457+
.id = DOWNLOADER_EVT_STOPPED,
458+
};
459+
460+
/* Start download */
461+
err = fota_download_any(BASE_DOMAIN, buf, NO_TLS, 0, 0, 0);
462+
zassert_ok(err, NULL);
463+
464+
/* Send first fragment to initialize DFU target */
465+
err = downloader_event_handler(&fragment_evt);
466+
zassert_ok(err, NULL);
467+
468+
/* Verify that error triggers retry (returns 0) when retries are left.
469+
* CONFIG_FOTA_SOCKET_RETRIES is set to 2 in test configuration.
470+
*/
471+
err = downloader_event_handler(&error_evt);
472+
zassert_equal(err, 0, "Expected retry on first error %d", retryable_errors[i]);
473+
474+
err = downloader_event_handler(&error_evt);
475+
zassert_equal(err, 0, "Expected retry on second error %d", retryable_errors[i]);
476+
477+
/* Third error should fail as retries are exhausted */
478+
err = downloader_event_handler(&error_evt);
479+
zassert_equal(err, -1, "Expected failure when retries exhausted for error %d",
480+
retryable_errors[i]);
481+
482+
/* Simulate the DOWNLOADER_EVT_STOPPED that the real downloader
483+
* would send after callback returns -1
484+
*/
485+
err = downloader_event_handler(&stopped_evt);
486+
zassert_ok(err, NULL);
487+
488+
k_sem_take(&stop_sem, K_FOREVER);
489+
}
490+
}
432491

433492
ZTEST(fota_download_tests, test_download_invalid_protocol)
434493
{

0 commit comments

Comments
 (0)