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

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

对于路由表,相关的数据结构有fib_tablefn_hashfn_zonefib_nodefib_aliasfib_infofib_nh等, 下面分别介绍这几个数据结构

 

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

struct fib_table {
/*使用hash链表将多个路由表变量链接在一起*/
struct hlist_node tb_hlist;
/*表id*/
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);
 
/*可变长数组,主要是用来指向掩码相关的hash数组*/
unsigned char	tb_data[0];
};


 

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

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

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

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

 

struct fn_hash {
struct fn_zone	*fn_zones[33];
struct fn_zone	*fn_zone_list;
};


 

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

struct fn_zone {
/*指向下一个非空的fn_zone*/
struct fn_zone	 *fz_next;
 
/*指向路由项关联的hash链表,对于掩码相关的目的ip地址,根据目的网络地址
的hash值,将新的fn_node节点插入到相应的hash链表中*/
struct hlist_head	*fz_hash;	/* Hash table pointer	*/
 
/*fn_node结构变量的个数,fn_node并不能说是对一个路由项的抽象,可以看成对一个
目的网络地址的抽象,而对于相同的目的网络地址,可以根据tos、priority、mark值创建
不同的路由,所以一个fn_node结构中fn_alias才能算作是对一个路由项的抽象*/
int	 fz_nent;	/* Number of entries	*/
 
/*该fn_zone中fz_hash链表的个数*/
int	 fz_divisor;	/* Hash divisor	 */
/*fz_hash的mask值*/
u32	 fz_hashmask;	/* (fz_divisor - 1)	*/
#define FZ_HASHMASK(fz)	 ((fz)->fz_hashmask)
   /*以上两个值用于fz_hash数组的容量扩充相关*/
 
/*该fn_zone对应的掩码长度*/
int	 fz_order;	/* Zone order	 */
/*根据fz_order而得到的掩码值*/
__be32	 fz_mask;
/*获取该fn_zone对应的掩码值*/
#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 {
    /*用于将hash值相同,且目的网络地址值不同,且网络掩
    码相同的fib_node变量链接在一起*/
struct hlist_node	fn_hash;
struct list_head	fn_alias;
__be32	 fn_key;
};


 

 

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

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

 

方法:

1.首先根据tostypescope等确定一个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,
/* User defined values  */
RT_SCOPE_SITE=200,
RT_SCOPE_LINK=253,
RT_SCOPE_HOST=254,
RT_SCOPE_NOWHERE=255
};


 

 

 

 

 

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

struct fib_info {
/*这两个指针用于将该fib_info链接到hash链表中*/
struct hlist_node	fib_hash;
struct hlist_node	fib_lhash;
int	 fib_treeref;
atomic_t	 fib_clntref;
/*标识是否将要释放该fib_info变量*/
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]
/*fib_nh变量的个数*/
int	 fib_nhs;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int	 fib_power;
#endif
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
u32	 fib_mp_alg;
#endif
    /*可变长度数组,用于动态申请fib_nh内存空间*/
struct fib_nh	 fib_nh[0];
#define fib_dev	 fib_nh[0].nh_dev
};


 

 

 

 

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

struct fib_nh {
    /*数据包输出设备接口*/
struct net_device	*nh_dev;
/*将fib_nh变量链接在hash链表中*/
struct hlist_node	nh_hash;
/*包含该变量的fib_info变量*/
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
/*出口设备的index*/
int	 nh_oif;
/*下一跳网关地址*/
__be32	 nh_gw;
};


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

 

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



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







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值