Hi everyone!
I am working on a project that uses FreeRTOS+TCP, network configuration is DHCP.
I am experiencing an issue when obtaining IP through DHCP, here is what happens:
- the MCU is on the network doing its thing, then it gets reset;
- the MCU issues a discover;
- the DHCP already has a lease for the MCU’s MAC address, it tries to ping the lease before offering it;
- a ICMP ping request is issued with destination MAC of the MCU, ARP request is skipped as the host already has a fresh ARP entry for that MAC address;
- the MCU replies to that ICMP ping request!
- the DHCP server deems that lease occupied, so it abandons it and offers the next available IP.
I looked at the code to understand why this happens, I landed in “FreeRTOS_IPv4.c”, function “prvAllowIPPacketIPv4”, line 320.
The condition to DROP the packet is that ALL of the followings are true:
- all endpoints are up (I only have one)
- the packet dst IP is not multicast
- the packet dst IP is not broadcast
- no endpoint matches ANY the following criteria:
- packet dst IP == 0 (in which case any interface is fine)
- endpoint IP == 0 (so if the interface is down)
- packet dst IP == endpoint IP (the packet is for this interface)
In other words, KEEP the packet if ANY of the following:
- at least one endpoint is down
- the packet dst IP is multicast
- the packet dst IP is broadcast
- there is an endpoint that either:
- is down
- has an IP that matches packet’s dst IP
This logic allows all unicast packets through my inactive endpoint. This allows my MCU to generate the ICMP ping reply even if it doesn’t have the requested IP (the ICMP ping reply handler simply swaps the IPs around to generate a reply).
I have made two little modifications to fix the issue I described at the beginning. I have not tested it thoroughly, I don’t know if this breaks other use-cases, but I did not find any issue yet, neither in code nor in practice.
What are your thoughts?
Was that the intended behaviour?
Thanks!
--- ./FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_IPv4.c
+++ ./FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_IPv4.c.patch
@@ -321,9 +321,7 @@
( FreeRTOS_FindEndPointOnIP_IPv4( ulDestinationIPAddress, 4 ) == NULL ) &&
/* Is it an IPv4 broadcast address x.x.x.255 ? */
( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) &&
- ( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) &&
- /* Or (during DHCP negotiation) we have no IP-address yet? */
- ( FreeRTOS_IsNetworkUp() != pdFALSE ) )
+ ( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) )
{
/* Packet is not for this node, release it */
eReturn = eReleaseBuffer;
--- ./FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_Routing.c
+++ ./FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_Routing.c.patch
@@ -410,7 +410,6 @@
#endif
{
if( ( ulIPAddress == 0U ) ||
- ( pxEndPoint->ipv4_settings.ulIPAddress == 0U ) ||
( pxEndPoint->ipv4_settings.ulIPAddress == ulIPAddress ) )
{
break;