Merge branch 'fix/netif_pbuf_after_del' into 'master'

esp_netif: retain pbuf RX free callback

Closes IDFGH-17719

See merge request espressif/esp-idf!49289
This commit is contained in:
David Čermák
2026-06-15 17:49:59 +08:00
3 changed files with 53 additions and 5 deletions
@@ -21,6 +21,9 @@ extern "C" {
* @brief Allocate custom pbuf containing pointer to a private l2-free function
*
* @note pbuf_free() will deallocate this custom pbuf and call the driver assigned free function
* @note The returned pbuf can outlive esp_netif driver configuration updates or esp_netif teardown.
* The driver handle and RX-buffer free callback captured during allocation must remain valid
* until the pbuf is freed.
*/
struct pbuf* esp_pbuf_allocate(esp_netif_t *esp_netif, void *buffer, size_t len, void *l2_buff);
+10 -5
View File
@@ -6,12 +6,12 @@
/**
* @file esp_pbuf reference
* This file handles lwip custom pbufs interfacing with esp_netif
* and the L2 free function esp_netif_free_rx_buffer()
* and L2 driver RX buffer free callbacks
*/
#include "lwip/mem.h"
#include "lwip/esp_pbuf_ref.h"
#include "esp_netif_net_stack.h"
#include "esp_netif_lwip_internal.h"
/**
* @brief Specific pbuf structure for pbufs allocated by ESP netif
@@ -20,7 +20,8 @@
typedef struct esp_custom_pbuf
{
struct pbuf_custom p;
esp_netif_t *esp_netif;
void* driver_handle;
void (*driver_free_rx_buffer)(void *h, void* buffer);
void* l2_buf;
} esp_custom_pbuf_t;
@@ -33,7 +34,9 @@ typedef struct esp_custom_pbuf
static void esp_pbuf_free(struct pbuf *pbuf)
{
esp_custom_pbuf_t* esp_pbuf = (esp_custom_pbuf_t*)pbuf;
esp_netif_free_rx_buffer(esp_pbuf->esp_netif, esp_pbuf->l2_buf);
if (esp_pbuf->driver_free_rx_buffer != NULL) {
esp_pbuf->driver_free_rx_buffer(esp_pbuf->driver_handle, esp_pbuf->l2_buf);
}
mem_free(pbuf);
}
@@ -54,7 +57,9 @@ struct pbuf* esp_pbuf_allocate(esp_netif_t *esp_netif, void *buffer, size_t len,
return NULL;
}
esp_pbuf->p.custom_free_function = esp_pbuf_free;
esp_pbuf->esp_netif = esp_netif;
/* The pbuf can outlive esp_netif driver config teardown. */
esp_pbuf->driver_handle = esp_netif->driver_handle;
esp_pbuf->driver_free_rx_buffer = esp_netif->driver_free_rx_buffer;
esp_pbuf->l2_buf = l2_buff;
p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &esp_pbuf->p, buffer, len);
if (p == NULL) {
@@ -18,6 +18,7 @@
#include "test_utils.h"
#include "memory_checks.h"
#include "lwip/netif.h"
#include "lwip/esp_pbuf_ref.h"
#include "esp_netif_test.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@@ -758,6 +759,44 @@ TEST(esp_netif, initial_mtu_config_applied)
esp_netif_destroy(n2);
}
static int s_l2_free_calls;
static void test_l2_free(void *h, void *buffer)
{
TEST_ASSERT_EQUAL_PTR((void *)0x1234, h);
TEST_ASSERT_EQUAL_PTR(&s_l2_free_calls, buffer);
++s_l2_free_calls;
}
TEST(esp_netif, pbuf_uses_allocated_rx_free_callback)
{
test_case_uses_tcpip();
esp_netif_driver_ifconfig_t driver_config = {
.handle = (void *)0x1234,
.driver_free_rx_buffer = test_l2_free,
};
esp_netif_config_t cfg = {
.base = ESP_NETIF_BASE_DEFAULT_WIFI_STA,
.driver = &driver_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
};
esp_netif_t *esp_netif = esp_netif_new(&cfg);
TEST_ASSERT_NOT_NULL(esp_netif);
uint8_t payload = 0;
s_l2_free_calls = 0;
struct pbuf *pbuf = esp_pbuf_allocate(esp_netif, &payload, sizeof(payload), &s_l2_free_calls);
TEST_ASSERT_NOT_NULL(pbuf);
esp_netif_driver_ifconfig_t empty_driver_config = { };
TEST_ESP_OK(esp_netif_set_driver_config(esp_netif, &empty_driver_config));
TEST_ASSERT_EQUAL(1, pbuf_free(pbuf));
TEST_ASSERT_EQUAL(1, s_l2_free_calls);
esp_netif_destroy(esp_netif);
}
TEST_GROUP_RUNNER(esp_netif)
{
/**
@@ -788,6 +827,7 @@ TEST_GROUP_RUNNER(esp_netif)
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_mesh)
#endif
RUN_TEST_CASE(esp_netif, initial_mtu_config_applied)
RUN_TEST_CASE(esp_netif, pbuf_uses_allocated_rx_free_callback)
RUN_TEST_CASE(esp_netif, route_priority)
RUN_TEST_CASE(esp_netif, set_get_dnsserver)
RUN_TEST_CASE(esp_netif, unified_netif_status_event)