Linux 路由 学习笔记 之七 策略规则的查找

上面分析了策略规则的添加,本文分析一下策略规则的查找。其实策略规则的存在就是为了实现策略路由功能的,而在策略路由的查找一节已经分析了策略规则的查找了,但为了在这一节单独分析策略规则,此处也一并再分析一下。

对于策略规则的功能模块来说,其查找函数是始于通用策略规则模块的fib_rules_lookup。

1通用规则的查找函数1.1fib_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到相应的fibrule后,即会调用协议相关的action函数,进行action操作,对于ipv4而言,即是fib4_rule_action。

fib_rule的action有FR_ACT_TO_TBL、FR_ACT_BLACKHOLE等,而我们使用fibrule主要是进行策略路由的,

因此,其action一般都是 FR_ACT_TO_TBL。基于策略路由的功能,我们可以猜测fib4_rule_action函数

主要是根据tableid找到相应的路由表,然后再调用路由表的查找函数,根据传入的条件,

查找符合要求的路由,我们接着来分析一下fib4_rule_action是否与我们猜测的一样。

intfib_rules_lookup(structfib_rules_ops*ops,structflowi*fl,

intflags,structfib_lookup_arg*arg)

{

structfib_rule*rule;

interr;

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;

gotoout;

}

}

err=-ESRCH;

out:

rcu_read_unlock();

returnerr;

}

上面函数在查找时,调用了通用规则的匹配函数,那下面我们就分析通用规则的匹配函数

1.2通用规则的匹配1.2.1fib_rule_match

对于这个功能,是通过函数fib_rule_match实现的(其实该函数通过调用协议相关的match函数也完成了协议相关的参数的匹配,此处这样说有些不妥),下面分析这个函数

fib_rule_match函数首先会进行通用参数的match,主要是包括接口index、fwmark等match。接着才会调用协议相关的match函数,对协议相关的参数进行match操作。

这个函数完成的功能如下:

对于传入的structfib_rule*结构的指针rule,与传入的路由查找相关的structflowi*

结构的指针fl

1.判断输入接口的index是否相等

2.判断mark值是否相等

3.调用函数ops->match继续进行fib_rule规则的匹配,对于ipv4,即为函数fib4_rule_match

4.如果fib_rule的规则是取反时,则返回的结果也需要进行取反操作

(不过目前通过iprule添加的规则是不允许使用取反的,所以第四个判断操作目前

来说均是返回ret)

*/

staticintfib_rule_match(structfib_rule*rule,structfib_rules_ops*ops,

structflowi*fl,intflags)

{

intret=0;

if(rule->ifindex&&(rule->ifindex!=fl->iif))

gotoout;

if((rule->mark^fl->mark)&rule->mark_mask)

gotoout;

/*对于ipv4协议,其match函数为fib4_rule_match*/

ret=ops->match(rule,fl,flags);

out:

return(rule->flags&FIB_RULE_INVERT)?!ret:ret;

}

1.3协议相关的策略规则的匹配

上面函数的通用规则的匹配函数里,调用了协议相关的策略规则匹配函数,下面我们就分析下ipv4协议相关的策略规则的匹配

对于ipv4,其协议相关的match函数为fib4_rule_match函数,我们分析一下这个函数。

这个函数主要是对源ip地址、目的ip地址以及tos的匹配操作。

(fibrule的添加类似于如下命令:

#ipruleaddfwmark0x4/0x40004from192.168.1.1/32to192.168.33.9/24tos10

iifbr0table231)

staticintfib4_rule_match(structfib_rule*rule,structflowi*fl,intflags)

{

structfib4_rule*r=(structfib4_rule*)rule;

__be32daddr=fl->fl4_dst;

__be32saddr=fl->fl4_src;

if(((saddr^r->src)&r->srcmask)||

((daddr^r->dst)&r->dstmask))

return0;

if(r->tos&&(r->tos!=fl->fl4_tos))

return0;

return1;

}

在通用规则的查找函数里,当规则匹配成功后,就会调用协议相关的action函数,下面我们就分析一下这个函数。

1.4协议相关的action

在分析v4协议相关的策略规则ops的action操作之前,我们先看下的策略规则的action类型有哪些

/*fibrule的action类型,FR_ACT_TO_TBL即该fibrule与路由表关联*/

enum

{

FR_ACT_UNSPEC,

FR_ACT_TO_TBL, /*Passtofixedtable*/

FR_ACT_RES1,

FR_ACT_RES2,

FR_ACT_RES3,

FR_ACT_RES4,

FR_ACT_BLACKHOLE, /*Dropwithoutnotification*/

FR_ACT_UNREACHABLE, /*DropwithENETUNREACH*/

FR_ACT_PROHIBIT, /*DropwithEACCES*/

__FR_ACT_MAX,

};

当我们建立一个策略规则,且与路由表的id关联时,即是选择了actionFR_ACT_TO_TBL,对于策略路由来说,肯定是这个action的。

下面分析下v4的action函数fib4_rule_action

1.根据rule的action规则决定后续操作,对于支持策略路由而言,我们建立fibrule的

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的tableid值,调用函数fib_get_table 获取相应的路由表,接着就是调用路由表的查找路由函数tb_lookup进行路由项的 查找,对于ipv4其路由表的tb_lookup即为函数fn_hash_lookup

staticintfib4_rule_action(structfib_rule*rule,structflowi*flp,

intflags,structfib_lookup_arg*arg)

{

interr=-EAGAIN;

structfib_table*tbl;

switch(rule->action){

caseFR_ACT_TO_TBL:

break;

caseFR_ACT_UNREACHABLE:

err=-ENETUNREACH;

gotoerrout;

caseFR_ACT_PROHIBIT:

err=-EACCES;

gotoerrout;

caseFR_ACT_BLACKHOLE:

default:

err=-EINVAL;

gotoerrout;

}

if((tbl=fib_get_table(rule->table))==NULL)

gotoerrout;

err=tbl->tb_lookup(tbl,flp,(structfib_result*)arg->result);

if(err>0)

err=-EAGAIN;

errout:

returnerr;

}

这个函数会根据策略规则绑定的路由表id,通过函数fib_get_table找到相应的路由表,然后再根据路由表的tb_lookup函数进行路由项的匹配操作。而对于路由的查找,我们在上面已经分析过了,此处不再赘述。

至此,分析完了策略规则的匹配。

年轻是我们唯一拥有权利去编织梦想的时光

Linux 路由 学习笔记 之七 策略规则的查找

相关文章:

你感兴趣的文章:

标签云: