martin-ger / esp-open-lwip

ESP8266 lwIP library with NAT, SLIP, ENC28j60 Ethernet, and routing support
67 stars 25 forks source link

What is the purpose of using loopback interface in ESP8266 ? #4

Open TridentTD opened 6 years ago

TridentTD commented 6 years ago

Do you mind to explain about the purpose of using loopback interface in ESP8266 ?

Thank you.

martin-ger commented 6 years ago

Cause it can be done... ;-) Actually, more a test and exercise for the routing stuff I am working on.

You could also have a local service like the MQTT server, but this is obviously not too interesting with just a few KB of mem. This might be of more interest when porting it to the ESP32.

TridentTD commented 6 years ago

Thanks for the answer : - )

And about funtionality of netif_poll , this function is what for? Why netif_poll in esp-wifi-repeater used for ?

martin-ger commented 6 years ago

A call to netif_poll() is required by lwip to drive a packet upstream again: When you send a packet to the loopback device, the sending function enqueues it finally in the netif for returning it and the sending function returns. As there is no TCP/IP-thread in the NONOS SDK somebody has to pick it up there and call the receive callback of anybody listening on that interface. This is done from netif_poll().

You might call it periodically, but this would introduce some latency. So I decided to add a callback, that indicates the existence of a queued packet. A user app migth then immediatly schedule a call to netif_poll() in its main "task". That's what the esp_wifi_repeater does. Currently, the only thing you can do with the loopback in the repeater is piniging it... Okay, that's limited fun, but I learned a lot about lwip in doing it: details about forwarding, how the raw-interface works, that there was an error in Espressif's ping implementation, why pinging of your own interfaces doesn't work...

TridentTD commented 6 years ago

Wow! very interesting.

If I wish to put "periodical netif_poll()" inside the esp-open-lwip , not in the task outside such as in user_init() . Are there any periodical functions in lwip can used for this purpose?

TridentTD commented 6 years ago

I have just tried ping to 127.0.0.1 by the esp-open-lwip, it works well. But when pinging to STATION_IP such as 192.168.43.110 , or SOFTAP_IP such as 192.168.4.1 it doesn't work. Is this issue an error in Espressif as you described above?

martin-ger commented 6 years ago

There is no periodical task in the NONOS SDK lwip stack. It is purely driven by interrupts and the user task. One could add ESP-specific coded (timers, tasks) to do the job, but lwip suggest the user polling.

The problem with pinging the WLAN netifs is, that their netif structure doesn't have the loopback queue, as it is compiled with other options. It is closed source, so mayby some kind of wrapper might work, but I don't think this would be so important (especially as you can do loopback now on the dedicated device).

TridentTD commented 6 years ago

Thank you, and one more question..

On ESP32 doesn't have any functions like ESP8266's eagle_lwip_getif() . How can I seperate between SOFTAP's netif and STATION's netif?

martin-ger commented 6 years ago

Havn't done that so far, but I guess, you can iterate the netif-list and identify them by name and number. On the ESP8266 STA is "ew0" and AP "ew1".

TridentTD commented 6 years ago

Thank you very much, master martin.

TridentTD commented 6 years ago

Hi, Master Margin.

I found something when I tried to edit some code, Pinging to 127.0.0.1 doesn't need outside system_os_post() called for periodical net_poll() any more,

I edit code in netif.c https://github.com/martin-ger/esp-open-lwip/blob/sdk-1.5.0/lwip/core/netif.c#L684

change to

#if LWIP_NETIF_LOOPBACK_MULTITHREADING
  /* For multithreading environment, schedule a call to netif_poll */
  tcpip_callback((tcpip_callback_fn)netif_poll, netif);
#else
  netif_poll(netif);
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */

and edit netif_init() to

void
netif_init(void)
{
#if LWIP_HAVE_LOOPIF
  ip_addr_t loop_ipaddr, loop_netmask, loop_gw;
  IP4_ADDR(&loop_gw, 127,0,0,1);
  IP4_ADDR(&loop_ipaddr, 127,0,0,1);
  IP4_ADDR(&loop_netmask, 255,0,0,0);

  netifnum = 0;
#if NO_SYS
  netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input);
#else  /* NO_SYS */
  netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input);
#endif /* NO_SYS */
  netifnum = 0;

  netif_set_up(&loop_netif);

#endif /* LWIP_HAVE_LOOPIF */
}

It can ping well to 127.0.0.1 without call loopback_netif_init((netif_status_callback_fn)schedule_netif_poll); and without call system_os_post(0, SIG_LOOPBACK, (ETSParam) netif); in the user app.

martin-ger commented 6 years ago

Okay, thanks. Will look into it - probably it works, when the downstream activity drives the packet upstream again. I am just experimenting with an Ethernet driver, guess I will get more insight into lwip by doing this...