linux内核 策略路由之查找

4.4.1 策略路由查找
       策略规则的查找函数fib_rules_lookup

功能:

      (1)遍历rules_list链表;

      (2)调用fib_rule_match进行规则匹配
      (3)调用函数指针action,进行路由表项的查找;
      (4)将arg->rule指向该规则的首地址。
//通用规则的查找
//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;
}

4.4.2 通用规则的匹配

功能:

      (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的规则是取反,则返回结果也取反
}

4.4.2.1 协议相关规则的匹配

功能

      对源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;
}

4.4.3 查路由表项

功能:

      (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;
}


你可能感兴趣的:(linux,网络协议)