mirror of
https://github.com/esphome/esphome.git
synced 2026-08-23 22:56:19 +00:00
[network] Add tcp_send_buffer option
This commit is contained in:
@@ -26,6 +26,15 @@ _LOGGER = logging.getLogger(__name__)
|
||||
# Components can request high performance networking and this configures lwip and WiFi settings
|
||||
KEY_HIGH_PERFORMANCE_NETWORKING = "high_performance_networking"
|
||||
CONF_ENABLE_HIGH_PERFORMANCE = "enable_high_performance"
|
||||
CONF_TCP_SEND_BUFFER = "tcp_send_buffer"
|
||||
|
||||
# lwIP queues at most this many unsent/unacked bytes per TCP socket; the
|
||||
# stock ESP-IDF default (5744 bytes) stalls bursty senders like a Bluetooth
|
||||
# proxy streaming GATT notifications. Bounds follow the lwIP guidance for the
|
||||
# default 1440 byte MSS: at least 2 x MSS, at most 65535 without window
|
||||
# scaling.
|
||||
TCP_SEND_BUFFER_MIN = 2880
|
||||
TCP_SEND_BUFFER_MAX = 65535
|
||||
|
||||
# Network priority tracking infrastructure
|
||||
# Components can query this to determine their relative setup priority.
|
||||
@@ -306,6 +315,11 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Optional(CONF_ENABLE_HIGH_PERFORMANCE): cv.All(
|
||||
cv.boolean, cv.only_on_esp32
|
||||
),
|
||||
cv.Optional(CONF_TCP_SEND_BUFFER): cv.All(
|
||||
cv.validate_bytes,
|
||||
cv.int_range(min=TCP_SEND_BUFFER_MIN, max=TCP_SEND_BUFFER_MAX),
|
||||
cv.only_on_esp32,
|
||||
),
|
||||
cv.Optional(CONF_PRIORITY): _validate_priority_list,
|
||||
}
|
||||
),
|
||||
@@ -446,6 +460,11 @@ async def to_code(config):
|
||||
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RECVMBOX_SIZE", 64)
|
||||
add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 64)
|
||||
|
||||
# After the high performance block so an explicit size wins over the
|
||||
# bundle's 65534 (last write wins in the sdkconfig store).
|
||||
if (tcp_send_buffer := config.get(CONF_TCP_SEND_BUFFER)) is not None:
|
||||
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT", tcp_send_buffer)
|
||||
|
||||
if CORE.is_nrf52:
|
||||
zephyr_add_prj_conf("NETWORKING", True)
|
||||
zephyr_add_prj_conf("NET_IPV6", True)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
wifi:
|
||||
ssid: "test_ssid"
|
||||
password: "test_password"
|
||||
|
||||
network:
|
||||
tcp_send_buffer: 32kB
|
||||
@@ -0,0 +1,15 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
wifi:
|
||||
ssid: "test_ssid"
|
||||
password: "test_password"
|
||||
|
||||
network:
|
||||
enable_high_performance: true
|
||||
tcp_send_buffer: 16384
|
||||
@@ -0,0 +1,66 @@
|
||||
"""Tests for the ``network: tcp_send_buffer:`` option.
|
||||
|
||||
The option sets lwIP's per-socket TCP send buffer
|
||||
(CONFIG_LWIP_TCP_SND_BUF_DEFAULT) on ESP-IDF. The stock default (5744 bytes)
|
||||
stalls bursty senders such as a Bluetooth proxy streaming GATT notifications;
|
||||
until now the only way to raise it was the all-or-nothing
|
||||
``enable_high_performance`` bundle.
|
||||
"""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from voluptuous import Invalid
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.esp32.const import KEY_VARIANT, VARIANT_ESP32
|
||||
from esphome.components.network import CONFIG_SCHEMA
|
||||
from esphome.const import KEY_FRAMEWORK_VERSION, PlatformFramework
|
||||
from esphome.core import CORE
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def _sdkconfig_option(name: str) -> int | None:
|
||||
from esphome.components.esp32.const import KEY_ESP32, KEY_SDKCONFIG_OPTIONS
|
||||
|
||||
return CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS].get(name)
|
||||
|
||||
|
||||
def test_tcp_send_buffer_sets_sdkconfig(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
generate_main(component_config_path("tcp_send_buffer.yaml"))
|
||||
assert _sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT") == 32000
|
||||
|
||||
|
||||
def test_tcp_send_buffer_overrides_high_performance(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
"""An explicit size wins over the high performance bundle's 65534."""
|
||||
generate_main(component_config_path("tcp_send_buffer_high_perf.yaml"))
|
||||
assert _sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT") == 16384
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", ["1kB", "128kB"])
|
||||
def test_out_of_range_rejected(
|
||||
set_core_config: SetCoreConfigCallable, value: str
|
||||
) -> None:
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
core_data={KEY_FRAMEWORK_VERSION: cv.Version(5, 5, 5)},
|
||||
platform_data={KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
with pytest.raises(Invalid):
|
||||
CONFIG_SCHEMA({"tcp_send_buffer": value})
|
||||
|
||||
|
||||
def test_rejected_on_esp8266(set_core_config: SetCoreConfigCallable) -> None:
|
||||
set_core_config(
|
||||
PlatformFramework.ESP8266_ARDUINO,
|
||||
core_data={KEY_FRAMEWORK_VERSION: cv.Version(3, 1, 2)},
|
||||
)
|
||||
with pytest.raises(Invalid, match="esp32"):
|
||||
CONFIG_SCHEMA({"tcp_send_buffer": "32kB"})
|
||||
@@ -0,0 +1,6 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
network:
|
||||
tcp_send_buffer: 32kB
|
||||
Reference in New Issue
Block a user