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 }