http://blog.csdn.net/lickylin/article/details/38326719

从现在开始学习路由相关的代码,在分析代码之前, 我们还是先分析数据结构,把数据结构之间的关系理解了以后,再理解代码就相对轻松多了。本小节先分析路由相关的数据结构。内核里面大多模块定义的数据结构之间一般都是使用链表或者hash表实现连接操作。

对于路由表,相关的数据结构有fib_table、fn_hash、fn_zone、fib_node、fib_alias、fib_info、fib_nh等, 下面分别介绍这几个数据结构

路由表结构,该结构为一个路由表的抽象,包括路由表的id、路由添加函数、路由查找函数、路由删除函数等

  1. struct fib_table {
  2. /*使用hash链表将多个路由表变量链接在一起*/
  3. struct hlist_node tb_hlist;
  4. /*表id*/
  5. u32  tb_id;
  6. unsigned    tb_stamp;
  7. /*路由查找函数*/
  8. int  (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
  9. /*路由插入函数*/
  10. int  (*tb_insert)(struct fib_table *, struct fib_config *);
  11. /*路由项删除函数*/
  12. int  (*tb_delete)(struct fib_table *, struct fib_config *);
  13. int  (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
  14. struct netlink_callback *cb);
  15. /*清空路由表的规则*/
  16. int  (*tb_flush)(struct fib_table *table);
  17. void     (*tb_select_default)(struct fib_table *table,
  18. const struct flowi *flp, struct fib_result *res);
  19. /*可变长数组,主要是用来指向掩码相关的hash数组*/
  20. unsigned char   tb_data[0];
  21. };

该结构主要用于描述以掩码划分的区域结构以及掩码区域之间的关系

对于ipv4来说,掩码可以为0-32共33种可能,因此对于一个fn_hash来说,则

定义了一个包含33个fn_zone的数组,而链表fn_zone_list,主要是将一个路由表里的

fn_zone链接在一起(以掩码大小的顺序排列,主要是在路由查找时,先匹配最长掩码对应的路由,以提高路由匹配的精确度)。

  1. struct fn_hash {
  2. struct fn_zone  *fn_zones[33];
  3. struct fn_zone  *fn_zone_list;
  4. };

以掩码划分的区域结构抽象,将掩码长度相同的所有路由放在同一个fn_zone中hash表中。

  1. struct fn_zone {
  2. /*指向下一个非空的fn_zone*/
  3. struct fn_zone   *fz_next;
  4. /*指向路由项关联的hash链表,对于掩码相关的目的ip地址,根据目的网络地址
  5. 的hash值,将新的fn_node节点插入到相应的hash链表中*/
  6. struct hlist_head   *fz_hash;   /* Hash table pointer   */
  7. /*fn_node结构变量的个数,fn_node并不能说是对一个路由项的抽象,可以看成对一个
  8. 目的网络地址的抽象,而对于相同的目的网络地址,可以根据tos、priority、mark值创建
  9. 不同的路由,所以一个fn_node结构中fn_alias才能算作是对一个路由项的抽象*/
  10. int  fz_nent;   /* Number of entries    */
  11. /*该fn_zone中fz_hash链表的个数*/
  12. int  fz_divisor;    /* Hash divisor  */
  13. /*fz_hash的mask值*/
  14. u32  fz_hashmask;   /* (fz_divisor - 1) */
  15. #define FZ_HASHMASK(fz)  ((fz)->fz_hashmask)
  16. /*以上两个值用于fz_hash数组的容量扩充相关*/
  17. /*该fn_zone对应的掩码长度*/
  18. int  fz_order;  /* Zone order    */
  19. /*根据fz_order而得到的掩码值*/
  20. __be32   fz_mask;
  21. /*获取该fn_zone对应的掩码值*/
  22. #define FZ_MASK(fz)  ((fz)->fz_mask)
  23. };

抽象为一个目的网络地址相同的所有路由项的基础结构,其中的fn_alias,表示该结构所包含的已存在的路由项的链表,fn_key为该结构对应的目的网络地址值,

用于和掩码长度相同的其他fib_node区分,对于同一个fn_zone里的fib_node,都链接到fn_zone->fz_hash中相应的hash表中

  1. struct fib_node {
  2. /*用于将hash值相同,且目的网络地址值不同,且网络掩
  3. 码相同的fib_node变量链接在一起*/
  4. struct hlist_node   fn_hash;
  5. struct list_head    fn_alias;
  6. __be32   fn_key;
  7. };

该结构可以理解为一个路由项的抽象。

当路由项的目的网络地址相同时,可以根据这个结构变量区分不同的路由项。包括tos、type、scope、state以及fib_info来区分一个路由项

方法:

1.首先根据tos、type、scope等确定一个fib_alias

2.当fib_alias确定以后,再根据priority等值确定一个fib_info,

3.根据fib_info确定出口设备与下一跳网关的ip地址。

  1. struct fib_alias {
  2. struct list_head    fa_list;
  3. struct rcu_head rcu;
  4. struct fib_info  *fa_info;
  5. u8   fa_tos;
  6. u8   fa_type;
  7. u8   fa_scope;
  8. u8   fa_state;
  9. };

而fa_scope表示路由的scope,取值范围如下:

RT_SCOPE_UNIVERSE:该选项用于所有通向非直连目的地的路由表项,即

应用层创建的路由中包含via的路由

RT_SCOPE_LINK:该选项用于目的地址为本地网络的路由项

RT_SCOPE_HOST:该选项用于路由为本机接口,

RT_SCOPE_NOWHERE:该选项用于路由不可到达

  1. enum rt_scope_t
  2. {
  3. RT_SCOPE_UNIVERSE=0,
  4. /* User defined values  */
  5. RT_SCOPE_SITE=200,
  6. RT_SCOPE_LINK=253,
  7. RT_SCOPE_HOST=254,
  8. RT_SCOPE_NOWHERE=255
  9. };

功能:主要是用来获取出口设备以及下一跳网关的数据结构,以及路由项的优先级,路由创建协议fib_protocol(RTPROTO_KERNEL、RTPROTO_BOOT、RTPROTO_STATIC等取值)。而fib_hash与fib_lhash则是将fib_info链接到对应的hash链表fib_info_hash[]与fib_info_laddrhash[]中去的。

  1. struct fib_info {
  2. /*这两个指针用于将该fib_info链接到hash链表中*/
  3. struct hlist_node   fib_hash;
  4. struct hlist_node   fib_lhash;
  5. int  fib_treeref;
  6. atomic_t     fib_clntref;
  7. /*标识是否将要释放该fib_info变量*/
  8. int  fib_dead;
  9. unsigned     fib_flags;
  10. int  fib_protocol;
  11. __be32   fib_prefsrc;
  12. /*优先级*/
  13. u32  fib_priority;
  14. u32  fib_metrics[RTAX_MAX];
  15. #define fib_mtu fib_metrics[RTAX_MTU-1]
  16. #define fib_window fib_metrics[RTAX_WINDOW-1]
  17. #define fib_rtt fib_metrics[RTAX_RTT-1]
  18. #define fib_advmss fib_metrics[RTAX_ADVMSS-1]
  19. /*fib_nh变量的个数*/
  20. int  fib_nhs;
  21. #ifdef CONFIG_IP_ROUTE_MULTIPATH
  22. int  fib_power;
  23. #endif
  24. #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
  25. u32  fib_mp_alg;
  26. #endif
  27. /*可变长度数组,用于动态申请fib_nh内存空间*/
  28. struct fib_nh    fib_nh[0];
  29. #define fib_dev  fib_nh[0].nh_dev
  30. };

包含下一跳网关及出口设备的结构

  1. struct fib_nh {
  2. /*数据包输出设备接口*/
  3. struct net_device   *nh_dev;
  4. /*将fib_nh变量链接在hash链表中*/
  5. struct hlist_node   nh_hash;
  6. /*包含该变量的fib_info变量*/
  7. struct fib_info  *nh_parent;
  8. unsigned     nh_flags;
  9. unsigned char    nh_scope;
  10. #ifdef CONFIG_IP_ROUTE_MULTIPATH
  11. int  nh_weight;
  12. int  nh_power;
  13. #endif
  14. #ifdef CONFIG_NET_CLS_ROUTE
  15. __u32    nh_tclassid;
  16. #endif
  17. /*出口设备的index*/
  18. int  nh_oif;
  19. /*下一跳网关地址*/
  20. __be32   nh_gw;
  21. };

而nh_hash是用来将fib_nh变量链接到对应的fib_info_devhash[]链表中的。

以上就是相应的数据结构分析,下面是这些数据结构之间的逻辑关系。没有给出fib_info_hash[]、fib_info_laddrhash[]与fib_info之间的,也没有给出fib_nh与fib_info_devhash之间的关系

以上就是路由相关的数据结构,下一节开始分析路由的添加与删除等功能。以上分析的数据结构没有包含路由缓存相关的数据结构,等到介绍到路由缓存时再进行分析。

Linux 路由 学习笔记 之一 相关的数据结构的更多相关文章

  1. Linux系统学习笔记:文件I/O

    Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...

  2. linux kernel学习笔记-5内存管理_转

    void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...

  3. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  4. Linux命令学习笔记目录

    Linux命令学习笔记目录 最近正在使用,linux,顺便将用到的命令整理了一下. 一. 文件目录操作命令: 0.linux命令学习笔记(0):man 命令 1.linux命令学习笔记(1):ls命令 ...

  5. 尚硅谷韩顺平Linux教程学习笔记

    目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...

  6. linux 驱动学习笔记01--Linux 内核的编译

    由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...

  7. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  8. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  9. MySQL学习笔记-事务相关话题

    事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...

随机推荐

  1. redis之闪电内幕

    一.简介和应用 二.Redis的对象redisObject 三.String 四.List 4.1 linkedlist(双端链表) 4.2 ziplist(压缩列表) 五.Hash 六.Set 七. ...

  2. .Net Core如何在程序的任意位置使用和注入服务

    最近有人问我:我该如何在Startup类之外的地方注入我的服务呢,都写在startup里看着好乱:我该如何在程序的其他地方获取我注入的服务呢: 故我写了这篇博客,文中有不对的地方欢迎指正. 一.如何在 ...

  3. 第6章 AOP与全局异常处理6.1-6.4 慕课网微信小程序开发学习笔记

    第6章 AOP与全局异常处理 https://coding.imooc.com/learn/list/97.html 目录: 第6章 AOP与全局异常处理6-1 正确理解异常处理流程 13:236-2 ...

  4. 大数据学习--day10(继承-权限-super-final-多态-组合)

    继承-权限-super-final-多态-组合 权限修饰符     内容         public         protected         default(不写就是它)         ...

  5. Scala基本语法总结(一)

    Scala基本语法总结 时隔快一年了,又捡起scala,不是想学的有多么的精通,只是想把之前遇到的知识点和实践中遇到的重点进行归纳总结,对以后的面试或许有点帮助吧! 一.scala开发环境的配置 我这 ...

  6. python3 练习题100例 (九)

    题目九:题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?程序分析:兔子的规律为数列1,1,2,3,5 ...

  7. python教程(二)·条件语句

    条件语句一般用来判断给定的条件是否成立,根据结果来执行不同的代码,也就是说,有了条件语句,才可以根据不同的情况做不同的事,从而控制程序的流程. 布尔类型 前面说到数据类型的时候,其中有一种叫 &quo ...

  8. P2257 YY的GCD

    P2257 YY的GCD 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 k ...

  9. HDOJ:6333-Problem B. Harvest of Apples(组合数学+莫队算法+逆元)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333 解题心得: 这个题可以说是十分精彩了,首先推组合数学的公式,其中一个很重要的公式是Cnm = C ...

  10. OpenCV 3.2 Viz 3D可视化

    该可视化模块提供了坐标系变化,3D动画等功能 最简单的显示坐标系 viz::Viz3d window("window"); window.showWidget("Coor ...