对于策略规则的功能模块来说,其查找函数是始于通用策略规则模块的fib_rules_lookup。
这个函数的功能是策略路由对应的路由查找函数
1.遍历传入的ops变量的rules_list链表,对于每一个fib_rule
a)调用fib_rule_match进行fib_rule规则匹配
i)当规则匹配后,则调用传入的ops变量的函数指针action进行
路由项的查找(对于ipv4,fib4_rules_ops->action即为fib4_rule_action),当路由
查找到后,则会调用fib_rule_get增加对匹配规则的引用计数,并
将arg->rule指向该规则的首地址
在fib_rule_match中,在完成了通用参数的match后,会调用协议相关的match函数,
对协议相关的参数进行match。而对于ipv4的match函数即为fib4_rule_match。
在match到相应的fib rule后,即会调用协议相关的action函数,进行action操作,对于ipv4而言,即是fib4_rule_action。
fib_rule的action有FR_ACT_TO_TBL、FR_ACT_BLACKHOLE等,而我们使用fib rule主要是进行策略路由的,
因此,其action一般都是 FR_ACT_TO_TBL。基于策略路由的功能,我们 可以猜测fib4_rule_action函数
主要是根据table id找到相应的路由表,然后再调用路由表的查找函数,根据传入的条件,
查找符合要求的路由,我们接着来分析一下fib4_rule_action是否与我们猜测的一样。
int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
int flags, struct fib_lookup_arg *arg)
{
struct fib_rule *rule;
int err;
rcu_read_lock();
list_for_each_entry_rcu(rule, ops->rules_list, list) {
if (!fib_rule_match(rule, ops, fl, flags))
continue;
err = ops->action(rule, fl, flags, arg);
if (err != -EAGAIN) {
fib_rule_get(rule);
arg->rule = rule;
goto out;
}
}
err = -ESRCH;
out:
rcu_read_unlock();
return err;
}
上面函数在查找时,调用了通用规则的匹配函数,那下面我们就分析通用规则的匹配函数
对于这个功能,是通过函数fib_rule_match实现的(其实该函数通过调用协议相关的match函数也完成了协议相关的参数的匹配,此处这样说有些不妥),下面分析这个函数
fib_rule_match函数首先会进行通用参数的match,主要是包括接口index、fwmark等match。接着才会调用协议相关的match函数,对协议相关的参数进行match操作。
这个函数完成的功能如下:
对于传入的struct fib_rule *结构的指针rule,与传入的路由查找相关的struct flowi *
结构的指针fl
1.判断输入接口的index是否相等
2.判断mark值是否相等
3.调用函数ops->match继续进行fib_rule规则的匹配,对于ipv4,即为函数fib4_rule_match
4.如果fib_rule的规则是取反时,则返回的结果也需要进行取反操作
(不过目前通过ip rule添加的规则是不允许使用取反的,所以第四个判断操作目前
来说均是返回ret)
*/
static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
struct flowi *fl, int flags)
{
int ret = 0;
if (rule->ifindex && (rule->ifindex != fl->iif))
goto out;
if ((rule->mark ^ fl->mark) & rule->mark_mask)
goto out;
/*对于ipv4协议,其match函数为fib4_rule_match*/
ret = ops->match(rule, fl, flags);
out:
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
}
上面函数的通用规则的匹配函数里,调用了协议相关的策略规则匹配函数,下面我们就分析下ipv4协议相关的策略规则的匹配
对于ipv4,其协议相关的match函数为fib4_rule_match函数,我们分析一下这个函数。
这个函数主要是对源ip地址、目的ip地址以及tos的匹配操作。
(fib rule的添加类似于如下命令:
# ip rule add fwmark 0x4/0x40004 from 192.168.1.1/32 to 192.168.33.9/24 tos 10
iif br0 table 231)
static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
{
struct fib4_rule *r = (struct fib4_rule *) rule;
__be32 daddr = fl->fl4_dst;
__be32 saddr = fl->fl4_src;
if (((saddr ^ r->src) & r->srcmask) ||
((daddr ^ r->dst) & r->dstmask))
return 0;
if (r->tos && (r->tos != fl->fl4_tos))
return 0;
return 1;
}
在通用规则的查找函数里,当规则匹配成功后,就会调用协议相关的action函数,下面我们就分析一下这个函数。
在分析v4协议相关的策略规则ops的action操作之前,我们先看下的策略规则的action类型有哪些
/*fib rule的action类型,FR_ACT_TO_TBL即该fib rule与路由表关联*/
enum
{
FR_ACT_UNSPEC,
FR_ACT_TO_TBL, /* Pass to fixed table */
FR_ACT_RES1,
FR_ACT_RES2,
FR_ACT_RES3,
FR_ACT_RES4,
FR_ACT_BLACKHOLE, /* Drop without notification */
FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
FR_ACT_PROHIBIT, /* Drop with EACCES */
__FR_ACT_MAX,
};
当我们建立一个策略规则,且与路由表的id关联时,即是选择了action FR_ACT_TO_TBL,对于策略路由来说,肯定是这个action的。
下面分析下v4的action函数fib4_rule_action
1.根据rule的action规则决定后续操作,对于支持策略路由而言,我们建立fib rule的
action均是FR_ACT_TO_TBL,而对于FR_ACT_UNREACHABLE、
FR_ACT_PROHIBIT、FR_ACT_BLACKHOLE等均是返回相应的失败码。而对于 FR_ACT_TO_TBL,则需要进一步进行路由项的查找
2.对于FR_ACT_TO_TBL,则根据fib_rule->table的table id值,调用函数fib_get_table 获取相应的路由表,接着就是调用路由表的查找路由函数tb_lookup进行路由项的 查找,对于ipv4其路由表的tb_lookup即为函数fn_hash_lookup
static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
int flags, struct fib_lookup_arg *arg)
{
int err = -EAGAIN;
struct fib_table *tbl;
switch (rule->action) {
case FR_ACT_TO_TBL:
break;
case FR_ACT_UNREACHABLE:
err = -ENETUNREACH;
goto errout;
case FR_ACT_PROHIBIT:
err = -EACCES;
goto errout;
case FR_ACT_BLACKHOLE:
default:
err = -EINVAL;
goto errout;
}
if ((tbl = fib_get_table(rule->table)) == NULL)
goto errout;
err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
if (err > 0)
err = -EAGAIN;
errout:
return err;
}
这个函数会根据策略规则绑定的路由表id,通过函数fib_get_table找到相应的路由表,然后再根据路由表的tb_lookup函数进行路由项的匹配操作。而对于路由的查找,我们在上面已经分析过了,此处不再赘述。
至此,分析完了策略规则的匹配。