feat(esp_eth): consume Rx checksum offload engine verdict; expose lwIP checksum Kconfig (IDFGH-18027)#18883
Open
DatanoiseTV wants to merge 2 commits into
Open
Conversation
The EMAC Rx checksum offload engine is enabled unconditionally (emac_hal_init_mac_default), but its verdict was never consumed: the DMA cannot drop erroneous frames in hardware because that requires Receive Store Forward, and the Rx FIFO is smaller than a full frame on most targets (verified on ESP32-S31: with store-and-forward enabled, full-size frames are never forwarded to memory). Consume the engine's per-frame verdict from the enhanced descriptor extended status (IPHeadErr/IPPayloadErr, qualified by IPChecksumBypass) in the Rx path and drop bad frames there. This lets the network stack rely on hardware-verified IP/TCP/UDP/ICMP checksums; with lwIP's software TCP receive checksum disabled, TCP Rx throughput on ESP32-S31 at 1000M improves from 160 to 186 Mbit/s (iperf2, wired peer, 320 MHz single core). Also document why Tx checksum insertion (TDES0.CIC) cannot be used: it requires Tx store-and-forward, which stops all transmission on ESP32-S31 (Tx FIFO smaller than a full frame); in threshold mode CIC is ignored and frames leave with a zeroed IP header checksum (verified on the wire).
Add LWIP_CHECKSUM_CHECK_TCP and LWIP_CHECKSUM_GEN_IP/UDP/TCP/ICMP options (all defaulting to the current behavior). Disabling the TCP receive check is useful when the network interface hardware verifies checksums and drops corrupted frames, e.g. the internal EMAC checksum offload engine on ESP32-S31; the generation options prepare for interfaces with transmit checksum insertion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The internal EMAC's Rx checksum offload engine is enabled unconditionally in
emac_hal_init_mac_default()(emac_ll_checksum_offload_mode(hal->mac_regs, ETH_CHECKSUM_HW)), but its result is never consumed:emac_ll_drop_tcp_err_frame_enable) only takes effect in Receive Store Forward mode. RSF is disabled on all targets except the original ESP32 because the Rx FIFO is smaller than a full frame - verified on ESP32-S31: with RSF force-enabled, frames larger than the FIFO are never forwarded to memory at all.IPHeadErr,IPPayloadErr, qualified byIPChecksumBypass) - but the DMA driver only checksRDES0.ErrSummary, which does not include the checksum engine bits.Consequences:
CONFIG_LWIP_CHECKSUM_CHECK_UDPdisabled (the IDF default), corrupted UDP datagrams that pass the Ethernet CRC are silently delivered to the application.Changes
Commit 1 - esp_eth: consume the checksum engine verdict in
emac_esp_dma_get_valid_recv_len(): when extended status is available and the engine was not bypassed, drop frames flagged withIPHeadErrorIPPayloadErr, the same wayErrSummaryframes are dropped. Non-IP frames, IPv6 frames with unsupported extension headers, and zero-checksum UDP are reported as bypass by the engine and are unaffected. Comments inemac_hal.cdocument the store-forward constraints (including why Tx checksum insertion via TDES0.CIC cannot work: it requires Tx store-and-forward, which stalls all transmission on ESP32-S31, and in threshold mode CIC is ignored - frames leave with a zeroed IP header checksum, verified with tcpdump on the link partner).Commit 2 - lwip: expose
LWIP_CHECKSUM_CHECK_TCPandLWIP_CHECKSUM_GEN_IP/UDP/TCP/ICMPin Kconfig (all defaulting to current behavior). With commit 1, disabling the TCP receive check on an internal-EMAC-only system is safe and removes redundant per-segment software checksumming.Measurements (ESP32-S31 @ 320 MHz, RGMII gigabit link, wired iperf2 peer, 0.1 ms RTT)
LWIP_CHECKSUM_CHECK_TCP=n: 160 -> 186 Mbit/s (+16 %).CHECKSUM_CHECK_UDP=n.Precedent
The same Synopsys DWMAC IP in the Linux
stmmacdriver handles this identically in spirit: Rx frames flagged by the checksum engine must not be treated as verified (CVE-2025-40337, fixed in commit 63fbe0e64132 by routing flagged frames to software re-validation; lwIP has no per-packet re-validation path, so dropping - the same policy the hardware applies in store-forward mode - is the equivalent). The Tx-side FIFO constraint is also known there: boards with Tx FIFO smaller than the frame size disable Tx checksum offload and fall back to software checksums.Testing
examples/ethernet/basicfor esp32 and esp32p4; full application build for esp32s31.Note
Medium Risk
Changes Ethernet receive filtering and optional lwIP checksum behavior—misconfiguration (disabling software checks without hardware validation) could admit corrupted traffic; defaults and EMAC-only guidance mitigate this.
Overview
Internal EMAC Rx path now drops frames the hardware checksum engine flags as bad. In
emac_esp_dma_get_valid_recv_len(), when enhanced Rx descriptor status is present and the engine did not bypass verification, frames withIPHeadErrorIPPayloadErrare flushed likeErrSummaryframes—so lwIP can trust hardware-checked IP/TCP/UDP/ICMP on cut-through targets where Receive Store Forward stays off.emac_hal.ccomments document why RSF and Tx store-and-forward stay disabled (small FIFOs; full-frame Tx offload not viable on ESP32-S31).lwIP gains Kconfig toggles for TCP receive checksum checking and software generation of IP/UDP/TCP/ICMP checksums (
lwipopts.hmaps them toCHECKSUM_*). Defaults preserve current behavior; with the DMA change, disabling redundant TCP Rx checks on internal-EMAC-only builds is documented as safe.Reviewed by Cursor Bugbot for commit 5fd2584. Bugbot is set up for automated code reviews on this repo. Configure here.