esp_netif: Introduction of esp-netif component as a replacement of tcpip_adpter

- provides object oriented access to network intefaces
- not limited to default netifs
- more generic abstraction to network input output functions
- event handler registration removed from component responsibility
- backward compatibility layer for legacy tcpip_apapter APIs

Closes IDF-39
This commit is contained in:
David Cermak
2019-06-28 16:47:34 +02:00
parent ec9f245dd3
commit ffe043b1a8
56 changed files with 4344 additions and 2629 deletions

View File

@@ -19,17 +19,14 @@
#include "lwip/dhcp.h"
#include "lwip/netif.h"
#include "esp_interface.h"
#include "tcpip_adapter.h"
#include "esp_netif.h"
#include "esp_netif_net_stack.h"
#include "netif/dhcp_state.h"
#define DHCP_NAMESPACE "dhcp_state"
#define VALID_NETIF_ID(id) ((id < ESP_IF_MAX) && (id != ESP_IF_WIFI_AP))
static uint32_t restored_ip_addr[TCPIP_ADAPTER_IF_MAX];
static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH", "IF_TEST"};
_Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX,
"Number interface keys differs from number of interfaces");
// DHCP_Client has to be enabled for this netif
#define VALID_NETIF_ID(netif) (ESP_NETIF_DHCPC&esp_netif_get_flags(netif))
bool dhcp_ip_addr_restore(void *netif)
{
@@ -37,13 +34,12 @@ bool dhcp_ip_addr_restore(void *netif)
bool err = false;
struct netif *net = (struct netif *)netif;
struct dhcp *dhcp = netif_dhcp_data(net);
esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
if(VALID_NETIF_ID(netif_id)) {
if(VALID_NETIF_ID(esp_netif)) {
uint32_t *ip_addr = &dhcp->offered_ip_addr.addr;
if (nvs_open(DHCP_NAMESPACE, NVS_READONLY, &nvs) == ESP_OK) {
if (nvs_get_u32(nvs, interface_key[netif_id], ip_addr) == ESP_OK) {
restored_ip_addr[netif_id] = *ip_addr;
if (nvs_get_u32(nvs, esp_netif_get_ifkey(esp_netif), ip_addr) == ESP_OK) {
err = true;
}
nvs_close(nvs);
@@ -58,28 +54,24 @@ void dhcp_ip_addr_store(void *netif)
struct netif *net = (struct netif *)netif;
struct dhcp *dhcp = netif_dhcp_data(net);
uint32_t ip_addr = dhcp->offered_ip_addr.addr;
esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
if(VALID_NETIF_ID(netif_id)) {
if (restored_ip_addr[netif_id] != ip_addr) {
if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
nvs_set_u32(nvs, interface_key[netif_id], ip_addr);
nvs_commit(nvs);
nvs_close(nvs);
}
if(VALID_NETIF_ID(esp_netif)) {
if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
nvs_set_u32(nvs,esp_netif_get_ifkey(esp_netif), ip_addr);
nvs_commit(nvs);
nvs_close(nvs);
}
}
}
void dhcp_ip_addr_erase(void *netif)
void dhcp_ip_addr_erase(void *esp_netif)
{
nvs_handle_t nvs;
struct netif *net = (struct netif *)netif;
esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);
if(VALID_NETIF_ID(netif_id)) {
if(VALID_NETIF_ID(esp_netif)) {
if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
nvs_erase_key(nvs, interface_key[netif_id]);
nvs_erase_key(nvs, esp_netif_get_ifkey(esp_netif));
nvs_commit(nvs);
nvs_close(nvs);
}

View File

@@ -49,7 +49,8 @@
#include <string.h>
#include "esp_eth.h"
#include "tcpip_adapter.h"
#include "esp_netif.h"
#include "esp_netif_net_stack.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
@@ -61,7 +62,7 @@
* @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(void *buf)
static void ethernet_free_rx_buf_l2(struct netif *netif, void *buf)
{
free(buf);
}
@@ -105,17 +106,15 @@ static void ethernet_low_level_init(struct netif *netif)
static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p)
{
struct pbuf *q = p;
esp_interface_t eth_if = tcpip_adapter_get_esp_if(netif);
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
esp_err_t ret = ESP_FAIL;
esp_eth_handle_t eth_handle = (esp_eth_handle_t)netif->state;
if (eth_if != ESP_IF_ETH) {
LWIP_DEBUGF(NETIF_DEBUG, ("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len));
if (!esp_netif) {
LWIP_DEBUGF(NETIF_DEBUG, ("corresponding esp-netif is NULL: netif=%p pbuf=%p len=%d\n", netif, p, p->len));
return ERR_IF;
}
if (q->next == NULL) {
ret = esp_eth_transmit(eth_handle, q->payload, q->len);
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
} else {
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);
@@ -129,7 +128,7 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p)
} else {
return ERR_MEM;
}
ret = esp_eth_transmit(eth_handle, q->payload, q->len);
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
/* content in payload has been copied to DMA buffer, it's safe to free pbuf now */
pbuf_free(q);
}
@@ -152,13 +151,13 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p)
* @param buffer ethernet buffer
* @param len length of buffer
*/
void ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
void ethernetif_input(struct netif *netif, void *buffer, size_t len, void *eb)
{
struct pbuf *p;
if (buffer == NULL || !netif_is_up(netif)) {
if (buffer) {
ethernet_free_rx_buf_l2(buffer);
ethernet_free_rx_buf_l2(netif, buffer);
}
return;
}
@@ -166,7 +165,7 @@ void ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
/* acquire new pbuf, type: PBUF_REF */
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
if (p == NULL) {
ethernet_free_rx_buf_l2(buffer);
ethernet_free_rx_buf_l2(netif, buffer);
return;
}
p->payload = buffer;
@@ -194,7 +193,8 @@ void ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
esp_eth_handle_t eth_handle = (esp_eth_handle_t)netif->state;
/* Have to get the esp-netif handle from netif first and then driver==ethernet handle from there */
esp_eth_handle_t eth_handle = esp_netif_get_io_driver(esp_netif_get_handle_from_netif_impl(netif));
/* Initialize interface hostname */
#if LWIP_NETIF_HOSTNAME
#if ESP_LWIP
@@ -207,6 +207,7 @@ err_t ethernetif_init(struct netif *netif)
/* Initialize the snmp variables and counters inside the struct netif. */
eth_speed_t speed;
esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &speed);
if (speed == ETH_SPEED_100M) {
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);

View File

@@ -1,105 +0,0 @@
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h"
#include "netif/wlanif.h"
#include <stdio.h>
#include <string.h>
#include "tcpip_adapter.h"
static struct netif *g_last_netif = NULL;
err_t nettestif_output(struct netif *netif, struct pbuf *p)
{
int i;
char *dat = p->payload;
/* output the packet to stdout */
printf("\nPacketOut:[");
for (i=0; i<p->len; i++) {
printf("%02x", *dat++);
}
printf("]\n");
return ERR_OK;
}
err_t nettestif_init(struct netif *netif)
{
g_last_netif = netif;
netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME;
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100);
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
netif->linkoutput = nettestif_output;
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
#if ESP_LWIP
#if LWIP_IGMP
netif->flags |= NETIF_FLAG_IGMP;
#endif
#endif
return ERR_OK;
}
void nettestif_input(void *buffer, u16_t len)
{
struct pbuf *p;
if (g_last_netif == NULL) {
printf("error!");
return;
}
printf("simul in: %d\n", len);
if (len==0) return;
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
p->l2_owner = NULL;
memcpy(p->payload, buffer, len);
/* full packet send to tcpip_thread to process
* on success - the packet is processed and deallocated in tcpip stack
* on failure - log error and deallocate the packet
*/
if (g_last_netif->input(p, g_last_netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
}
}

View File

@@ -50,8 +50,20 @@
#include <stdio.h>
#include <string.h>
#include "tcpip_adapter.h"
#include "esp_netif.h"
#include "esp_netif_net_stack.h"
/**
* @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);
}
/**
* In this function, the hardware should be initialized.
@@ -82,7 +94,7 @@ low_level_init(struct netif *netif)
#endif
#if !ESP_L2_TO_L3_COPY
netif->l2_buffer_free_notify = esp_wifi_internal_free_rx_buffer;
netif->l2_buffer_free_notify = lwip_netif_wifi_free_rx_buffer;
#endif
}
@@ -104,16 +116,21 @@ low_level_init(struct netif *netif)
static err_t ESP_IRAM_ATTR
low_level_output(struct netif *netif, struct pbuf *p)
{
wifi_interface_t wifi_if = tcpip_adapter_get_esp_if(netif);
struct pbuf *q = p;
err_t ret;
if (wifi_if >= ESP_IF_MAX) {
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
if (esp_netif == NULL) {
return ERR_IF;
}
esp_netif_type_t type = esp_netif_get_type(esp_netif);
if (type != ESP_NETIF_TYPE_STA && type != ESP_NETIF_TYPE_AP) {
return ERR_IF;
}
struct pbuf *q = p;
err_t ret;
if(q->next == NULL) {
ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len);
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
} else {
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);
@@ -123,7 +140,8 @@ low_level_output(struct netif *netif, struct pbuf *p)
} else {
return ERR_MEM;
}
ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len);
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
pbuf_free(q);
}
@@ -140,13 +158,14 @@ low_level_output(struct netif *netif, struct pbuf *p)
* @param netif the lwip network interface structure for this ethernetif
*/
void ESP_IRAM_ATTR
wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
wlanif_input(struct netif *netif, void *buffer, size_t len, void* eb)
{
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
struct pbuf *p;
if(!buffer || !netif_is_up(netif)) {
if (eb) {
esp_wifi_internal_free_rx_buffer(eb);
esp_netif_free_rx_buffer(esp_netif, eb);
}
return;
}
@@ -154,16 +173,18 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
#if (ESP_L2_TO_L3_COPY == 1)
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p == NULL) {
esp_wifi_internal_free_rx_buffer(eb);
// esp_wifi_internal_free_rx_buffer(eb);
esp_netif_free_rx_buffer(esp_netif, eb);
return;
}
p->l2_owner = NULL;
memcpy(p->payload, buffer, len);
esp_wifi_internal_free_rx_buffer(eb);
esp_netif_free_rx_buffer(esp_netif, eb);
// esp_wifi_internal_free_rx_buffer(eb);
#else
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
if (p == NULL){
esp_wifi_internal_free_rx_buffer(eb);
esp_netif_free_rx_buffer(esp_netif, eb);
return;
}
p->payload = buffer;