Restarting DHCP on Coldfire Lite (V3)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Restarting DHCP on Coldfire Lite (V3)

3,078 Views
vier_kuifjes
Senior Contributor I
Hello,

I'm working on a project using Coldfire Lite (V3).

The problem is that, when I shut down the router to which the coldfire ethernet link is connected, Coldfire Lite does not automatically request a new IP adress via DHCP after the link comes up again. Instead, it just keeps using it's originally assigned IP address.

What I would like to do is to detect when the link comes up, and then trigger the DHCP client to request a new IP address. I probably have to use dhc_setup() to do this. But I still have to detect when the link comes up somehow...

Also, I'm not sure if I can call dhc_setup() from just anywhere in my code.

If anyone could help me out, I would be very grateful.

Thanks in advance - Marc

Labels (1)
0 Kudos
7 Replies

652 Views
bkatt
Contributor IV


Marc VDH wrote:

The problem is that, when I shut down the router to which the coldfire ethernet link is connected, Coldfire Lite does not automatically request a new IP adress via DHCP after the link comes up again. Instead, it just keeps using it's originally assigned IP address.

What I would like to do is to detect when the link comes up, and then trigger the DHCP client to request a new IP address. I probably have to use dhc_setup() to do this. But I still have to detect when the link comes up somehow...



The DHCP protocol allows the client to continue using the IP address for the agreed-upon lease time, regardless of whether the server reboots. If there are any switches between the DHCP client and server, the client has no way of knowing what's going on with the server.

That said, whenever a client detects a loss of connection, it can play nice by renewing the lease early; this helps for example when you move a device to a different network without shutting it off. In Niche Lite, it looks like you could accomplish this by changing the DHCP client state from DHCS_BOUND to DHCS_INITREBOOT. Then the dhc_second() routine would handle everything else.

But how do you know you have lost connection? That's out of the scope of Niche Lite, and appears to vary based on the ethernet PHY. Freescale provides the function fec_mii_read(). For the PHY I am using, I can read mii register 0x10, and bit 0 of the result indicates a connection (bits 1 and 2 indicate 100 and FDX).

If you decide to do this, I suggest you make the change when the connection is lost (not when it "comes up"), and only if the state is DHCS_BOUND.

0 Kudos

652 Views
vier_kuifjes
Senior Contributor I
Ok, thanks for your reply, this might actually help.

Still I'm kinda surprised. Isn't the operating system supposed to take care of this automatically? Seems reasonable to me. For instance, when the coldfire device is not connected to a network at power up, it will not negotiate an IP address with the DHCP server when the physical connection is made.
0 Kudos

652 Views
bkatt
Contributor IV


Marc VDH wrote:

For instance, when the coldfire device is not connected to a network at power up, it will not negotiate an IP address with the DHCP server when the physical connection is made.


This appears to be caused by a hard-coded 30 second time-out in dhcsetup.c. I don't know why this strategy was chosen, but I suppose you could modify dhcsetup to do what is appropriate for your situation. For example, if there is no default address to fall back to, get rid of the 30 second limit and stay in dhcsetup indefinitely.

0 Kudos

652 Views
vier_kuifjes
Senior Contributor I
OK, the link detection using the mii status register works. I inserted this in one of the tasks and is called about every 2 seconds.

But calling dhc_setup() from within the same task when the link returns seems to make the program crash. So now I have to figure out where to call dhc_setup() to make sure everything keeps working as it should...
0 Kudos

652 Views
vier_kuifjes
Senior Contributor I
Looks like I've got it working now. Using DHC_SETUP wasn't the right approach. Here's what I have in my application task:

Code:
TK_ENTRY(tk_updateDisplay){ uint16 mymrdata; int iface; linkDownDetect = FALSE;  // Wait for TCP/IP stack to init while (!iniche_net_ready)     TK_SLEEP(1); // Task's must not return, Infinite loops  for (;;) {  while(!(fec_mii_read(FEC_PHY0, PHY_REG_PSR, &mymrdata))) // read proprietary status register  ;  if (mymrdata & PHY_R17_LNK)   {   linkDownDetect = TRUE;   // detect if link is down        LCD_Clean ();     LCD_String( (unsigned char *)"Link down!" , 1 );  }  else  {   if (linkDownDetect == TRUE)   {    if( POWERUP_CONFIG_DHCP_ENABLED )    {          LCD_Clean ();       LCD_String( (unsigned char *)"Restarting DHCP..." , 1 );        for (iface = 0; iface < STATIC_NETS; iface++)         dhc_state_init(iface, TRUE);    }   }   linkDownDetect = FALSE;                if (decoded)        {    displayUpdating = TRUE;                 displayTask();      displayUpdating = FALSE;        } }       tk_sleep( DISPLAY_REFRESH_TIME ); // Wait DISPLAY_REFRESH_TIME seconds....

 I still have to try out more situations, but it seems to work in the cases I already tested (disconnect/reconnect LAN, shutting down and restarting the router).

Thanks for the help!
0 Kudos

652 Views
vier_kuifjes
Senior Contributor I
For reference this is the final version of what I actually did to restart DHCP:

Changes in the file dhcsetup.c :

Code:
:
:
#ifdef DHCP_CLIENT
#include "dhcpclnt.h"
#include "nvparms.h"    /* For nvparms struct */
#include "netbuf.h"     /* To remove warnings for net.h */
#include "net.h"        /* For nets[] */
#include "in_utils.h"   /* For netexit() */

extern   void  set_link_down_detect(char link_status);

int dhc_main_ipset(int iface, int state);
:
:
:
void
dhc_setup(void)
{ 
   int      iface;
   uint16 mymrdata;
   ulong    dhcp_started;
   ip_addr  dhcp_saveaddr[STATIC_NETS];
   int      e;
   int      dhcnets = 0;   /* number of nets doing DHCP */

   while(!(fec_mii_read(FEC_PHY0, PHY_REG_PSR, &mymrdata))) // read proprietary status register
   ;
   if (mymrdata & PHY_R17_LNK)  // detect if link is down
      set_link_down_detect(TRUE);
   else
      set_link_down_detect(FALSE);

   e = dhc_init();
:
:

 
Changes in the file timeouts.c :

Code:
:
:
#ifdef TELNET_SVR
extern   void  tel_check(void);
#endif

unsigned long nextppp = 0L;   /* tick for next call to ppp timer */

#ifdef DHCP_CLIENT
static char link_down_detect;

void set_link_down_detect(char link_status)
{
 link_down_detect = link_status;
}

char read_link_down_detect(void)
{
 return link_down_detect;
}
#endif

void (*port_1s_callout)(void) = NULL;
:
:
:
#ifdef USE_PPP
      ppp_timeisup();
#endif
#ifdef DHCP_CLIENT
   while(!(fec_mii_read(FEC_PHY0, PHY_REG_PSR, &mymrdata))) // read proprietary status register
   ;
   if (mymrdata & PHY_R17_LNK) 
    link_down_detect = TRUE;   // detect if link is down
   else
   {
    if (link_down_detect == TRUE)
    {
     if( POWERUP_CONFIG_DHCP_ENABLED )
     {
      for (iface = 0; iface < STATIC_NETS; iface++)
       dhc_state_init(iface, TRUE);
     }
    }
    link_down_detect = FALSE;
   }

      dhc_second();
#endif
#ifdef DHCP_SERVER
      dhcp_timeisup();
#endif
:
:

 
Additionally, you may add some code in your application to force DHCP renegotiation. This could be triggered by a communication watchdog, for instance:

Code:
#ifdef DHCP_CLIENT
extern   void  set_link_down_detect(char link_status);
#endif
:
:
:
    watchdog_timer += UPDATE_TIME;
    if (watchdog_timer > WATCHDOG_TIMEOUT_TIME) // something wrong with network comm
    {
#ifdef DHCP_CLIENT
 set_link_down_detect(TRUE);
#endif
 watchdog_timer = 0;
    }

 With the new version of Coldfire Lite, version 3.2, it is also important to make the change that I described in following thread. This is because V3.2 resets the CPU when the network link is broken. The following modification fixes this. See thread below:

http://forums.freescale.com/freescale/board/message?board.id=CWCFCOMM&thread.id=2530

0 Kudos

652 Views
vier_kuifjes
Senior Contributor I
Is there no one around here that knows about the inner workings of Coldfire Lite?

Anyway... as soon as I finish working at my current project, I will start porting the Coldfire Lite application to the uTasker...
0 Kudos