lwip nd没有实现ra,contik有参考

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间隔没限制

 1 /*---------------------------------------------------------------------------*/
 2 void
 3 uip_ds6_send_ra_periodic(void)
 4 {
 5   if(racount > 0) {
 6     /* send previously scheduled RA */
 7     uip_nd6_ra_output(NULL);
 8     PRINTF("Sending periodic RA
");
 9   }
10   /* rand_t = min + rand % (max - min) */
11   rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
12     (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
13   PRINTF("Random time 1 = %u
", rand_time);
14   /* intial ra interval = 16s, initial 3 ra, should not exceed initial_ra_interval */
15   if(racount < UIP_ND6_MAX_INITIAL_RAS) {
16     if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
17       rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
18       PRINTF("Random time 2 = %u
", rand_time);
19     }
20     racount++;
21   }
22   PRINTF("Random time 3 = %u
", rand_time);
23   stimer_set(&uip_ds6_timer_ra, rand_time);
24 }
25  

如果收到了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 = 0;
  PRINTF("Solicited RA, random time %u
", 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在这个文件中定义

 1 /*---------------------------------------------------------------------------*/
 2 static void
 3 rs_input(void)
 4 {
 5 
 6   PRINTF("Received RS from ");
 7   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
 8   PRINTF(" to ");
 9   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
10   PRINTF("
");
11   UIP_STAT(++uip_stat.nd6.recv);
12 
13 
14 #if UIP_CONF_IPV6_CHECKS
15   /*
16    * Check hop limit / icmp code
17    * target address must not be multicast
18    * if the NA is solicited, dest must not be multicast
19    */
20   if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
21     PRINTF("RS received is bad
");
22     goto discard;
23   }
24 #endif /*UIP_CONF_IPV6_CHECKS */
25 
26   /* Only valid option is Source Link-Layer Address option any thing
27      else is discarded */
28   nd6_opt_offset = UIP_ND6_RS_LEN;
29   nd6_opt_llao = NULL;
30 
31   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
32 #if UIP_CONF_IPV6_CHECKS
33     if(UIP_ND6_OPT_HDR_BUF->len == 0) {
34       PRINTF("RS received is bad
");
35       goto discard;
36     }
37 #endif /*UIP_CONF_IPV6_CHECKS */
38     switch (UIP_ND6_OPT_HDR_BUF->type) {
39     case UIP_ND6_OPT_SLLAO:
40       nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
41       break;
42     default:
43       PRINTF("ND option not supported in RS
");
44       break;
45     }
46     nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
47   }
48   /* Options processing: only SLLAO */
49   if(nd6_opt_llao != NULL) {
50 #if UIP_CONF_IPV6_CHECKS
51     if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
52       PRINTF("RS received is bad
");
53       goto discard;
54     } else {
55 #endif /*UIP_CONF_IPV6_CHECKS */
56       uip_lladdr_t lladdr_aligned;
57       extract_lladdr_from_llao_aligned(&lladdr_aligned);
58       if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
59         /* we need to add the neighbor */
60         uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
61                         0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
62       } else {
63         /* If LL address changed, set neighbor state to stale */
64         const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
65         if(lladdr == NULL) {
66           goto discard;
67         }
68         if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
69             lladdr, UIP_LLADDR_LEN) != 0) {
70           uip_ds6_nbr_t nbr_data;
71           nbr_data = *nbr;
72           uip_ds6_nbr_rm(nbr);
73           nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
74                                 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
75           nbr->reachable = nbr_data.reachable;
76           nbr->sendns = nbr_data.sendns;
77           nbr->nscount = nbr_data.nscount;
78         }
79         nbr->isrouter = 0;
80       }
81 #if UIP_CONF_IPV6_CHECKS
82     }
83 #endif /*UIP_CONF_IPV6_CHECKS */
84   }
85 
86   /* Schedule a sollicited RA */
87   uip_ds6_send_ra_sollicited();
88 
89 discard:
90   uip_clear_buf();
91   return;
92 }
  1 /*---------------------------------------------------------------------------*/
  2 void
  3 uip_nd6_ra_output(uip_ipaddr_t * dest)
  4 {
  5 
  6   UIP_IP_BUF->vtc = 0x60;
  7   UIP_IP_BUF->tcflow = 0;
  8   UIP_IP_BUF->flow = 0;
  9   UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
 10   UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
 11 
 12   if(dest == NULL) {
 13     uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
 14   } else {
 15     /* For sollicited RA */
 16     uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
 17   }
 18   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
 19 
 20   UIP_ICMP_BUF->type = ICMP6_RA;
 21   UIP_ICMP_BUF->icode = 0;
 22 
 23   UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
 24 
 25   UIP_ND6_RA_BUF->flags_reserved =
 26     (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
 27 
 28   UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
 29   //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
 30   //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
 31   UIP_ND6_RA_BUF->reachable_time = 0;
 32   UIP_ND6_RA_BUF->retrans_timer = 0;
 33 
 34   uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
 35   nd6_opt_offset = UIP_ND6_RA_LEN;
 36 
 37 
 38   /* Prefix list */
 39   for(prefix = uip_ds6_prefix_list;
 40       prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
 41     if((prefix->isused) && (prefix->advertise)) {
 42       UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
 43       UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
 44       UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
 45       UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
 46       UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
 47       UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
 48       UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
 49       uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
 50       nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
 51       uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
 52     }
 53   }
 54 
 55   /* Source link-layer option */
 56   create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
 57 
 58   uip_len += UIP_ND6_OPT_LLAO_LEN;
 59   nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
 60 
 61   /* MTU */
 62   UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
 63   UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
 64   UIP_ND6_OPT_MTU_BUF->reserved = 0;
 65   //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
 66   UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
 67 
 68   uip_len += UIP_ND6_OPT_MTU_LEN;
 69   nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
 70 
 71 #if UIP_ND6_RA_RDNSS
 72   if(uip_nameserver_count() > 0) {
 73     uint8_t i = 0;
 74     uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip;
 75     uip_ipaddr_t *dns = NULL;
 76     UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS;
 77     UIP_ND6_OPT_RDNSS_BUF->reserved = 0;
 78     UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration();
 79     if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
 80       UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds();
 81     }
 82     while((dns = uip_nameserver_get(i)) != NULL) {
 83       uip_ipaddr_copy(ip++, dns);
 84       i++;
 85     }
 86     UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
 87     PRINTF("%d nameservers reported
", i);
 88     uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3;
 89     nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3;
 90   }
 91 #endif /* UIP_ND6_RA_RDNSS */
 92 
 93   UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
 94   UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
 95 
 96   /*ICMP checksum */
 97   UIP_ICMP_BUF->icmpchksum = 0;
 98   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
 99 
100   UIP_STAT(++uip_stat.nd6.sent);
101   PRINTF("Sending RA to ");
102   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
103   PRINTF(" from ");
104   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
105   PRINTF("
");
106   return;
107 }

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

原文地址:https://www.cnblogs.com/yanhc/p/8542849.html