在最新的iFreeBSD(FeeBSD 11.X)代码里依然没有实现RFC-2461中规定的对于anycast或者proxy类型的NS包在回NA的时候需要一个小于1S的随机时间的延时:
“If the Target Address is an anycast address the sender SHOULD delay
sending a response for a random time between 0 and MAX_ANYCAST_DELAY_TIME seconds.”
其中,MAX_ANYCAST_DELAY_TIME为1 second.
大致意思就是说,对于接受到的每一个NS包,需要回一个NA给对端。对于anycast或者proxy这种类型的包,再回NA的时候需要一个时间延迟,该延时时一个小于1S的随机时间。
/* * Neighbor advertisement input handling. * * Based on RFC 2461 * Based on RFC 2462 (duplicate address detection) * * the following items are not implemented yet: * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) */voidnd6_na_input(structmbuf*m,intoff,inticmp6len);
nd6_na_input(){if(anycast||proxy){intdelay=random()%HZ;structtimer*anycast_delay_timer;anycast_delay_timer=(structtimer*)malloc(sizeof(structtimer));if(anycast==NULL){gotofreeit;}na_arg->timer=anycast_delay_timer;/* need free it in the async function */jtimer_init(anycast_delay_timer);jtimer_start(anycast_delay_timer,delay,anycast_delay_handler,na_arg);return;}freeit:…}voidanycast_delay_handler(void*arg){structna_arg_t*na_arg=(structna_arg_t*)arg;/*send out the NA packet*/...free(na_arg->timer);}
structna_struct_t{.../* 放到一个TAILQ里头 */TAILQ_ENTRY(na_struct_t)anycast_delay_list;};TAILQ_HEAD(anycast_list_,na_struct_t)anycast_list=TAILQ_HEAD_INITIALIZER(anycast_list);staticstructtimeranycast_delay_timer;staticbooleantimer_running=false;/* the max members in the anycast_delay_list */#define ANYCAST_DELAY_MAX_LEN 64/* anycast/proxy delay list length */intanycast_delay_len=0;nd6_na_input(){...if(anycast||proxy){intdelay=random()%HZ;structna_struct_t*na_arg=set_na(...);spin_lock(&anycast_list_lock);if(anycast_delay_len>ANYCAST_DELAY_MAX_LEN){gotofreeit;}TAILQ_INSERT_TAIL(&anycast_list,na_arg,anycast_delay_list);anycast_delay_len++;spin_unlock(&anycast_list_lock);if(!timer_running){timer_running=true;timer_start(&anycast_delay_timer,delay,anycast_delay_handler,(void*)0);}return;}}voidanycast_delay_handler(void*arg){spin_lock(&anycast_list_lock);/* once this function is executed, the tail should not be empty */structna_arg_t*na=TAILQ_FIRST(&anycast_list);TAILQ_REMOVE(&anycast_list,na,anycast_delay_list);anycast_delay_len--;/*send out the NA packet*/...if(!TAILQ_EMPTY(&anycast_list)){intdelay=random()%HZ;/* 还有NA需要send, 所以重启定时器 */timer_start(&anycast_delay_timer,delay,anycast_delay_handler,(void*)0);}else{/* 没有NA了,所以NS里面可以启动定时器了 */timer_running=false;}spin_unlock(&anycast_list_lock);}
/* the max members in the anycast_delay_list */#define ANYCAST_DELAY_MAX_LEN 64/* anycast/proxy delay list length */intanycast_delay_len=0;structna_struct_t{...intexpire;/*这个包需要延时发送的时刻 */TAILQ_ENTRY(na_struct_t)anycast_delay_list;/* 放到一个TAILQ里头 */};TAILQ_HEAD(anycast_list_,na_struct_t)anycast_list=TAILQ_HEAD_INITIALIZER(anycast_list);staticstructtimeranycast_delay_timer;staticbooleantimer_running=false;nd6_na_input(){...if(anycast||proxy){intdelay=random()%HZ;structna_struct_t*na_arg=set_na(...);na_arg->expire=ticks+delay;spin_lock(&anycast_list_lock);if(anycast_delay_len>ANYCAST_DELAY_MAX_LEN){gotofreeit;}TAILQ_INSERT_TAIL(&anycast_list,na_arg,anycast_delay_list);anycast_delay_len++;spin_unlock(&anycast_list_lock);if(!timer_running){timer_running=true;timer_start(&anycast_delay_timer,delay,anycast_delay_handler,(void*)0);}return;}freeit:...}voidanycast_delay_handler(void*arg__unused){structna_arg_anycast_delay*na_arg=NULL;intnow=ticks;intdelay=0;spin_lock(&anycast_list_lock);TAILQ_FOREACH(na_arg,&anycast_list,anycast_delay_list){if(na_arg->expire<now){/* already expired. */anycast_delay_len--;/*send out the NA packet*/...}elseif(!delay||na_arg->expire-now<na_arg){delay=na_arg->expire-now;}}if(!delay){/* 还有NA需要send, 所以重启定时器 */timer_start(&anycast_delay_timer,delay,anycast_delay_handler,(void*)0);}else{/* 没有NA了,所以NS里面可以启动定时器了 */timer_running=false;}spin_unlock(&anycast_list_lock);}