This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Handling DHCP client timeout

Other Parts Discussed in Thread: TM4C1294NCPDT, EK-TM4C1294XL

Hello,

I am using TI-RTOS 2.14.04.31 with NDK 2.24.03.35 and XDC 3.32.00.06. I am running a TM4C1294NCPDT processor on a custom board, that uses EK-TM4C1294XL as reference.

The issue I have is that the DHCP client times out after around 3 minutes of not getting an IP address and stays off forever. In our application the board has to be connected to the internet reliably, as the application of the product would make restarting them quite a hassle and generally unwanted.

The internet connection paramaters have been set up in the .cfg file.

Attempts to restart the client using the information I've found on this forum have been unsuccessful. Readding the DHCP service using CfgAddEntry after a call to statusReportHook creates new DHCP tasks while leaving the old one(s) in an inactive state. This quickly leads to memory problems and an eventual crash.

I have been unsuccessful in removing the old entries and readding a new one from my statusReportHook function.

What would be a good way to go about this?

  • Hi Jaan,

    How did you try to remove the old entries? Can you share the code you used?

    Gilbert
  • I used the information I gained from this post:  

    Unfortunately I do not have the code I tried any more as that was a while ago.

    At the moment I have a function being called when statusReportHook reports of an interface being used. The function is as follows:

    void startDHCP()
    {
    	HANDLE hCfg = 0;
    	hCfg = CfgGetDefault();
    
        /* Use DHCP to obtain IP address on interface 1 */
        {
            CI_SERVICE_DHCPC dhcpc;
            UINT8 DHCP_OPTIONS[] =
    		{
    			DHCPOPT_SUBNET_MASK,
    			DHCPOPT_NAME_SERVERS,
    		};
    
            /* Specify DHCP Service on IF specified by "IfIdx" */
            bzero(&dhcpc, sizeof(dhcpc));
            dhcpc.cisargs.Mode   = 1;
            dhcpc.cisargs.IfIdx  = 1;
            dhcpc.cisargs.pCbSrv = &ti_ndk_config_Global_serviceReport;
            dhcpc.param.pOptions = DHCP_OPTIONS;
            dhcpc.param.len = 2;
            int ret = CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                    sizeof(dhcpc), (UINT8 *)&dhcpc, 0);
            System_printf("RET %d\n", ret); System_flush();
        }
    }

    Please let me know if this is not enough information to go off of and thank you for taking the time to answer me!

  • Can you verify the DHCP client is being/not being removed using the code below from the other thread?

      /* remove the DHCP client configuration */ 
        status = CfgRemoveEntry(hCfg, entry); 
        if (status < 0) { 
            System_printf("ipaddrhook: error, couldn't remove DHCP client entry (%d)\n", status); 
        } 

    You can put a breakpoint at the function below. Can you confirm if it hits there after calling the above code?

    void DHCPClose( HANDLE hDHCP )
  • Hi,

    I ran this code in statusReportHook on DHCP service time out:

    void removeDHCP()
    {
        HANDLE hCfg = 0;
        HANDLE entry;
        int status;
    
    	/* get the default configuration */
    	hCfg = CfgGetDefault();
    
    	if (!hCfg) {
    		System_printf("ipaddrhook: error, couldn't get default config\n");
    	}
    
    	/* get the DHCP client configuration */
    	status = CfgGetEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 1, &entry);
    	if (!status) {
    		System_printf("ipaddrhook: error, couldn't get DHCP client entry\n");
    	}
    
    	/* remove the DHCP client configuration */
    	status = CfgRemoveEntry(hCfg, entry);
    	if (status < 0) {
            System_printf("ipaddrhook: error, couldn't remove DHCP client entry (%d)\n", status);
        }
    }

    Looking at ROV I see that the DHCP task has been stopped. Trying to start it up again immediately after does not seem to work - no DHCP task in ROV.

    void statusReportHook(uint32_t IPAddr, unsigned int IfIdx, unsigned int fAdd)
    {
    	if (IPAddr == 5 && fAdd == 1026) {		
    		System_printf("DHCP timeout\n"); System_flush();
    		removeDHCP();
    		startDHCP();
    	}
    }

  • Have you confirmed that the function DHCPClose() has been called?
  • Yes, DHCPClose() was called.

  • What is the program output that you are getting from your remove/startDHCP functions?

    | Looking at ROV I see that the DHCP task has been stopped.
    Can you provide a screenshot of this?

    | Trying to start it up again immediately after does not seem to work - no DHCP task in ROV.
    Can you provide a screenshot of this as well?
  • I took a bunch of screenshots of different configurations.

    Here's a screenshot of ROV and SysMin output after DHCP times out because of no ethernet cable attached:

    Here's one without a cable plugged in but before timing out:

    Here's one of a cable connected but no IP assigned yet:

    And here's one with an IP assigned and my network tasks started:

    networkTask is started in netIPAddrHook, which in turn runs doCommandTask and eventPostTask once a server IP has been resolved.

    My statusReportHook function for the previous screenshots:

    void statusReportHook(uint32_t IPAddr, unsigned int IfIdx, unsigned int fAdd)
    {
    	if (IPAddr == 5 && fAdd == 1026) {
    		// TODO Restart system? DHCP timeouts in ~3 minutes so it should be fine
    		System_printf("DHCP timeout\n"); System_flush();
    		removeDHCP();
    	}
    }

    Modifying it to start DHCP after removing it:

    void statusReportHook(uint32_t IPAddr, unsigned int IfIdx, unsigned int fAdd)
    {
    	if (IPAddr == 5 && fAdd == 1026) {
    		System_printf("DHCP timeout\n"); System_flush();
    		removeDHCP();
    		startDHCP();
    	}
    }

    Yields the same result:

    Just in case:

    void startDHCP()
    {
    	HANDLE hCfg = 0;
    	hCfg = CfgGetDefault();
    
        /* Use DHCP to obtain IP address on interface 1 */
        {
            CI_SERVICE_DHCPC dhcpc;
            UINT8 DHCP_OPTIONS[] =
    		{
    			DHCPOPT_SUBNET_MASK,
    			DHCPOPT_NAME_SERVERS,
    		};
    
            /* Specify DHCP Service on IF specified by "IfIdx" */
            bzero(&dhcpc, sizeof(dhcpc));
            dhcpc.cisargs.Mode   = 1;
            dhcpc.cisargs.IfIdx  = 1;
            dhcpc.cisargs.pCbSrv = &ti_ndk_config_Global_serviceReport;
            dhcpc.param.pOptions = DHCP_OPTIONS;
            dhcpc.param.len = 2;
            int ret = CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                    sizeof(dhcpc), (UINT8 *)&dhcpc, 0);
            System_printf("RET %d\n", ret); System_flush();
        }
    }
    
    void removeDHCP()
    {
        HANDLE hCfg = 0;
        HANDLE entry;
        int status;
    
    	/* get the default configuration */
    	hCfg = CfgGetDefault();
    
    	if (!hCfg) {
    		System_printf("ipaddrhook: error, couldn't get default config\n");
    	}
    
    	/* get the DHCP client configuration */
    	status = CfgGetEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 1, &entry);
    	if (!status) {
    		System_printf("ipaddrhook: error, couldn't get DHCP client entry\n");
    	}
    
    	/* remove the DHCP client configuration */
    	status = CfgRemoveEntry(hCfg, entry);
    	if (status < 0) {
            System_printf("ipaddrhook: error, couldn't remove DHCP client entry (%d)\n", status);
        }
    }

  • I have determined that the program never goes past

        /* Kill our DHCP task if needed */
        if( pLease->dhcpTASK )
        {
            fdCloseSession( pLease->dhcpTASK );
            TaskDestroy( pLease->dhcpTASK );
        }

    and hence startDHCP is never called. The program never returns to statusReportHook.

    EDIT: I had statusReportHook start DHCP before removing the service. In this case I see dhcpTask running again in ROV:

    I do not get an IP address from the router after plugging in the cable though.

  • So the DHCP client task seems to be getting removed, which helps resolve one of your earlier issues correct?

    Are you seeing any DHCP request packets coming out on the wire? A tool you can use for this is Wireshark. You should be able to see the packets once you run Wireshark because they are broadcast packets. You should see something similar to the screencap below:

    You should be watching for the DHCP Discover packet.

  • After only removing the DHCP service on timeout and then plugging in the cable leads to no DHCP packets sent over the network.

    Starting DHCP before removing it leads to two packets sent out:

    Unfortunately that's all I can see using the current network configuration. Those are also the same packets I see when the device gets registered on the network.

    To clarify, my issue is that I need DHCP to work as close to always as possible and I'm not sure how to go about it.

  • We are currently trying to replicate your issue on our end and figuring out how to resolve it as quickly as possible. I will let you know what we find.

    Gilbert
  • We tried a test case (attached) in which we left the cable unplugged, ran and waited for the DHCP fault, and then ran code to reset DHCP. At this point, we also plugged the cable back in and we were able obtain an IP successfully.

    Can you try reproducing this? Once you see the fault, you need to halt and then change the global variable STEVE_debug equal to 1 (open the CCS expressions window and enter the variable name in order to change it). This will kick off the DHCP restart code (in test.c of the attached).

    0652.dhcp_reset_test.zip

    Regards,

    Gilbert

  • I am getting an error regarding a missing compiler. I have been unsuccessful in finding the one specified, can you help?
  • Are you not able to update the compiler options? Have you tried cleaning the project before building it again? If you still have issues, let me know what compiler you are using, and I'll just re-upload the project with a different compiler set.
  • I am unable to import the CCS project, the importer states I need ARM compiler version 15.12. I am currently using the TI ARM compiler v5.2.6.

    Thank you!
  • I'm sorry, I'm still getting the same error.

    See details below.
    Error: Import failed for project 'udpEcho_EK_TM4C1294XL_TI_TivaTM4C1294NCPDT' because its compiler definition is not available. Please install the ARMv15.12 compiler before importing this project - click 'View > CCS App Center' to check if compiler updates are available, or install the compiler manually and register it with CCS through 'Preferences > CCS > Build > Compilers'.

  • That's odd. When I downloaded and imported the project, I can see no reference to the ARMv15.12 compiler. Did you make sure to delete the older version of the project before unzipping the new one?

    Just in case, I removed the ARMv15.12 compiler before building and zipping this version of the project:

    8802.dhcp_reset_test.zip

    If  you still can't import the project for some reason, you can import the "TI-RTOS for TivaC" udpEcho example we have in the Resource Explorer and just drop in the files from the zipped example.

    Regards,

    Gilbert

  • Hello,

    I finally got it to work and it works as you said. Letting DHCP timeout and then setting the comically named variable to 1 brought DHCP up again without problems.

    I assume the problem for me was not calling to start DHCP in a task context and the fix would be to call it from a task context?

    Thank you so much for taking the time to help me!

  • I tested removing and adding the DHCP interface as suggested by your project and I can verify that it does in fact work properly. For others to come, I have included how I did it.

    I added a global variable to monitor the status of DHCP and tested for it in another thread that is started at startup. A DHCP timeout calls statusReportHook, which in turn sets said global variable to false. The monitoring thread picks it up and starts DHCP again.

    bool dhcpRunning = true; // Global
    
    if (!dhcpRunning) {
        removeDHCP();
        Task_sleep(2000);
        startDHCP();
        dhcpRunning = true;
    }

    void removeDHCP()
    {
        HANDLE hCfg = 0;
        HANDLE entry;
        int status;
    
    	/* get the default configuration */
    	hCfg = CfgGetDefault();
    
    	if (!hCfg) {
    		System_printf("ipaddrhook: error, couldn't get default config\n");
    	}
    
    	/* get the DHCP client configuration */
    	status = CfgGetEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 1, &entry);
    	if (!status) {
    		System_printf("ipaddrhook: error, couldn't get DHCP client entry\n");
    	}
    
    	/* remove the DHCP client configuration */
    	status = CfgRemoveEntry(hCfg, entry);
    	if (status < 0) {
            System_printf("ipaddrhook: error, couldn't remove DHCP client entry (%d)\n", status);
        }
    	System_printf("DHCP removed\n"); System_flush();
    }
    
    void startDHCP()
    {
    	HANDLE hCfg = 0;
    	hCfg = CfgGetDefault();
    
        /* Use DHCP to obtain IP address on interface 1 */
        {
            CI_SERVICE_DHCPC dhcpc;
            UINT8 DHCP_OPTIONS[] =
    		{
    			DHCPOPT_SUBNET_MASK,
    			DHCPOPT_NAME_SERVERS,
    		};
    
            /* Specify DHCP Service on IF specified by "IfIdx" */
            bzero(&dhcpc, sizeof(dhcpc));
            dhcpc.cisargs.Mode   = 9;
            dhcpc.cisargs.IfIdx  = 1;
            dhcpc.cisargs.pCbSrv = &ti_ndk_config_Global_serviceReport;
            dhcpc.param.pOptions = DHCP_OPTIONS;
            dhcpc.param.len = 2;
            int ret = CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                    sizeof(dhcpc), (UINT8 *)&dhcpc, 0);
            System_printf("RET %d\n", ret); System_flush();
        }
    }

    void statusReportHook(uint32_t IPAddr, unsigned int IfIdx, unsigned int fAdd)
    {
    	if (IPAddr == 5 && fAdd == 1026) { // DHCP is now disabled
    		dhcpRunning = false;
    	}
    }