- 全局散列表net->ipv4.fib_table_hash中,存放所有的路由表fib_table;
结构体fib_alias
相同网段的每一条路由表项有各自的fib_alias结构;多个fib_alias可以共享一个fib_info结构;
struct fib_alias
struct list_head fa_list; |
//将所有fib_alias组成的链表 |
struct fib_info *fa_info; |
//指向fib_info,储存如何处理路由信息 |
u8 fa_tos; |
//路由的服务类型比特位字段 |
u8 fa_type; |
//路由表项的类型,间接定义了当路由查找匹配时,应采取的动作 |
u8 fa_scope; |
//路由表项的作用范围 |
u8 fa_state; |
//一些标志位,目前只有FA_S_ACCESSED。表示该表项已经被访问过。 |
结构体fib_info
结构体Fib_info存储真正重要路由信息,即如何到达目的地。
struct fib_info
struct hlist_node fib_hash; |
//所有fib_info组成的散列表,该表为全局散列表fib_info_hash |
struct hlist_node fib_lhash; |
//当存在首源地址时,才会将fib_info插入该散列表,该表为全局散列表fib_info_laddrhash |
struct net *fib_net; |
|
Int fib_treeref; |
//使用该fib_info结构的fib_node的数目 |
atomic_t fib_clntref; |
//引用计数。路由查找成功而被持有的引用计数 |
Int fib_dead; |
//标记路由表项正在被删除的标志,当该标志被设置为1时,警告该数据结构将被删除而不能再使用 |
Unsigned fib_flags; |
//当前使用的唯一标志是RTNH_F_DEAD,表示下一跳已无效 |
Int fib_protocol; |
//设置路由的协议 |
__be32 fib_prefsrc; |
//首选源IP地址 |
u32 fib_priority; |
//路由优先级,默认为0,值越小优先级越高 |
u32 fib_metrics[RTAX_MAX]; |
//与路由相关的度量值 |
Int fib_nhs; |
//可用的下一跳数量,通常为1.只有支持多路径路由时,才大于1 |
struct fib_nh fib_nh[0]; |
//表示路由的下一跳 |
结构体fib_nh
该结构体中存放着下一跳路由的地址nh_gw。
struct fib_nh
struct net_device *nh_dev; |
//该路由表项输出网络设备 |
struct hlist_node nh_hash; |
//fib_nh组成的散列表 |
struct fib_info *nh_parent; |
//指向所属fib_info结构体 |
struct fib_info *nh_parent; |
|
Unsigned nh_flags; |
|
unsigned char nh_scope; |
|
Int nh_oif; |
//输出网络设备索引 |
__be32 nh_gw; |
//网关地址 |
策略规则结构体fib_rule
struct fib_rule { struct list_head list; int iifindex;//接 口 index int oifindex;// out 接口index u32 mark;//mark 值 u32 mark_mask;//mark 掩 码 值 u32 flags; u32 table;//路由表id u8 action;//规则 /* 3 bytes hole, try to use */ u32 target; __be64 tun_id; struct fib_rule __rcu *ctarget; struct net *fr_net; atomic_t refcnt;//引 用 计 数 u32 pref;//优先级, 值越小优先级越大 int suppress_ifgroup; int suppress_prefixlen; char iifname[IFNAMSIZ];//入接 口 名 称 char oifname[IFNAMSIZ];//出接 口 名 称 struct rcu_head rcu; };
策略操作函数fib_rules_ops
struct fib_rules_ops { int family;//对应协议簇 struct list_head list;//将注册到系统的fib_rules_ops链接到链表rules_ops int rule_size;//一个策略规则所占用的内存大小 int addr_size;//协议相关的地址长度 int unresolved_rules; int nr_goto_rules; //action函数,策略规则匹配后,所调用的action函数,执行后续的操作。 //一般是获取到相应的路由表,查找符合要求的路由项 int (*action)(struct fib_rule *, struct flowi *, int, struct fib_lookup_arg *); bool (*suppress)(struct fib_rule *, struct fib_lookup_arg *); //规则匹配函数,对于策略规则的匹配,首先是通用匹配,待通用匹配完成后, //则会调用该函数,进行协议相关参数(源、目的地址等)的匹配 int (*match)(struct fib_rule *, struct flowi *, int); //协议相关的配置参数 int (*configure)(struct fib_rule *, struct sk_buff *, struct fib_rule_hdr *, struct nlattr **); int (*delete)(struct fib_rule *); int (*compare)(struct fib_rule *, struct fib_rule_hdr *, struct nlattr **); int (*fill)(struct fib_rule *, struct sk_buff *, struct fib_rule_hdr *); size_t (*nlmsg_payload)(struct fib_rule *); /* Called after modifications to the rules set, must flush * the route cache if one exists. */ void (*flush_cache)(struct fib_rules_ops *ops); int nlgroup; const struct nla_policy *policy; struct list_head rules_list;//将该协议簇已添加的所有fib_rule规则链接在一起 struct module *owner; struct net *fro_net; struct rcu_head rcu; };
ipv4类型的策略规则
IPV4协议相关的fib4_rule结构,该结构包含了基础的fib_rule,增加源IP、目的IP、tos等相关IPV4成员
struct fib4_rule//ipv4相关的结构 { struct fib_rule common; u8 dst_len; u8 src_len; u8 tos; __be32 src;//源ip __be32 srcmask; __be32 dst;//目的ip __be32 dstmask; #ifdef CONFIG_NET_CLS_ROUTE u32 tclassid; #endif }; rule4->src_len = frh->src_len; rule4->srcmask = inet_make_mask(rule4->src_len); rule4->dst_len = frh->dst_len; rule4->dstmask = inet_make_mask(rule4->dst_len); rule4->tos = frh->tos;
路由策略初始化
IPV4协议相关初始化fib4_rules_init
功能:(1)注册fib4_rules_ops
(2)创建local、main、default规则表,添到rules_list
(3)将fib4_rules_ops添到rules_ops中。
static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = { .family = AF_INET, .rule_size = sizeof(struct fib4_rule), .addr_size = sizeof(u32), .action = fib4_rule_action, .suppress = fib4_rule_suppress, .match = fib4_rule_match, .configure = fib4_rule_configure, .delete = fib4_rule_delete, .compare = fib4_rule_compare, .fill = fib4_rule_fill, .nlmsg_payload = fib4_rule_nlmsg_payload, .flush_cache = fib4_rule_flush_cache, .nlgroup = RTNLGRP_IPV4_RULE, .policy = fib4_rule_policy, .owner = THIS_MODULE, }; int __net_init fib4_rules_init(struct net *net) { int err; struct fib_rules_ops *ops; ops = fib_rules_register(&fib4_rules_ops_template, net); //执行kdump-memcpy 拷贝一份fib4_rules_ops_template 同时list 到net->rules_ops上去 err = fib_default_rules_init(ops);/*创建 local main default 对应的 fib_rule,最后list 到 fib_rules_ops->rules-list 链表上去, 也就是ipv4 只有一个rules-ops 但是有很多table fiber_rule*/ net->ipv4.rules_ops = ops; net->ipv4.fib_has_custom_rules = false; return 0; } static int fib_default_rules_init(struct fib_rules_ops *ops) { int err; err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, 0); err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0); err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0); } int fib_default_rule_add(struct fib_rules_ops *ops, u32 pref, u32 table, u32 flags) { struct fib_rule *r; r = kzalloc(ops->rule_size, GFP_KERNEL); atomic_set(&r->refcnt, 1); r->action = FR_ACT_TO_TBL; r->pref = pref; r->table = table; r->flags = flags; r->fr_net = ops->fro_net; r->suppress_prefixlen = -1; r->suppress_ifgroup = -1; /* The lock is not required here, the list in unreacheable * at the moment this function is called */ list_add_tail(&r->list, &ops->rules_list); return 0; }