ESP_Sprite:
Hardware ESP32 WROOM - two core
Web server - my design I been using in STM cpus for 10 years - uses sockets. NOT LWIP - I use FreeRTOS +TCP.
Using a JTAG debugger, I trapped the msg packet when it came in from wifi and watched how it was processed. I found that once the code was interrupted (breakpoint) the ESP would stop processing packets. I would have to reset, and watch a single trap again.
By using JTAG to watch the flow I went into the IDF source and added my own logging to watch flow and variables (logging did not freeze the ESP). The only thing I found which I could not explain was in the etharp.c file. The function processes the incoming packet.
Code: Select all
void
etharp_input(struct pbuf *p, struct netif *netif)
{
struct etharp_hdr *hdr;
/* these are aligned properly, whereas the ARP header fields might not be */
ip4_addr_t sipaddr, dipaddr;
u8_t for_us, from_us;
//ESP_LOGI("HinkleDBA", "etharp_input\n");
LWIP_ASSERT_CORE_LOCKED();
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
hdr = (struct etharp_hdr *)p->payload;
/* RFC 826 "Packet Reception": */
if ((hdr->hwtype != PP_HTONS(LWIP_IANA_HWTYPE_ETHERNET)) ||
(hdr->hwlen != ETH_HWADDR_LEN) ||
(hdr->protolen != sizeof(ip4_addr_t)) ||
(hdr->proto != PP_HTONS(ETHTYPE_IP))) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
pbuf_free(p);
return;
}
ETHARP_STATS_INC(etharp.recv);
#if LWIP_ACD
/* We have to check if a host already has configured our ip address and
* continuously check if there is a host with this IP-address so we can
* detect collisions.
* acd_arp_reply ensures the detection of conflicts. It will handle possible
* defending or retreating and will make sure a new IP address is selected.
* etharp_input does not need to handle packets that originate "from_us".
*/
acd_arp_reply(netif, hdr);
#endif /* LWIP_ACD */
/* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules). */
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr);
/* this interface is not configured? */
if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
for_us = 0;
from_us = 0;
//ESP_LOGI("HinkleDBA", "etharp_input - ip4_addr_isany_val(*netif_ip4_addr(netif) results Zero for_us, from_us\n" );
} else {
//ESP_LOGI("HinkleDBA", "etharp_input - dipaddr = %X", (unsigned int)dipaddr.addr );
/* ARP packet directed to us? */
for_us = (u8_t)ip4_addr_eq(&dipaddr, netif_ip4_addr(netif));
/* ARP packet from us? */
from_us = (u8_t)ip4_addr_eq(&sipaddr, netif_ip4_addr(netif));
}
//ESP_LOGI("HinkleDBA", "etharp_input for_us %d from_us %d\n", for_us, from_us);
/* ARP message directed to us?
-> add IP address in ARP cache; assume requester wants to talk to us,
can result in directly sending the queued packets for this host.
ARP message not directed to us?
-> update the source IP address in the cache, if present */
etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
//ESP_LOGI("HinkleDBA", "etharp_input hdr->opcode %d PP_HTONS(ARP_REQUEST) %d\n",hdr->opcode, PP_HTONS(ARP_REQUEST));
/* now act on the message itself */
switch (hdr->opcode) {
/* ARP request? */
case PP_HTONS(ARP_REQUEST):
/* ARP request. If it asked for our address, we send out a
* reply. In any case, we time-stamp any existing ARP entry,
* and possibly send out an IP packet that was queued on it. */
//ESP_LOGI("HinkleDBA", "etharp_input case PP_HTONS(ARP_REQUEST): for_us %d from_us %d\n", for_us, from_us);
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
/* ARP request for our address? */
if (for_us && !from_us) {
//ESP_LOGI("HinkleDBA", "Send etharp_raw\n");
/* send ARP response */
etharp_raw(netif,
(struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
(struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
&hdr->shwaddr, &sipaddr,
ARP_REPLY);
//ESP_LOGI("HinkleDBA", "etharp_input Return from etharp_raw\n");
/* we are not configured? */
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
/* request was not directed to us */
} else {
/* { for_us == 0 and netif->ip_addr.addr != 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
}
break;
case PP_HTONS(ARP_REPLY):
/* ARP reply. We already updated the ARP cache earlier. */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
ETHARP_STATS_INC(etharp.err);
break;
}
/* free ARP packet */
pbuf_free(p);
}
I left my logging code in (commented out) so you can see the flow I was looking at. Notice the switch where the type of response is decided.
the flow would Enter the switch with opcode ARP_REQUEST. for_us == 1 and to_us == 0; It would enter the proper case block - pass the for_us/to_us check but quite often NEVER get to etharp_raw(); Logging would not show processing etharp_raw(). I can't explain as there is no code to change the process path - so maybe an interaction within ESP prevented the logging from being sent.
I tried several changes to the IDF via your menu.
Gratuitous ARP OFF - nothing worked then.
Gratuitous ARP ON - timer 15 sec and WIFI power management off - did not work.
I'm back at Gratuitous ARP ON - 60 sec on timer and WIFI power management on (I forgot the flag name).
Every change - I deleted the build folder and recompiled the IDF.
It is working now and I can't explain why.
I compared the sdkconfig file from before (when at timer 15 and WIFI PM off) to timer 60 and WIFI PM on - to see if there were any unseen flags being set/cleared in the background - it was OK.
I did notice one thing the I think should be addressed in the IDF config. IMO, configuration flags that control behavior should only appear once. If you look at your Gratuitous ARP timer config setting - it appears twice under two different names - one for ESP and one for LWIP - same value ... so which one does the IDF use?
I say it working fine now - but that statement is based on minimal testing. Time will tell.
Thanks for replying to my questions.