自己在做项目时,需求与LWIP协议栈中的DHCP实现不太一样,发现如果修改起来没有想象的那么容易,跟大家分享一下修改过程。

一、时间变量

 
    
  1. u32_t offered_t0_lease; /* lease period (in seconds) */ 
  2. u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ 
  3. u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period)  */ 
  4.  
  5.  
  6. u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ 
  7. u16_t t1_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ 
  8. u16_t t2_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ 
  9.  

 

在offered_t0_lease 租约时间,服务器在offer报文跟ack报文中都会给你,时间是秒,在lwip协议栈中则是在ack报文中获得并保存下来,option为51。其他更新时间与绑定时间也类似,看起来比较容易。可是在使用中,出现了两个疑问。

1.在dhcp的代码中,没有定时器,这个时间是如何与系统时间所匹配呢?

2.还有几个变量t1_timeout、t2_timeout是做什么用的?
 
   其实解决了这两个问题,对于dhcp控制时间的思路也就比较清晰了。
   解决第一个疑问,dhcp的轮询是依靠这段代码实现的。
 
      
  1. for(idxtimer=0; 
  2.             idxtimer < (sizeof(timers_table)/sizeof(timers_info)); 
  3.             idxtimer ++) 
  4.         { 
  5.             ptmr_inf = &timers_table[idxtimer]; 
  6.             ptmr_inf->timer += time_diff; 
  7.             if (ptmr_inf->timer > ptmr_inf->timer_interval) 
  8.             { 
  9.                 if (ptmr_inf->timer_func) 
  10.                     ptmr_inf->timer_func(); 
  11.                 ptmr_inf->timer -= ptmr_inf->timer_interval; 
  12.             } 
  13.         } 
     
 
     
  1. static timers_info timers_table[] = { 
  2.     /* LWIP_TCP */ 
  3.     { 0, TCP_FAST_INTERVAL,     tcp_fasttmr}, 
  4.     { 0, TCP_SLOW_INTERVAL,     tcp_slowtmr}, 
  5.     /* LWIP_ARP */ 
  6.     { 0, ARP_TMR_INTERVAL,      etharp_tmr}, 
  7.     /* LWIP_DHCP */ 
  8.     #if LWIP_DHCP 
  9.     { 0, DHCP_COARSE_TIMER_SECS, dhcp_coarse_tmr}, 
  10.     { 0, DHCP_FINE_TIMER_MSECS,  dhcp_fine_tmr}, 
  11.     #endif 
  12. }; 
   就是每隔DHCP_COARSE_TIMER_SECS时间后,执行一下dhcp_coarse_tmr()函数。所以是每隔系统时间DHCP_COARSE_TIMER_SECS调用一次该函数。dhcp的时间就是通过这样的方式与系统时间耦合上的。
 
 
   第二个疑问。
 
 
     
  1. timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; 
  2. dhcp->t1_timeout = (u16_t)timeout; 
 
就是这么得来的,t1_timeout为以DHCP_COARSE_TIMER_SECS为衡量的单位时间,就是说有t1个DHCP_COARSE_TIMER_SECS时间,而在dhcp_coarse_tmr()函数中的t1_timeout--也就是每次轮询,都自减一个DHCP_COARSE_TIMER_SECS时间,这样就能够做到虽然自己没有计时器,但是却很好的耦合上了系统时间。