路由表学习笔记

来源:互联网 发布:格式化工厂for mac 编辑:程序博客网 时间:2024/05/01 08:51

1、 路由表相关的数据结构

struct fib_table {

struct hlist_node tb_hlist;

u32 tb_id;//路由表id0-255

unsigned tb_stamp;

int tb_default;//()

int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);

//路由查找函数,会被初始化为fn_hash_lookup

int (*tb_insert)(struct fib_table *, struct fib_config *);

//路由插入函数,会被初始化为fn_hash_insert

int (*tb_delete)(struct fib_table *, struct fib_config *);

//路由删除函数,会被初始化为fn_hash_delete

int (*tb_dump)(struct fib_table *table, struct sk_buff *skb,

     struct netlink_callback *cb);

int (*tb_flush)(struct fib_table *table);

//路由flush函数,会被初始化为fn_hash_flush,将设置为RTNH_F_DEAD的fib_info结构的内存释放掉

void (*tb_select_default)(struct fib_table *table,

     const struct flowi *flp, struct fib_result *res);

 

unsigned char tb_data[0];

};

 

 

struct fn_hash {

struct fn_zone *fn_zones[33];//以网络掩码区分不同的子网,此处每一个fn_zone,代表网络掩码相同的子网

struct fn_zone *fn_zone_list;//fn_zone的链表头存储在该结构体中

};

 

struct fn_zone {

struct fn_zone *fz_next; /* Next not empty zone */

struct hlist_head *fz_hash; /* Hash table pointer */

int fz_nent; /* Number of entries */

 

int fz_divisor; /* Hash divisor */

u32 fz_hashmask; /* (fz_divisor - 1) */

#define FZ_HASHMASK(fz) ((fz)->fz_hashmask)

 

int fz_order; /* Zone order */

__be32 fz_mask;

#define FZ_MASK(fz) ((fz)->fz_mask)

};

struct fib_node {

struct hlist_node fn_hash;

struct list_head fn_alias;

__be32 fn_key;

struct fib_alias        fn_embedded_alias;

};

struct fib_alias {

struct list_head fa_list;

struct fib_info *fa_info;

u8 fa_tos;

u8 fa_type;

u8 fa_scope;

u8 fa_state;

#ifdef CONFIG_IP_FIB_TRIE

struct rcu_head rcu;

#endif

};

 

 

/*

 * This structure contains data shared by many of routes.

 */

 

struct fib_info {

struct hlist_node fib_hash; //用于链接fib_info,这样可以通过fib_find_info来实现快速查找fib_info

struct hlist_node fib_lhash;

struct net *fib_net;

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

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;

};

 

 

这些数据结构之间的关联如下(深入理解linux网络 一书中的图):




a) 在一个路由表中,是根据网络掩码来进行划分不同的网域,因此在一个路由表中,会有33fn_zone

b) 在网络掩码相同的网域中,根据子网值来进行进一步的划分(如192.168.1/24则,fn_key192.168.1)每一个子网对应于一个fib_node

c) 对于每一个特定子网,更进一步的划分依据是tos值、priorityscope等,,这对应于结构体fib_alias,fib_alias相关的链表以ip_tos的升序排列

d) 而fib_info就代表一条路由基本信息,在同一个fib_alias中,fib_info相关的链表以fib_priority的升序排列。

关于hash值的生成,是调用函数fn_hash生成的(将一个fn_zone中所有的fib_node根据生成的hash值,链接到不同的fn_zone-> fz_hash[]中)。

static inline u32 fn_hash(__be32 key, struct fn_zone *fz)

{

u32 h = ntohl(key)>>(32 - fz->fz_order);

h ^= (h>>20);

h ^= (h>>10);

h ^= (h>>5);

h &= FZ_HASHMASK(fz);

return h;

}

只要理解了上面的几个数据结构直接的关系,就能够很好的理解路由添加、删除等操作了(无非就是将路由信息添加到该数据表中)。

 

 

路由表的初始化

 

 

 

路由的添加:

ip route add 192.168.1.0/24 dev eth0 src 192.168.1.111

 

在函数ip_fib_init,会通过调用函数rtnl_register,将inet_rtm_newroute、inet_rtm_delroute

注册到到rtnl_msg_handlers[PF_INET][ RTM_NEWROUTE]. doit、

rtnl_msg_handlers[PF_INET][ RTM_DELROUTE]. doit中

这样当应用层通过rtnetlinkkernel层发送类型为RTM_NEWROUTE、RTM_DELROUTE的消息时,内核就会调用函数rtnetlink_rcv_msg找到正确的rtnl_msg_handlers[].doit,接着就会调用到函数inet_rtm_newroute、inet_rtm_delroute执行添加路由与删除路由的操作。

 



0 0