mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(mbedtls): Add configuration to control dynamic buffer strategy in mbedtls
Problem: 1. In low-memory scenarios, the dynamic buffer feature can fail due to memory fragmentation. 2. It requires a contiguous 16KB heap chunk, but continuous allocation and deallocation of the RX buffer can lead to fragmentation. 3. If another component allocates memory between these operations, it can break up the available 16KB block, causing allocation failure. Solution: 1. Introduce configurable strategy for using dynamic buffers in TLS connections. 2. For example, convert RX buffers to static after the TLS handshake. 3. Allow users to select the strategy via a new field in the esp_http_client_cfg_t structure. 4. The strategy can be controlled independently for each TLS session.
This commit is contained in:
@@ -51,4 +51,13 @@ menu "Example Configuration"
|
||||
help
|
||||
Select ethernet interface to pass the OTA data.
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_TLS_DYN_BUF_RX_STATIC
|
||||
bool "Use static rx buffer for dynamic buffer after TLS handshake"
|
||||
depends on MBEDTLS_DYNAMIC_BUFFER
|
||||
default n
|
||||
help
|
||||
This converts the dynamic RX buffer to static allocation after the TLS handshake
|
||||
is complete. This reduces memory fragmentation by avoiding repeated dynamic
|
||||
allocations during data transfer.
|
||||
endmenu
|
||||
|
||||
@@ -101,6 +101,12 @@ void simple_ota_example_task(void *pvParameter)
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
.if_name = &ifr,
|
||||
#endif
|
||||
#if CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC
|
||||
/* This part applies static buffer strategy for rx dynamic buffer.
|
||||
* This is to avoid frequent allocation and deallocation of dynamic buffer.
|
||||
*/
|
||||
.tls_dyn_buf_strategy = HTTP_TLS_DYN_BUF_RX_STATIC,
|
||||
#endif /* CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import http.server
|
||||
import multiprocessing
|
||||
@@ -6,6 +6,7 @@ import os
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Any
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
||||
@@ -13,6 +14,7 @@ import pexpect
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
try:
|
||||
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
|
||||
except ModuleNotFoundError:
|
||||
@@ -130,6 +132,20 @@ def calc_all_sha256(dut: Dut) -> Tuple[str, str]:
|
||||
return str(sha256_bootloader), str(sha256_app)
|
||||
|
||||
|
||||
def setting_connection(dut: Dut, env_name: Optional[str] = None) -> Any:
|
||||
if env_name is not None and dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
|
||||
dut.expect('Please input ssid password:')
|
||||
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
|
||||
ap_password = get_env_config_variable(env_name, 'ap_password')
|
||||
dut.write(f'{ap_ssid} {ap_password}')
|
||||
try:
|
||||
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
|
||||
print(f'Connected to AP/Ethernet with IP: {ip_address}')
|
||||
except pexpect.exceptions.TIMEOUT:
|
||||
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
|
||||
return get_host_ip4_by_dest_ip(ip_address)
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32s3
|
||||
@@ -387,6 +403,39 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None:
|
||||
tls1_3_server.kill()
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.ethernet_ota
|
||||
@pytest.mark.parametrize('config', ['tls1_2_dynamic',], indirect=True)
|
||||
def test_examples_protocol_simple_ota_example_tls1_2_dynamic(dut: Dut) -> None:
|
||||
"""
|
||||
steps: |
|
||||
1. join AP/Ethernet
|
||||
2. Fetch OTA image over HTTPS
|
||||
3. Reboot with the new OTA image
|
||||
"""
|
||||
sha256_bootloader, sha256_app = calc_all_sha256(dut)
|
||||
# Start server
|
||||
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8001))
|
||||
thread1.daemon = True
|
||||
thread1.start()
|
||||
try:
|
||||
# start test
|
||||
dut.expect(f'Loaded app from partition at offset 0x10000', timeout=30)
|
||||
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||
|
||||
host_ip = setting_connection(dut)
|
||||
|
||||
dut.expect('Starting OTA example task', timeout=30)
|
||||
dut.write(f'https://{host_ip}:8001/simple_ota.bin')
|
||||
dut.expect('OTA Succeed, Rebooting...', timeout=120)
|
||||
# after reboot
|
||||
dut.expect(f'Loaded app from partition at offset 0x110000', timeout=30)
|
||||
dut.expect('OTA example app_main start', timeout=10)
|
||||
finally:
|
||||
thread1.terminate()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[2:]: # if two or more arguments provided:
|
||||
# Usage: pytest_simple_ota.py <image_dir> <server_port> [cert_di>]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
|
||||
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC=y
|
||||
Reference in New Issue
Block a user