策略路由之策略路由规则匹配

这篇笔记来看看路由查询过程中,到底是如何根据策略路由规则引导最终的路由数据库查询的。

源代码路径 说明
net/core/fib_rules.c 策略路由非协议相关实现
net/ipv4/fib_rules.c 策略路由的IPv4实现

1. 策略路由查询: fib_rules_lookup()

实际的路由查询过程中,该函数是由fib_lookup()调用的,fib_lookup()负责完成整个路由查询过程,这里只看策略路由数据库的查询实现。

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) {
jumped:
		//查询条件如果和策略路由规则不匹配,直接尝试匹配下一条
		if (!fib_rule_match(rule, ops, fl, flags))
			continue;
		//规则匹配了,如果action是跳转到另外一条策略路由规则继续匹配,那么进行跳转
		if (rule->action == FR_ACT_GOTO) {
			struct fib_rule *target;
			//获取目标规则target的指针,该指针会是保存在ctarget中的
			target = rcu_dereference(rule->ctarget);
			if (target == NULL) {
				//由于允许先指定一个不存在的target规则,所以这里需要特殊处理一下
				continue;
			} else {
				//进行跳转
				rule = target;
				goto jumped;
			}
		} else if (rule->action == FR_ACT_NOP)
			//如果规则的action是什么都不做,那么继续遍历下一条
			continue;
		else
			//执行action,对于IPv4,该函数是fib4_rule_action()
			err = ops->action(rule, fl, flags, arg);
		//如果不等于-EAGAIN,那么查询结束(是否有路由由err决定),增加该规则引用计数并返回
		if (err != -EAGAIN) {
			fib_rule_get(rule);
			arg->rule = rule;
			goto out;
		}
	}
	//执行到最后都没找到,那么是一种ESRCH失败
	err = -ESRCH;
out:
	rcu_read_unlock();
	return err;
}

查询过程思路还是非常清晰的,IPv4的action实现fib4_rule_action()见笔记策略路由之IPv4接口实现。

2. 策略路由规则匹配: fib_rule_match()

该函数是通用规则匹配函数,可以看出,通用规则中,只会检查输入接口和mark值。

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;
	//调用协议族的match()回调,对于IPv4,该函数是fib4_rule_match(),
	//其中会比较源IP、目的IP和TOS
	ret = ops->match(rule, fl, flags);
out:
	//如果设置了取反标记,则取反即可
	return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
}

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