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

 

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

 

通用规则的查找函数 

1.1 fib_rules_lookup

 

这个函数的功能是策略路由对应的路由查找函数

1.遍历传入的ops变量的rules_list链表,对于每一个fib_rule

   a)调用fib_rule_match进行fib_rule规则匹配

      i)当规则匹配后,则调用传入的ops变量的函数指针action进行

        路由项的查找(对于ipv4fib4_rules_ops->action即为fib4_rule_action),当路由

        查找到后,则会调用fib_rule_get增加对匹配规则的引用计数,并

        将arg->rule指向该规则的首地址

 

fib_rule_match中,在完成了通用参数的match后,会调用协议相关的match函数,

对协议相关的参数进行match。而对于ipv4match函数即为fib4_rule_match

match到相应的fib rule后,即会调用协议相关的action函数,进行action操作,对于ipv4而言,即是fib4_rule_action

 

fib_ruleactionFR_ACT_TO_TBLFR_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;

}

 

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

1.2 通用规则的匹配

1.2.1 fib_rule_match

 

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

fib_rule_match函数首先会进行通用参数的match,主要是包括接口indexfwmarkmatch。接着才会调用协议相关的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;

}

 

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

上面函数的通用规则的匹配函数里,调用了协议相关的策略规则匹配函数,下面我们就分析下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函数,下面我们就分析一下这个函数。

 

1.4 协议相关的action

 

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

/*fib ruleaction类型,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的。

下面分析下v4action函数fib4_rule_action

 

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

   action均是FR_ACT_TO_TBL,而对于FR_ACT_UNREACHABLE

   FR_ACT_PROHIBITFR_ACT_BLACKHOLE等均是返回相应的失败码。而对于 FR_ACT_TO_TBL,则需要进一步进行路由项的查找

2.对于FR_ACT_TO_TBL,则根据fib_rule->tabletable 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函数进行路由项的匹配操作。而对于路由的查找,我们在上面已经分析过了,此处不再赘述。

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

 

Logo

更多推荐