mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-13 02:37:21 +00:00
lwip: Use custom pbufs for eth and wifi port/netif
This commit is contained in:
@@ -86,7 +86,8 @@ set(srcs
|
|||||||
"port/esp32/debug/lwip_debug.c"
|
"port/esp32/debug/lwip_debug.c"
|
||||||
"port/esp32/freertos/sys_arch.c"
|
"port/esp32/freertos/sys_arch.c"
|
||||||
"port/esp32/sockets_ext.c"
|
"port/esp32/sockets_ext.c"
|
||||||
"port/esp32/netif/wlanif.c")
|
"port/esp32/netif/wlanif.c"
|
||||||
|
"port/esp32/netif/esp_pbuf_ref.c")
|
||||||
|
|
||||||
if(CONFIG_LWIP_PPP_SUPPORT)
|
if(CONFIG_LWIP_PPP_SUPPORT)
|
||||||
list(APPEND srcs
|
list(APPEND srcs
|
||||||
|
|||||||
@@ -1365,7 +1365,7 @@
|
|||||||
#define ESP_LWIP_SELECT 1
|
#define ESP_LWIP_SELECT 1
|
||||||
#define ESP_LWIP_LOCK 1
|
#define ESP_LWIP_LOCK 1
|
||||||
#define ESP_THREAD_PROTECTION 1
|
#define ESP_THREAD_PROTECTION 1
|
||||||
#define ESP_IP_FORWARD 1
|
#define LWIP_SUPPORT_CUSTOM_PBUF 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|||||||
32
components/lwip/port/esp32/include/netif/esp_pbuf_ref.h
Normal file
32
components/lwip/port/esp32/include/netif/esp_pbuf_ref.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file esp_pbuf reference interface file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LWIP_ESP_PBUF_REF_H__
|
||||||
|
#define __LWIP_ESP_PBUF_REF_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
struct pbuf* esp_pbuf_allocate(esp_netif_t *esp_netif, void *buffer, size_t len, void *l2_buff);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //__LWIP_ESP_PBUF_REF_H__
|
||||||
58
components/lwip/port/esp32/netif/esp_pbuf_ref.c
Normal file
58
components/lwip/port/esp32/netif/esp_pbuf_ref.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file esp_pbuf reference
|
||||||
|
* This file handles lwip custom pbufs interfacing with esp_netif
|
||||||
|
* and the L2 free function esp_netif_free_rx_buffer()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "netif/esp_pbuf_ref.h"
|
||||||
|
#include "esp_netif_net_stack.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specific pbuf structure for pbufs allocated by ESP netif
|
||||||
|
* of PBUF_REF type
|
||||||
|
*/
|
||||||
|
typedef struct esp_custom_pbuf
|
||||||
|
{
|
||||||
|
struct pbuf_custom p;
|
||||||
|
esp_netif_t *esp_netif;
|
||||||
|
void* l2_buf;
|
||||||
|
} esp_custom_pbuf_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free custom pbuf containing the L2 layer buffer allocated in the driver
|
||||||
|
*
|
||||||
|
* @param pbuf Custom pbuf holding the packet passed to lwip input
|
||||||
|
* @note This function called as a custom_free_function() upon pbuf_free()
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
mem_free(pbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct pbuf* esp_pbuf_allocate(esp_netif_t *esp_netif, void *buffer, size_t len, void *l2_buff)
|
||||||
|
{
|
||||||
|
struct pbuf *p;
|
||||||
|
|
||||||
|
esp_custom_pbuf_t* esp_pbuf = mem_malloc(sizeof(esp_custom_pbuf_t));
|
||||||
|
if (esp_pbuf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
esp_pbuf->p.custom_free_function = esp_pbuf_free;
|
||||||
|
esp_pbuf->esp_netif = esp_netif;
|
||||||
|
esp_pbuf->l2_buf = l2_buff;
|
||||||
|
p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &esp_pbuf->p, buffer, len);
|
||||||
|
if (p == NULL) {
|
||||||
|
mem_free(esp_pbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
@@ -52,22 +52,12 @@
|
|||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "esp_netif_net_stack.h"
|
#include "esp_netif_net_stack.h"
|
||||||
#include "esp_compiler.h"
|
#include "esp_compiler.h"
|
||||||
|
#include "netif/esp_pbuf_ref.h"
|
||||||
|
|
||||||
/* Define those to better describe your network interface. */
|
/* Define those to better describe your network interface. */
|
||||||
#define IFNAME0 'e'
|
#define IFNAME0 'e'
|
||||||
#define IFNAME1 'n'
|
#define IFNAME1 'n'
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free resources allocated in L2 layer
|
|
||||||
*
|
|
||||||
* @param buf memory alloc in L2 layer
|
|
||||||
* @note this function is also the callback when invoke pbuf_free
|
|
||||||
*/
|
|
||||||
static void ethernet_free_rx_buf_l2(struct netif *netif, void *buf)
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this function, the hardware should be initialized.
|
* In this function, the hardware should be initialized.
|
||||||
* Invoked by ethernetif_init().
|
* Invoked by ethernetif_init().
|
||||||
@@ -120,11 +110,6 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
||||||
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
#if ESP_LWIP
|
|
||||||
/* This pbuf RAM was not allocated on layer2, no extra free operation needed in pbuf_free */
|
|
||||||
q->l2_owner = NULL;
|
|
||||||
q->l2_buf = NULL;
|
|
||||||
#endif
|
|
||||||
pbuf_copy(q, p);
|
pbuf_copy(q, p);
|
||||||
} else {
|
} else {
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
@@ -149,33 +134,30 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
* interface. Then the type of the received packet is determined and
|
* interface. Then the type of the received packet is determined and
|
||||||
* the appropriate input function is called.
|
* the appropriate input function is called.
|
||||||
*
|
*
|
||||||
* @param netif lwip network interface structure for this ethernetif
|
* @param h lwip network interface structure (struct netif) for this ethernetif
|
||||||
* @param buffer ethernet buffer
|
* @param buffer ethernet buffer
|
||||||
* @param len length of buffer
|
* @param len length of buffer
|
||||||
|
* @param l2_buff Placeholder for a separate L2 buffer. Unused for ethernet interface
|
||||||
*/
|
*/
|
||||||
void ethernetif_input(void *h, void *buffer, size_t len, void *eb)
|
void ethernetif_input(void *h, void *buffer, size_t len, void *l2_buff)
|
||||||
{
|
{
|
||||||
struct netif *netif = h;
|
struct netif *netif = h;
|
||||||
|
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
|
|
||||||
if (unlikely(buffer == NULL || !netif_is_up(netif))) {
|
if (unlikely(buffer == NULL || !netif_is_up(netif))) {
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
ethernet_free_rx_buf_l2(netif, buffer);
|
esp_netif_free_rx_buffer(esp_netif, buffer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* acquire new pbuf, type: PBUF_REF */
|
/* allocate custom pbuf to hold */
|
||||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
|
p = esp_pbuf_allocate(esp_netif, buffer, len, buffer);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
ethernet_free_rx_buf_l2(netif, buffer);
|
esp_netif_free_rx_buffer(esp_netif, buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p->payload = buffer;
|
|
||||||
#if ESP_LWIP
|
|
||||||
p->l2_owner = netif;
|
|
||||||
p->l2_buf = buffer;
|
|
||||||
#endif
|
|
||||||
/* full packet send to tcpip_thread to process */
|
/* full packet send to tcpip_thread to process */
|
||||||
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||||
@@ -228,7 +210,6 @@ err_t ethernetif_init(struct netif *netif)
|
|||||||
netif->output_ip6 = ethip6_output;
|
netif->output_ip6 = ethip6_output;
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
netif->linkoutput = ethernet_low_level_output;
|
netif->linkoutput = ethernet_low_level_output;
|
||||||
netif->l2_buffer_free_notify = ethernet_free_rx_buf_l2;
|
|
||||||
|
|
||||||
ethernet_low_level_init(netif);
|
ethernet_low_level_init(netif);
|
||||||
|
|
||||||
|
|||||||
@@ -37,11 +37,6 @@ static err_t openthread_output_ip6(struct netif *netif, struct pbuf *p, const st
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
||||||
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
#if ESP_LWIP
|
|
||||||
/* This pbuf RAM was not allocated on layer2, no extra free operation needed in pbuf_free */
|
|
||||||
q->l2_owner = NULL;
|
|
||||||
q->l2_buf = NULL;
|
|
||||||
#endif
|
|
||||||
pbuf_copy(q, p);
|
pbuf_copy(q, p);
|
||||||
} else {
|
} else {
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
@@ -84,10 +79,6 @@ void openthread_netif_input(void *h, void *buffer, size_t len, void *eb)
|
|||||||
LWIP_DEBUGF(NETIF_DEBUG, ("Failed to read OpenThread message\n"));
|
LWIP_DEBUGF(NETIF_DEBUG, ("Failed to read OpenThread message\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_LWIP
|
|
||||||
p->l2_owner = NULL;
|
|
||||||
p->l2_buf = NULL;
|
|
||||||
#endif
|
|
||||||
/* full packet send to tcpip_thread to process */
|
/* full packet send to tcpip_thread to process */
|
||||||
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("openthread_netif_input: IP input error\n"));
|
LWIP_DEBUGF(NETIF_DEBUG, ("openthread_netif_input: IP input error\n"));
|
||||||
@@ -135,7 +126,6 @@ err_t openthread_netif_init(struct netif *netif)
|
|||||||
netif->output = NULL;
|
netif->output = NULL;
|
||||||
netif->output_ip6 = openthread_output_ip6;
|
netif->output_ip6 = openthread_output_ip6;
|
||||||
netif->mld_mac_filter = openthread_netif_multicast_handler;
|
netif->mld_mac_filter = openthread_netif_multicast_handler;
|
||||||
netif->l2_buffer_free_notify = NULL;
|
|
||||||
netif_set_link_up(netif);
|
netif_set_link_up(netif);
|
||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Ethernet Interface Skeleton
|
* Ethernet Interface Skeleton used for WiFi
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -53,27 +53,14 @@
|
|||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "esp_netif_net_stack.h"
|
#include "esp_netif_net_stack.h"
|
||||||
#include "esp_compiler.h"
|
#include "esp_compiler.h"
|
||||||
|
#include "netif/esp_pbuf_ref.h"
|
||||||
#ifndef CONFIG_LWIP_L2_TO_L3_COPY
|
|
||||||
/**
|
|
||||||
* @brief Free resources allocated in L2 layer
|
|
||||||
*
|
|
||||||
* @param buf memory alloc in L2 layer
|
|
||||||
* @note this function is also the callback when invoke pbuf_free
|
|
||||||
*/
|
|
||||||
static void lwip_netif_wifi_free_rx_buffer(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);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this function, the hardware should be initialized.
|
* In this function, the hardware should be initialized.
|
||||||
* Called from ethernetif_init().
|
* Called from wlanif_input().
|
||||||
*
|
*
|
||||||
* @param netif the already initialized lwip network interface structure
|
* @param netif the already initialized lwip network interface structure
|
||||||
* for this ethernetif
|
* for this wlanif
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
low_level_init(struct netif *netif)
|
low_level_init(struct netif *netif)
|
||||||
@@ -102,9 +89,6 @@ low_level_init(struct netif *netif)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_LWIP_L2_TO_L3_COPY
|
|
||||||
netif->l2_buffer_free_notify = lwip_netif_wifi_free_rx_buffer;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,14 +96,14 @@ low_level_init(struct netif *netif)
|
|||||||
* contained in the pbuf that is passed to the function. This pbuf
|
* contained in the pbuf that is passed to the function. This pbuf
|
||||||
* might be chained.
|
* might be chained.
|
||||||
*
|
*
|
||||||
* @param netif the lwip network interface structure for this ethernetif
|
* @param netif the lwip network interface structure for this wlanif
|
||||||
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
||||||
* @return ERR_OK if the packet could be sent
|
* @return ERR_OK if the packet could be sent
|
||||||
* an err_t value if the packet couldn't be sent
|
* an err_t value if the packet couldn't be sent
|
||||||
*
|
*
|
||||||
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
||||||
* strange results. You might consider waiting for space in the DMA queue
|
* strange results. You might consider waiting for space in the DMA queue
|
||||||
* to become availale since the stack doesn't retry to send a packet
|
* to become available since the stack doesn't retry to send a packet
|
||||||
* dropped because of memory failure (except for the TCP timers).
|
* dropped because of memory failure (except for the TCP timers).
|
||||||
*/
|
*/
|
||||||
static err_t
|
static err_t
|
||||||
@@ -140,7 +124,6 @@ low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
||||||
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
q->l2_owner = NULL;
|
|
||||||
pbuf_copy(q, p);
|
pbuf_copy(q, p);
|
||||||
} else {
|
} else {
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
@@ -168,18 +151,21 @@ low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
* interface. Then the type of the received packet is determined and
|
* interface. Then the type of the received packet is determined and
|
||||||
* the appropriate input function is called.
|
* the appropriate input function is called.
|
||||||
*
|
*
|
||||||
* @param netif the lwip network interface structure for this ethernetif
|
* @param h lwip network interface structure (struct netif) for this ethernetif
|
||||||
|
* @param buffer wlan buffer
|
||||||
|
* @param len length of buffer
|
||||||
|
* @param l2_buff wlan's L2 buffer pointer
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
wlanif_input(void *h, void *buffer, size_t len, void* eb)
|
wlanif_input(void *h, void *buffer, size_t len, void* l2_buff)
|
||||||
{
|
{
|
||||||
struct netif * netif = h;
|
struct netif * netif = h;
|
||||||
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
|
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
|
|
||||||
if(unlikely(!buffer || !netif_is_up(netif))) {
|
if(unlikely(!buffer || !netif_is_up(netif))) {
|
||||||
if (eb) {
|
if (l2_buff) {
|
||||||
esp_netif_free_rx_buffer(esp_netif, eb);
|
esp_netif_free_rx_buffer(esp_netif, l2_buff);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -187,26 +173,23 @@ wlanif_input(void *h, void *buffer, size_t len, void* eb)
|
|||||||
#ifdef CONFIG_LWIP_L2_TO_L3_COPY
|
#ifdef CONFIG_LWIP_L2_TO_L3_COPY
|
||||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
esp_netif_free_rx_buffer(esp_netif, eb);
|
esp_netif_free_rx_buffer(esp_netif, l2_buff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p->l2_owner = NULL;
|
|
||||||
memcpy(p->payload, buffer, len);
|
memcpy(p->payload, buffer, len);
|
||||||
esp_netif_free_rx_buffer(esp_netif, eb);
|
esp_netif_free_rx_buffer(esp_netif, l2_buff);
|
||||||
#else
|
#else
|
||||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
|
p = esp_pbuf_allocate(esp_netif, buffer, len, l2_buff);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
esp_netif_free_rx_buffer(esp_netif, eb);
|
esp_netif_free_rx_buffer(esp_netif, l2_buff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p->payload = buffer;
|
|
||||||
p->l2_owner = netif;
|
#endif
|
||||||
p->l2_buf = eb;
|
|
||||||
#endif /* CONFIG_LWIP_L2_TO_L3_COPY */
|
|
||||||
|
|
||||||
/* full packet send to tcpip_thread to process */
|
/* full packet send to tcpip_thread to process */
|
||||||
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
LWIP_DEBUGF(NETIF_DEBUG, ("wlanif_input: IP input error\n"));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +202,7 @@ wlanif_input(void *h, void *buffer, size_t len, void* eb)
|
|||||||
*
|
*
|
||||||
* This function should be passed as a parameter to netif_add().
|
* This function should be passed as a parameter to netif_add().
|
||||||
*
|
*
|
||||||
* @param netif the lwip network interface structure for this ethernetif
|
* @param netif the lwip network interface structure for this wlanif
|
||||||
* @return ERR_OK if the loopif is initialized
|
* @return ERR_OK if the loopif is initialized
|
||||||
* ERR_MEM if private data couldn't be allocated
|
* ERR_MEM if private data couldn't be allocated
|
||||||
* any other err_t on error
|
* any other err_t on error
|
||||||
|
|||||||
Reference in New Issue
Block a user