lwip nd

ND有4项缓存,对于前缀、邻居、目的、默认路由器。

对于缓存,现在了解的比较清楚了;

但,对于其它3项,邻居、目的、默认路由器,还不是太了解,

在ip6_route中,看到了对默认路由器的使用,对于全局地址,在通过LWIP_HOOK_IP6_ROUTE找不到路径时,会先看目的地址子网是否和本地接口的子网匹配,若否,会调用nd6_find_route,找到一个默认路由器。

若找不到默认路由器,再判源地址是否和本地接口匹配,若否,再判默认接口。

1 /* Router tables. */
2 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
3 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];
4 struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES];
5 struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS];

 

nd6_input

 1       case ND6_OPTION_TYPE_PREFIX_INFO:
 2       {
 3         struct prefix_option *prefix_opt;
 4         prefix_opt = (struct prefix_option *)buffer;
 5     必须ON_LINK,前缀长度必须为64,且不能为链路本地地址
 6         if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) &&
 7             (prefix_opt->prefix_length == 64)  &&
 8             !ip6_addr_islinklocal(&(prefix_opt->prefix))) {
 9           /* Add to on-link prefix list. */
10           s8_t prefix;
11           ip6_addr_t prefix_addr;
12 
13           /* Get a memory-aligned copy of the prefix. */
14           ip6_addr_set(&prefix_addr, &(prefix_opt->prefix));
15       查询之前有没有,没有的话,添加
16           /* find cache entry for this prefix. */
17           prefix = nd6_get_onlink_prefix(&prefix_addr, inp);
18           if (prefix < 0) {
19             /* Create a new cache entry. */
20             prefix = nd6_new_onlink_prefix(&prefix_addr, inp);
21           }
22           if (prefix >= 0) {
23             prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime);
24       flag里需要要自主
25 #if LWIP_IPV6_AUTOCONFIG
26             if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) {
27               /* Mark prefix as autonomous, so that address autoconfiguration can take place.
28                * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/
29               prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS;
30             }
31 #endif /* LWIP_IPV6_AUTOCONFIG */
32           }
33         }
34 
35         break;
36       }

添加新前缀的地方,前缀和netif是绑定的。

 1 static s8_t
 2 nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif)
 3 {
 4   s8_t i;
 5   默认存6个前缀,找到第一个netif为空的,或者已经失效的
 6   /* Create new entry. */
 7   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
 8     if ((prefix_list[i].netif == NULL) ||
 9         (prefix_list[i].invalidation_timer == 0)) {
10       /* Found empty prefix entry. */
11       prefix_list[i].netif = netif;
12       ip6_addr_set(&(prefix_list[i].prefix), prefix);
13 #if LWIP_IPV6_AUTOCONFIG
14       prefix_list[i].flags = 0;
15 #endif /* LWIP_IPV6_AUTOCONFIG */
16       return i;
17     }
18   }
19 
20   /* Entry not available. */
21   return -1;
22 }

 

nd6_tmr中,

遍历每个前缀,

  如果已经超时,那么,直接将无效时间设置为0,设置netif为空,删除该前缀,

          同时,判断该前缀是否生成过地址,若是,将生成的地址设为无效;

  如果未超时,那么,减无效时间,

          判断该netif是否允许自动配置,前缀flag是否自主,且前缀flag未生成过地址

            若均满足,则遍历该netif除link local外的其它地址,如果有无效的地址,那么,生成一个新的地址(前缀用这个,接口ID用链路本地地址)

 1   /* Process prefix entries. */
 2   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
 3     if (prefix_list[i].netif != NULL) {
 4       if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) {
 5         /* Entry timed out, remove it */
 6         prefix_list[i].invalidation_timer = 0;
 7 
 8 #if LWIP_IPV6_AUTOCONFIG
 9         /* If any addresses were configured with this prefix, remove them */
10         if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) {
11           s8_t j;
12 
13           for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) {
14             if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) &&
15                 ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) {
16               netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID);
17               prefix_list[i].flags = 0;
18 
19               /* Exit loop. */
20               break;
21             }
22           }
23         }
24 #endif /* LWIP_IPV6_AUTOCONFIG */
25 
26         prefix_list[i].netif = NULL;
27         prefix_list[i].flags = 0;
28       } else {
29         prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
30 
31 #if LWIP_IPV6_AUTOCONFIG
32         /* Initiate address autoconfiguration for this prefix, if conditions are met. */
33         if (prefix_list[i].netif->ip6_autoconfig_enabled &&
34             (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) &&
35             !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) {
36           s8_t j;
37           /* Try to get an address on this netif that is invalid.
38            * Skip 0 index (link-local address) */
39           for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) {
40             if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) {
41               /* Generate an address using this prefix and interface ID from link-local address. */
42               netif_ip6_addr_set_parts(prefix_list[i].netif, j,
43                 prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1],
44                 netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]);
45 
46               /* Mark it as tentative (DAD will be performed if configured). */
47               netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE);
48 
49               /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */
50               prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED;
51 
52               /* Exit loop. */
53               break;
54             }
55           }
56         }
57 #endif /* LWIP_IPV6_AUTOCONFIG */
58       }
59     }
60   }

 

 

 

posted on 2018-04-23 22:30  yanhc  阅读(298)  评论(0编辑  收藏  举报

导航