+TCP DHCP discovery

I am using the STM32F7 chip with +TCP, and the corresponding NetworkInterface.c, etc.

I have the device connected to a TP-Link switch.

Per router wiresharks, the first prvSendDHCPDiscover() never hits the router.

Is there some misconfiguration I should look for, or do I need to restructure something else to make this work faster? Its taking a good 10 seconds + to get an address.

If I understand correctly, the first DHCP request does not make it onto the wire, but the second does. If so, this may be due to the receive timeout as follows:

When the system boots up the ARP cache is empty, so when you create a socket the first DHCP request will get replaced by and ARP packet to find the address of the DHCP server. That happens inside the TCP/IP stack though, the socket doesn’t see it and is still waiting for the DHCP reply. After a while the receive time out will expire and it will re-send the DHCP request, and this time the DHCP server address will hopefully be known from the ARP reply so the DHCP packet makes it onto the wire. So if the receive time out is long you will see that as a delay.

Each socket has a default receive timeout set by ipconfigSOCK_RECEIVE_BLOCK_TIME. You can change the default after the socket is created using FreeRTOS_setsockopt().

I don’t think that is quite right, because ARP relates to IP, and dhcp is pre arp, sent to a broadcast address.

I tracked it down to a unifi switch though, there must be some managed switch setting I haven’t figured out yet as bypassing the switch yields first time response.

Yes - think I must have been thinking about locating DNS server rather than DHCP - sorry for confusion - glad you worked it out.

When you look well, you will see that the two DHCP requests are slightly different:

The first request has the broadcast flag turned off ( 0 ).
When it doesn’t receive a reply, it will resubmit the DHCP request with the broadcast flag switched on ( 1 ).

When the flag if turned off, the reply will be directed to the offered IP-address.

You can try the following change:

-if( xDHCPData.xUseBroadcast != pdFALSE )
 {
     pxDHCPMessage->usFlags = ( uint16_t ) dhcpBROADCAST;
 }
-else
-{
-    pxDHCPMessage->usFlags = 0u;
-}

in other words: always request an answer in a broadcast packet.

Explanation: when the flag is off, the reply will be sent to e.g. 192.168.1.124 along with the MAC-address of your device.
Normally the unicast reply should arrive, but maybe in your case, the packet is dropped somewhere along the line.

My testing here showed that even if I sped up the rate, it took about 5 seconds, so even with a higher rate it wasn’t getting a reply on broadcasts.

But does it make a difference if you force the router to send broadcasts?

    pxDHCPMessage->usFlags = ( uint16_t ) dhcpBROADCAST;

If you run a DHCP server on your laptop you can study the actual packets and their timing. And also make a PCAP and post it here?

Alternatively, you can enable debug logging in your FreeRTOSIPConfig.h:

    #define ipconfigHAS_DEBUG_PRINTF	1
    #if( ipconfigHAS_DEBUG_PRINTF == 1 )
        #define FreeRTOS_debug_printf(X)	lUDPLoggingPrintf X
    #endif

I just enabled this debug logging and I see this conversation:

6.313 [IP-task   ] prvInitialiseDHCP: start after 250 ticks
6.313 [IP-task   ] vDHCPProcess: discover
6.314 [IP-task   ] vDHCPProcess: offer 192.168.2.208
6.314 [IP-task   ] vDHCPProcess: reply 192.168.2.208
6.316 [IP-task   ] vDHCPProcess: offer 192.168.2.208
6.316 [IP-task   ] vDHCPProcess: acked 192.168.2.208
6.316 [IP-task   ] IP Address: 192.168.2.208
6.316 [IP-task   ] Subnet Mask: 255.255.255.0
6.316 [IP-task   ] Gateway Address: 192.168.2.5
6.316 [IP-task   ] DNS Server Address: 192.168.2.5

Everything is done within 3 ms. I know that routers can respond slower, like 1 or 2 seconds.

Please find here a PCAP showing two different DHCP sessions:

dhcp_negotiation.zip (521 Bytes)

I used an open source DHCP-server called “Dual DHCP DNS Server”, ideal for testing.