ESP32-C6 BLE Mesh Proxy Performance Issue (Slow Mesh Forwarding)
Posted: Tue May 05, 2026 11:03 am
I am observing significant latency when using an ESP32-C6 node as a BLE Mesh GATT Proxy.
Data path under test:
Issue:
- GATT receive on ESP is fast
- Forwarding into mesh (ADV) is slow/delayed
This issue is reproducible and does NOT occur when using other nodes (e.g., Tuya light) as proxy.
--------------------------------------------------
Test Setup:
- Chip: ESP32-C6
- ESP-IDF: v5.4.1
- BLE Mesh role: Proxy enabled
- Network: Multiple mesh nodes (lights + panels)
- Phone connects via BLE Mesh Proxy
--------------------------------------------------
Observed Behavior:
Case 1: Proxy = ESP32-C6
- Phone → ESP (GATT): fast
- ESP → Mesh (ADV): slow/delayed
- Occasionally log seen:
Case 2: Proxy = Light node (non-ESP)
- Phone → Proxy: fast
- Proxy → Mesh: fast (no delay)
--------------------------------------------------
Key Observations:
1. Heap is sufficient
2. Connection interval adjusted
- Forced from default ~7.5 ms to ~100 ms
- Verified in logs (conn_int ≈ 84)
- No improvement
3. Wi-Fi disabled
- No change
4. Relay disabled
- No change
5. Custom GATT service removed
- No change
6. Network transmit reduced
- No change
--------------------------------------------------
Internal Understanding:
Proxy receives packet over GATT, then stack creates a NEW mesh packet (originating node), not relay.
Flow:
Latency appears between:
--------------------------------------------------
Instrumentation Added:
- Logged Proxy RX → confirms immediate reception
- Added logs in ble_adv.c (bt_mesh_ble_task_post)
- Monitored ADV queue behavior
- Added logs for actual ADV transmission timing
--------------------------------------------------
Suspected Root Cause:
Possible issues in one of the following:
- ADV queue saturation
- BLE Mesh task scheduling delay
- Proxy → ADV conversion inefficiency
- Stack-level scheduling differences vs vendor implementations (e.g., Tuya)
--------------------------------------------------
Questions:
1. Is this expected behavior when ESP32 acts as Proxy + originating node?
2. Are there known limitations with:
- ADV queue size?
- BLE Mesh scheduling under Proxy load?
3. Any recommended tuning for:
- ADV queue
- task priority
- proxy handling
4. Any known differences vs vendor stacks (e.g., Tuya) that explain this behavior?
--------------------------------------------------
Expected Behavior:
ESP32-C6 proxy node should forward messages into the mesh with similar latency as other nodes, without noticeable delay.
--------------------------------------------------
Summary:
- Issue isolated to Proxy → ADV path
- Not caused by:
- Wi-Fi
- Heap
- Relay
- Connection interval
- Likely related to ADV scheduling / queue / stack behavior
--------------------------------------------------
Data path under test:
Code: Select all
Phone → GATT Proxy (ESP32-C6) → Mesh (ADV)
- GATT receive on ESP is fast
- Forwarding into mesh (ADV) is slow/delayed
This issue is reproducible and does NOT occur when using other nodes (e.g., Tuya light) as proxy.
--------------------------------------------------
Test Setup:
- Chip: ESP32-C6
- ESP-IDF: v5.4.1
- BLE Mesh role: Proxy enabled
- Network: Multiple mesh nodes (lights + panels)
- Phone connects via BLE Mesh Proxy
--------------------------------------------------
Observed Behavior:
Case 1: Proxy = ESP32-C6
- Phone → ESP (GATT): fast
- ESP → Mesh (ADV): slow/delayed
- Occasionally log seen:
Code: Select all
No outbound bearer found, inbound bearer 1
- Phone → Proxy: fast
- Proxy → Mesh: fast (no delay)
--------------------------------------------------
Key Observations:
1. Heap is sufficient
Code: Select all
Free heap ~200 KB
Largest block ~170 KB
- Forced from default ~7.5 ms to ~100 ms
- Verified in logs (conn_int ≈ 84)
- No improvement
3. Wi-Fi disabled
- No change
4. Relay disabled
- No change
5. Custom GATT service removed
- No change
6. Network transmit reduced
- No change
--------------------------------------------------
Internal Understanding:
Proxy receives packet over GATT, then stack creates a NEW mesh packet (originating node), not relay.
Flow:
Code: Select all
GATT RX → Access layer → Model → Network layer → ADV enqueue → ADV TX
Code: Select all
ADV enqueue → actual ADV transmission
Instrumentation Added:
- Logged Proxy RX → confirms immediate reception
- Added logs in ble_adv.c (bt_mesh_ble_task_post)
- Monitored ADV queue behavior
- Added logs for actual ADV transmission timing
--------------------------------------------------
Suspected Root Cause:
Possible issues in one of the following:
- ADV queue saturation
- BLE Mesh task scheduling delay
- Proxy → ADV conversion inefficiency
- Stack-level scheduling differences vs vendor implementations (e.g., Tuya)
--------------------------------------------------
Questions:
1. Is this expected behavior when ESP32 acts as Proxy + originating node?
2. Are there known limitations with:
- ADV queue size?
- BLE Mesh scheduling under Proxy load?
3. Any recommended tuning for:
- ADV queue
- task priority
- proxy handling
4. Any known differences vs vendor stacks (e.g., Tuya) that explain this behavior?
--------------------------------------------------
Expected Behavior:
ESP32-C6 proxy node should forward messages into the mesh with similar latency as other nodes, without noticeable delay.
--------------------------------------------------
Summary:
- Issue isolated to Proxy → ADV path
- Not caused by:
- Wi-Fi
- Heap
- Relay
- Connection interval
- Likely related to ADV scheduling / queue / stack behavior
--------------------------------------------------