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. Spring异常重试框架Spring Retry

    Spring Retry支持集成到Spring或者Spring Boot项目中,而它支持AOP的切面注入写法,所以在引入时必须引入aspectjweaver.jar包. 快速集成的代码样例: @Con ...

  2. windows service 2012:搭建FTP服务器

    最近公司将服务器从线上移植到线下每次上传项目都要进入服务器感觉好麻烦, 所以就想搭建一个FTP的站点来管理项目,弄这个之前首先要关闭我们的windows service 2012 服务器的防火墙,只有 ...

  3. linux 操作系统之磁盘管理

    磁盘管理 存储设备:硬盘 , U盘 , 移动硬盘 , 光盘 , 软件. 组装一台电脑 无法被修改 df -h #查看磁盘分区的情况 , 可用的. 查看磁盘或者目录的内容 df “df” 常用的 “-i ...

  4. burp实时获取token

    在一些web网站里 会加入token来限制用户的一些操作 如果用户的请求里面没有这个token  那么我们的一些操作就会很麻烦 现在 我来演示一下burp如何自动更新token 首先 需要dvwa  ...

  5. Java 8 中有趣的操作 Stream

    Stream 不是java io中的stream 对象创建 我们没有必要使用一个迭代来创建对象,直接使用流就可以 String[] strs = {"haha","hoh ...

  6. python类的封装

    Python之类的封装 1. 什么是封装 装:往容器/名称空间里存入名字 封:代表将存放于名称空间中的名字给藏起来,这种隐藏对外不对内(怎么做到的,在下文解释) 2. 为何要封装 封数据属性:不想要给 ...

  7. go内建容器-字符和字符串操作

    1.基础定义 在基础语法篇提到过golang的rune相当于其他编程语言的char,其本质是一个int32(四字节),用[]rune来转换一个字符串时,得到的是个解码后的结果,存储在新开辟的[]run ...

  8. 教你阅读MSDN英文文档,迅速提升编程能力

    在教大家阅读英文文档之前,首先给大家明确一个概念.C#和.NET的区别? 有一定编程经验的同学应该多多少少知道这方面的概念,但是可能模糊,理解的不一定深刻.我在这里简单给出两者的基本定义: C#:仅仅 ...

  9. 20145234黄斐《Java程序设计》第二周学习总结

    教材学习内容总结 类型 Java可区分为基本类型(Primitive Type)和类类型(Class Type),其中类类型也叫参考类型(Reference Type). 字节类型,也叫byte类型, ...

  10. 成都Uber优步司机奖励政策(4月1日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...