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. git 完善使用中

    GIT 版本库控制: 第一步:Git 的账号注册 url :https://github.com/ 这是git的官网如果第一次打开会这样 中间红色圈内是注册 内容, 第一项是用户名 第二项是邮箱 第三 ...

  2. Flume:source和sink

    Flume – 初识flume.source和sink 目录基本概念常用源 Source常用sink 基本概念  什么叫flume? 分布式,可靠的大量日志收集.聚合和移动工具.  events ...

  3. Leecode刷题之旅-C语言/python-169求众数

    /* * @lc app=leetcode.cn id=169 lang=c * * [169] 求众数 * * https://leetcode-cn.com/problems/majority-e ...

  4. Go语言入门(一)特性、安装、环境搭建、第一个程序等

    Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性.谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮 ...

  5. 深入解析Dropout

    过拟合是深度神经网(DNN)中的一个常见问题:模型只学会在训练集上分类,这些年提出的许多过拟合问题的解决方案:其中dropout具有简单性并取得良好的结果: Dropout 上图为Dropout的可视 ...

  6. [原创]用python检测LVS real server状态实现HTTP高可用

    import httplib import os import time def check_http(i): try: conn=httplib.HTTPConnection(i, 80, time ...

  7. Zookeeper原理和实战开发经典视频教程 百度云网盘下载

    Zookeeper原理和实战开发 经典视频教程 百度云网盘下载 资源下载地址:http://pan.baidu.com/s/1o7ZjPeM   密码:r5yf   

  8. CC3200-LAUNCHXL驱动不能正常识别的问题

    1. 本次使用利尔达的CC3200底板,完全兼容官方CC3200-LAUNCHXL,如果上电之后驱动识别为2路串口,是有问题的.原因是FT2232外接的EEPROM没有烧写固件. 2. 安装FT_Pr ...

  9. 征战 OSG-序及目录

    其实很早就应该写这个了,一直拖到现在就是因为懒啊. 自从七月演习回来,被划到三维平台开发部,就一直混日子,也没人带领,也没人问结果,就这么一直堕落下来了,直到有一天才发现自己也看不上自己了,觉得自己这 ...

  10. AirtestIDE实践一:梦幻西游手游师门任务自动化

    Airtest Project是网易自研的游戏自动化项目.Airtest IDE是这个项目的一个IDE,就像Eclipse.Pycharm一样,是一个集成开发工具.Airtest框架是一个基于Open ...