功能:
(1)遍历rules_list链表;
(2)调用fib_rule_match进行规则匹配//通用规则的查找
//ops 传入
//arg 返回查找结果
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) //遍历ops->rules_list的所有fib_rule节点
{
DEBUG_V4Route("\n%s-->table:%u ifindex:%d mark:0x%x mark_mask:0x%x flags:0x%x\n",__FUNCTION__,\
rule->table,rule->ifindex,rule->mark,rule->mark_mask,rule->flags);
jumped:
if (!fib_rule_match(rule, ops, fl, flags))//规则匹配
continue;
if (rule->action == FR_ACT_GOTO) {
struct fib_rule *target;
target = rcu_dereference(rule->ctarget);
if (target == NULL) {
continue;
} else {
rule = target;
goto jumped;
}
} else if (rule->action == FR_ACT_NOP)
continue;
else
err = ops->action(rule, fl, flags, arg);//fib4_rule_action 查找对应的路由表项
if (err != -EAGAIN) {
fib_rule_get(rule);
arg->rule = rule;//arg->rule赋值
goto out;
}
}
err = -ESRCH;
out:
rcu_read_unlock();
return err;
}
功能:
(1)对接口index、mark等匹配;
(2)调用协议相关的match进行匹配。static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
struct flowi *fl, int flags)
{
int ret = 0;
//对于传入的fib_rule变量与传入的路由查找键值flowi变量比较
if (rule->ifindex && (rule->ifindex != fl->iif))//判断输入接口index是否相等
goto out;
if ((rule->mark ^ fl->mark) & rule->mark_mask)//mark是否相等
goto out;
ret = ops->match(rule, fl, flags);//协议规则的匹配,ipv4调用fib4_rule_match
DEBUG_V4Route("%s-->rule->flags:0x%x ret:%d\n",__FUNCTION__,rule->flags,ret);
out:
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;//若fib_rule的规则是取反,则返回结果也取反
}
功能:
对源ip地址、目的ip地址以及tos的匹配操作
//ipv4协议相关的匹配
//对源IP、目的IP、tos进行比较,相等返回1,不等返回0
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;
//比较规则fib_rule 与 传入路由参数flowi 的值是否相等
if (((saddr ^ r->src) & r->srcmask) ||
((daddr ^ r->dst) & r->dstmask))//源IP、目的IP是否相等
return 0;
if (r->tos && (r->tos != fl->fl4_tos))//tos是否相等
return 0;
return 1;
}
功能:
(1)获取到相应的路由表;
(2)查找符合要求的路由项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://策略规则并且与路由表ID相关联
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;
}
DEBUG_V4Route("%s-->table:%u\n",__FUNCTION__,rule->table);
if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL)//根据id值,获取相应的路由表
goto errout;
err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);//对应ipv4的查找函数fn_hash_lookup
if (err > 0)
err = -EAGAIN;
errout:
return err;
}