kernel中路由表的实现

分类: LINUX

原文地址:TCP/IP学习(41)——Kernel中路由表的实现(4) 作者:GFree_Wind

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
   


在昨天的查找函数中,还有一个函数没有学习,即check_leaf。
  1. /* should be called with rcu_read_lock */
  2. static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
  3.          t_key key, const struct flowi4 *flp,
  4.          struct fib_result *res, int fib_flags)
  5. {
  6.     struct leaf_info *li;
  7.     /* 
  8.     得到叶子节点的hlist_head.
  9.     所谓的hlist_head其实只是list_head的变种,只为了节省一个指针的空间。
  10.     其它的hlist_head的操作也类似于list_head的同等操作。
  11.     */
  12.     struct hlist_head *hhead = &l->list;
  13.     struct hlist_node *node;

     /* 遍历hlist */
  1.     hlist_for_each_entry_rcu(li, node, hhead, hlist) {
 /*struct leaf_info为hlist_node真正的数据 */

          /* 对于同一route,但其它参数不同如TOS等,这时使用fib_alias区分。*/
  1.         struct fib_alias *fa;
  2.         int plen = li->plen;
  3.         __be32 mask = inet_make_mask(plen);
          
          /* 比较目的地址 */
  1.         if (l->key != (key & ntohl(mask)))
  2.             continue;

  3.         list_for_each_entry_rcu(fa, &li->falh, fa_list) {
  4.             /* 获得route的info */
  5.             struct fib_info *fi = fa->fa_info;
  6.             int nhsel, err;
             
             /* 比较route的info,如tos,scope等*/
  1.             if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
  2.                 continue;
  3.             
  4.             if (fa->fa_info->fib_scope < flp->flowi4_scope)
  5.                 continue;
  6.             fib_alias_accessed(fa);
  7.             err = fib_props[fa->fa_type].error;
  8.             if (err) {
  9. #ifdef CONFIG_IP_FIB_TRIE_STATS
  10.                 t->stats.semantic_match_passed++;
  11. #endif
  12.                 return err;
  13.             }
  14.             if (fi->fib_flags & RTNH_F_DEAD)
  15.                 continue;
             /* 
             遍历该route的所有下一跳。
             一般情况下,route只有一个下一跳地址。但是如果enable了multiple path的话,一个route信息就
             可以有多个下一跳地址。
             */
  1.             for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
  2.                 const struct fib_nh *nh = &fi->fib_nh[nhsel];
                 /* 该下一跳不可用 */
  1.                 if (nh->nh_flags & RTNH_F_DEAD)
  2.                     continue;
                 /* 出口dev不匹配 */
  1.                 if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
  2.                     continue;

  3. #ifdef CONFIG_IP_FIB_TRIE_STATS
  4.                 t->stats.semantic_match_passed++;
  5. #endif
                 
                 /* ok。找到了一个合适的路由 */
  1.                 res->prefixlen = plen;
  2.                 res->nh_sel = nhsel;
  3.                 res->type = fa->fa_type;
  4.                 res->scope = fa->fa_info->fib_scope;
  5.                 res->fi = fi;
  6.                 res->table = tb;
  7.                 res->fa_head = &li->falh;
  8.                 if (!(fib_flags & FIB_LOOKUP_NOREF))
  9.                     atomic_inc(&res->fi->fib_clntref);
  10.                 return 0;
  11.             }
  12.         }

  13. #ifdef CONFIG_IP_FIB_TRIE_STATS
  14.         t->stats.semantic_match_miss++;
  15. #endif
  16.     }

  17.     return 1;
  18. }
学习完这个函数,trie方式的路由表查找过程就已结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值