zoukankan      html  css  js  c++  java
  • 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   }

  • 相关阅读:
    算法题(2):两个数组的交集
    git 的一些小 tips
    linux 命令 -- chmod
    linux 命令 -- alias 和 grep
    docker 学习笔记(2)
    docker 学习笔记(1)
    redis 学习笔记(2)
    redis 学习笔记(1)
    对对象的list集合以excel表格导出
    字符串处理
  • 原文地址:https://www.cnblogs.com/yanhc/p/8922323.html
Copyright © 2011-2022 走看看