Page 1 of 1

How is the rx buffer of a custom i/o driver using esp_netif_receive() is freed?

Posted: Thu Sep 02, 2021 2:53 pm
by ci4rail
Hi,
I'm writing a cdc ecm (Ethernet over USB) driver for the esp32s2 which is using the same esp-netif configuration as the native ethernet driver (ESP_NETIF_DEFAULT_ETH).
In the manual (https://docs.espressif.com/projects/esp ... river.html) is written:
The first two functions for transmitting and freeing the rx buffer are provided as callbacks, i.e. they get called from esp-netif (and its underlying TCP/IP stack) and I/O driver provides their implementation.
So I wrote the implementation to free the rx buffer and assigned it to the function pointer esp_netif->driver_free_rx_buffer.
Now I found that the function is never called. So I checked the native ethernet driver and it assigns NULL to esp_netif->driver_free_rx_buffer.
Now I suspect that the buffer is already freed in the lwip stack or in esp-netif. Is this correct?

Re: How is the rx buffer of a custom i/o driver using esp_netif_receive() is freed?

Posted: Thu Apr 28, 2022 9:29 am
by Daniel81
I encountered the same problem and found, that a buffer allocated and passed to

Code: Select all

esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)
will never be freed, even though you specify a driver_free_rx_buffer callback.

I found out by try and error (no documentation found), that the driver_free_rx_buffer callback
will only be called, if you pass a non-NULL argument to the 'void *eb' parameter of esp_netif_receive(...).

Passing the same buffer twice, as 'void *buffer' and 'void *eb' did the trick. Now the driver_free_rx_buffer
callback is called and you can free the buffer.

Re: How is the rx buffer of a custom i/o driver using esp_netif_receive() is freed?

Posted: Thu Apr 28, 2022 10:27 am
by ESP_ondrej
Daniel81 wrote: I encountered the same problem and found, that a buffer allocated and passed to
CODE: SELECT ALL

esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)
You probably found this in `esp_netif_loopback.c`, am I right? This piece of code is not used on target, it is used for test purposes.

The true is though, the Ethernet `esp_netif->driver_free_rx_buffer` is currently not used. Buffers coming from Ethernet driver are simply freed by direct call of `free` by `static void ethernet_free_rx_buf_l2(struct netif *netif, void *buf)` function in `ethernetif.c`.

To use `esp_netif->driver_free_rx_buffer` for Ethernet, you could probably update `ethernet_free_rx_buf_l2` as follows (similar to `wlanif.c`):

Code: Select all

static void ethernet_free_rx_buf_l2(struct netif *netif, void *buf)
{
    esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
    esp_netif_free_rx_buffer(esp_netif, buf);
}

Re: How is the rx buffer of a custom i/o driver using esp_netif_receive() is freed?

Posted: Fri Aug 12, 2022 7:31 pm
by witek117
@ci4rail did you succeed in writing a CDC-ECM (Ethernet over USB) driver for the esp32s2?