lwip中关于nd的实现,没有路由器的功能,不能发送ra

在contiki中发现有nd发送ra的实现,

contiki/core/net/ipv6/uip-ds6.c

在rs的接收处理中,发送sollicited,在定时器中定期发送periodic。

发送solicted的时候,其实,是让定时器直接到时间实现的。

在uip_ds6_init中初始化ra发送定时器,初始设为2s后发送?等待链路本地地址有效

初始设置为2s,之后定时处理函数会处理定时器首次超时,处理完之后,会将定时器设置为RA间隔时间。

void
uip_ds6_init(void)
{
#if UIP_ND6_SEND_RA
stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
#endif /* UIP_ND6_SEND_RA */

在uip_ds6_periodic中定期处理是否超时,uip_ds6_periodic类似lwip中的nd_tmr。如果超时了,就发送uip_ds6_send_ra_periodic

void
uip_ds6_periodic(void)
{
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
/* Periodic RA sending */
if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
uip_ds6_send_ra_periodic();
}
#endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */

uip_ds6_send_ra_periodic函数中设置了两次随机时间,没看明白为什么?

第一次时间:间隔=最小间隔+随机数*(最大间隔-最小间隔)

第二次时间:初始的3次ra间隔不能超过初始最大间隔16s,后续的ra间隔没限制

 /*---------------------------------------------------------------------------*/
void
uip_ds6_send_ra_periodic(void)
{
if(racount > ) {
/* send previously scheduled RA */
uip_nd6_ra_output(NULL);
PRINTF("Sending periodic RA\n");
}
  /* rand_t = min + rand % (max - min) */
rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
(uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
PRINTF("Random time 1 = %u\n", rand_time);
  /* intial ra interval = 16s, initial 3 ra, should not exceed initial_ra_interval */
if(racount < UIP_ND6_MAX_INITIAL_RAS) {
if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
PRINTF("Random time 2 = %u\n", rand_time);
}
racount++;
}
PRINTF("Random time 3 = %u\n", rand_time);
stimer_set(&uip_ds6_timer_ra, rand_time);
}

如果收到了rs(rs_input在uip-nd6.c文件中),则会发送sollicited的ra,在uip_ds6_send_ra_sollicited中,其实是直接将定时器设置到时间。

/*---------------------------------------------------------------------------*/
#if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA
void
uip_ds6_send_ra_sollicited(void)
{
/* We have a pb here: RA timer max possible value is 1800s,
* hence we have to use stimers. However, when receiving a RS, we
* should delay the reply by a random value between 0 and 500ms timers.
* stimers are in seconds, hence we cannot do this. Therefore we just send
* the RA (setting the timer to 0 below). We keep the code logic for
* the days contiki will support appropriate timers */
rand_time = ;
PRINTF("Solicited RA, random time %u\n", rand_time); if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
/* Ensure that the RAs are rate limited */
/* stimer_set(&uip_ds6_timer_ra, rand_time +
UIP_ND6_MIN_DELAY_BETWEEN_RAS -
stimer_elapsed(&uip_ds6_timer_ra));
*/ } else {
stimer_set(&uip_ds6_timer_ra, rand_time);
}
}
}

uip-nd6.c实际的接收rs和发送ra在这个文件中定义

 /*---------------------------------------------------------------------------*/
static void
rs_input(void)
{ PRINTF("Received RS from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv); #if UIP_CONF_IPV6_CHECKS
/*
* Check hop limit / icmp code
* target address must not be multicast
* if the NA is solicited, dest must not be multicast
*/
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != )) {
PRINTF("RS received is bad\n");
goto discard;
}
#endif /*UIP_CONF_IPV6_CHECKS */ /* Only valid option is Source Link-Layer Address option any thing
else is discarded */
nd6_opt_offset = UIP_ND6_RS_LEN;
nd6_opt_llao = NULL; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
#if UIP_CONF_IPV6_CHECKS
if(UIP_ND6_OPT_HDR_BUF->len == ) {
PRINTF("RS received is bad\n");
goto discard;
}
#endif /*UIP_CONF_IPV6_CHECKS */
switch (UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_SLLAO:
nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
break;
default:
PRINTF("ND option not supported in RS\n");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << );
}
/* Options processing: only SLLAO */
if(nd6_opt_llao != NULL) {
#if UIP_CONF_IPV6_CHECKS
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
PRINTF("RS received is bad\n");
goto discard;
} else {
#endif /*UIP_CONF_IPV6_CHECKS */
uip_lladdr_t lladdr_aligned;
extract_lladdr_from_llao_aligned(&lladdr_aligned);
if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
/* we need to add the neighbor */
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
} else {
/* If LL address changed, set neighbor state to stale */
const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
if(lladdr == NULL) {
goto discard;
}
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
lladdr, UIP_LLADDR_LEN) != ) {
uip_ds6_nbr_t nbr_data;
nbr_data = *nbr;
uip_ds6_nbr_rm(nbr);
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
nbr->reachable = nbr_data.reachable;
nbr->sendns = nbr_data.sendns;
nbr->nscount = nbr_data.nscount;
}
nbr->isrouter = ;
}
#if UIP_CONF_IPV6_CHECKS
}
#endif /*UIP_CONF_IPV6_CHECKS */
} /* Schedule a sollicited RA */
uip_ds6_send_ra_sollicited(); discard:
uip_clear_buf();
return;
}
 /*---------------------------------------------------------------------------*/
void
uip_nd6_ra_output(uip_ipaddr_t * dest)
{ UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = ;
UIP_IP_BUF->flow = ;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) {
uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
} else {
/* For sollicited RA */
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
}
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RA;
UIP_ICMP_BUF->icode = ; UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; UIP_ND6_RA_BUF->flags_reserved =
(UIP_ND6_M_FLAG << ) | (UIP_ND6_O_FLAG << ); UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
//UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
//UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
UIP_ND6_RA_BUF->reachable_time = ;
UIP_ND6_RA_BUF->retrans_timer = ; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
nd6_opt_offset = UIP_ND6_RA_LEN; /* Prefix list */
for(prefix = uip_ds6_prefix_list;
prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
if((prefix->isused) && (prefix->advertise)) {
UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / ;
UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
UIP_ND6_OPT_PREFIX_BUF->reserved2 = ;
uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
}
} /* Source link-layer option */
create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); uip_len += UIP_ND6_OPT_LLAO_LEN;
nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; /* MTU */
UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> ;
UIP_ND6_OPT_MTU_BUF->reserved = ;
//UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(); uip_len += UIP_ND6_OPT_MTU_LEN;
nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; #if UIP_ND6_RA_RDNSS
if(uip_nameserver_count() > ) {
uint8_t i = ;
uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip;
uip_ipaddr_t *dns = NULL;
UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS;
UIP_ND6_OPT_RDNSS_BUF->reserved = ;
UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration();
if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds();
}
while((dns = uip_nameserver_get(i)) != NULL) {
uip_ipaddr_copy(ip++, dns);
i++;
}
UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << );
PRINTF("%d nameservers reported\n", i);
uip_len += UIP_ND6_OPT_RDNSS_BUF->len << ;
nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << ;
}
#endif /* UIP_ND6_RA_RDNSS */ UIP_IP_BUF->len[] = ((uip_len - UIP_IPH_LEN) >> );
UIP_IP_BUF->len[] = ((uip_len - UIP_IPH_LEN) & 0xff); /*ICMP checksum */
UIP_ICMP_BUF->icmpchksum = ;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending RA to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
return;
}

在linux和freebsd中每怎么找到发送ra的部分。

最新文章

  1. js中的时间与毫秒数互相转换
  2. 找window的三种方法
  3. js window对象
  4. C# 从服务器下载文件代码的几种方法
  5. javascript——继承
  6. C# 基础 知识点
  7. 【CSS中width、height的默认值】
  8. C#三层开发做学生管理系统
  9. 委托与Lambda-浅谈
  10. php_mysql、php_mysqli 与 pdo_mysql 的区别与选择
  11. UVA 10131 Is Bigger Smarter?(DP)
  12. jQuery checkbox 全选
  13. 2292: 【POJ Challenge 】永远挑战
  14. this final 关键字
  15. IdentityServer4 中文文档
  16. Winsock API编程介绍
  17. 图解Redis之数据结构篇——简单动态字符串SDS
  18. arm-linux-ld:u-boot.lds:1: ignoring invalid character `#&#39; in expression
  19. 带上RESTful的金手铐,你累吗?
  20. C#设计模式--设配器模式

热门文章

  1. 《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?
  2. 小程序的&lt;label&gt;标签
  3. Node: 使用nrm管理npm源
  4. Dijkstra求解单源最短路径
  5. Java之函数式接口@FunctionalInterface详解(附源码)
  6. Xmind8 Pro 破解教程(序列号|破解文件)
  7. layui+springmvc实现文件异步上传
  8. 在Anaconda3下安装(CPU版)TensorFlow(清华镜像源)
  9. 详解隐马尔可夫模型(HMM)中的维特比算法
  10. vscode 调试 react 项目