http://blog.csdn.net/lickylin/article/details/38326719
 
从现在开始学习路由相关的代码,在分析代码之前, 我们还是先分析数据结构,把数据结构之间的关系理解了以后,再理解代码就相对轻松多了。本小节先分析路由相关的数据结构。内核里面大多模块定义的数据结构之间一般都是使用链表或者hash表实现连接操作。
对于路由表,相关的数据结构有fib_table、fn_hash、fn_zone、fib_node、fib_alias、fib_info、fib_nh等, 下面分别介绍这几个数据结构
 
路由表结构,该结构为一个路由表的抽象,包括路由表的id、路由添加函数、路由查找函数、路由删除函数等
 
- struct fib_table {  
- struct hlist_node tb_hlist;  
- u32  tb_id;  
- unsigned    tb_stamp;  
- int  (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);  
- int  (*tb_insert)(struct fib_table *, struct fib_config *);  
- int  (*tb_delete)(struct fib_table *, struct fib_config *);  
- int  (*tb_dump)(struct fib_table *table, struct sk_buff *skb,  
-      struct netlink_callback *cb);  
- int  (*tb_flush)(struct fib_table *table);  
- void     (*tb_select_default)(struct fib_table *table,  
-      const struct flowi *flp, struct fib_result *res);  
-    
- unsigned char   tb_data[0];  
- };  
 
 
该结构主要用于描述以掩码划分的区域结构以及掩码区域之间的关系
对于ipv4来说,掩码可以为0-32共33种可能,因此对于一个fn_hash来说,则
定义了一个包含33个fn_zone的数组,而链表fn_zone_list,主要是将一个路由表里的
fn_zone链接在一起(以掩码大小的顺序排列,主要是在路由查找时,先匹配最长掩码对应的路由,以提高路由匹配的精确度)。
 
 
- struct fn_hash {  
- struct fn_zone  *fn_zones[33];  
- struct fn_zone  *fn_zone_list;  
- };  
 
 
以掩码划分的区域结构抽象,将掩码长度相同的所有路由放在同一个fn_zone中hash表中。
 
- struct fn_zone {  
- struct fn_zone   *fz_next;  
-    
- struct hlist_head   *fz_hash;   
-    
- int  fz_nent;   
-    
- int  fz_divisor;    
- u32  fz_hashmask;   
- #define FZ_HASHMASK(fz)  ((fz)->fz_hashmask)  
-    
-    
- int  fz_order;  
- __be32   fz_mask;  
- #define FZ_MASK(fz)  ((fz)->fz_mask)  
- };  
 
 
 
 
 
抽象为一个目的网络地址相同的所有路由项的基础结构,其中的fn_alias,表示该结构所包含的已存在的路由项的链表,fn_key为该结构对应的目的网络地址值,
用于和掩码长度相同的其他fib_node区分,对于同一个fn_zone里的fib_node,都链接到fn_zone->fz_hash中相应的hash表中
 
 
- struct fib_node {  
-     
- struct hlist_node   fn_hash;  
- struct list_head    fn_alias;  
- __be32   fn_key;  
- };  
 
 
 
该结构可以理解为一个路由项的抽象。
当路由项的目的网络地址相同时,可以根据这个结构变量区分不同的路由项。包括tos、type、scope、state以及fib_info来区分一个路由项
 
方法:
1.首先根据tos、type、scope等确定一个fib_alias
2.当fib_alias确定以后,再根据priority等值确定一个fib_info,
3.根据fib_info确定出口设备与下一跳网关的ip地址。
 
- struct fib_alias {  
- struct list_head    fa_list;  
- struct rcu_head rcu;  
- struct fib_info  *fa_info;  
- u8   fa_tos;  
- u8   fa_type;  
- u8   fa_scope;  
- u8   fa_state;  
- };  
 
而fa_scope表示路由的scope,取值范围如下:
RT_SCOPE_UNIVERSE:该选项用于所有通向非直连目的地的路由表项,即
                              应用层创建的路由中包含via的路由                       
RT_SCOPE_LINK:该选项用于目的地址为本地网络的路由项
RT_SCOPE_HOST:该选项用于路由为本机接口,
RT_SCOPE_NOWHERE:该选项用于路由不可到达                                
 
- enum rt_scope_t  
- {  
- RT_SCOPE_UNIVERSE=0,  
- RT_SCOPE_SITE=200,  
- RT_SCOPE_LINK=253,  
- RT_SCOPE_HOST=254,  
- RT_SCOPE_NOWHERE=255  
- };  
 
 
 
 
 
 
功能:主要是用来获取出口设备以及下一跳网关的数据结构,以及路由项的优先级,路由创建协议fib_protocol(RTPROTO_KERNEL、RTPROTO_BOOT、RTPROTO_STATIC等取值)。而fib_hash与fib_lhash则是将fib_info链接到对应的hash链表fib_info_hash[]与fib_info_laddrhash[]中去的。
 
- struct fib_info {  
- struct hlist_node   fib_hash;  
- struct hlist_node   fib_lhash;  
- int  fib_treeref;  
- atomic_t     fib_clntref;  
- int  fib_dead;  
- unsigned     fib_flags;  
- int  fib_protocol;  
- __be32   fib_prefsrc;  
- u32  fib_priority;  
- u32  fib_metrics[RTAX_MAX];  
- #define fib_mtu fib_metrics[RTAX_MTU-1]  
- #define fib_window fib_metrics[RTAX_WINDOW-1]  
- #define fib_rtt fib_metrics[RTAX_RTT-1]  
- #define fib_advmss fib_metrics[RTAX_ADVMSS-1]  
- int  fib_nhs;  
- #ifdef CONFIG_IP_ROUTE_MULTIPATH  
- int  fib_power;  
- #endif  
- #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED  
- u32  fib_mp_alg;  
- #endif  
-     
- struct fib_nh    fib_nh[0];  
- #define fib_dev  fib_nh[0].nh_dev  
- };  
 
 
 
 
 
包含下一跳网关及出口设备的结构
 
- struct fib_nh {  
-     
- struct net_device   *nh_dev;  
- struct hlist_node   nh_hash;  
- struct fib_info  *nh_parent;  
- unsigned     nh_flags;  
- unsigned char    nh_scope;  
- #ifdef CONFIG_IP_ROUTE_MULTIPATH  
- int  nh_weight;  
- int  nh_power;  
- #endif  
- #ifdef CONFIG_NET_CLS_ROUTE  
- __u32    nh_tclassid;  
- #endif  
- int  nh_oif;  
- __be32   nh_gw;  
- };  
 
而nh_hash是用来将fib_nh变量链接到对应的fib_info_devhash[]链表中的。
 
以上就是相应的数据结构分析,下面是这些数据结构之间的逻辑关系。没有给出fib_info_hash[]、fib_info_laddrhash[]与fib_info之间的,也没有给出fib_nh与fib_info_devhash之间的关系
 

 
以上就是路由相关的数据结构,下一节开始分析路由的添加与删除等功能。以上分析的数据结构没有包含路由缓存相关的数据结构,等到介绍到路由缓存时再进行分析。
 
Linux 路由 学习笔记 之一 相关的数据结构
原文:http://www.cnblogs.com/virusolf/p/4358336.html