策略路由之策略路由查询

本文探讨了策略路由查询过程,主要涉及fib_rules_lookup()函数的调用,以及fib_rule_match()在策略路由规则匹配中的作用。对于IPv4,fib4_rule_match()回调函数会进一步检查源IP、目的IP和tos字段,而fib4_rule_action()则处理匹配后的策略行动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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

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

策略路由查询: fib_rules_lookup()

实际的路由查询过程中,该函数是由fib_lookup()调用的,fib_lookup()负责完成整个路由查询过程。

// 在查询之前,已经确定了对应的协议族,flowi为查询条件
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) {
		    // action是跳转到另外一条策略路由规则继续匹配,那么进行跳转
			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()回调
			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;
}

策略路由规则匹配: 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;
    // 规则指定了网络设备对象,那么将其和条件中的iif比较
	if (rule->ifindex && (rule->ifindex != fl->iif))
		goto out;
    // fwmark值比较
	if ((rule->mark ^ fl->mark) & rule->mark_mask)
		goto out;
	// 调用协议族的match()回调,对于IPv4,该函数是fib4_rule_match()
	ret = ops->match(rule, fl, flags);
out:
	// 如果设置了取反标记,对结果取反即可
	return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
}

IPv4策略路由规则匹配回调: fib4_rule_match()

IPv4协议比较源IP和目的IP,以及tos三个字段。

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

IPv4策略路由action()回调: fib4_rule_action()

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: // blackhole
	default:
		err = -EINVAL;
		goto errout;
	}
    // 调用路由表的查询接口
	if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL)
		goto errout;
	err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
	if (err > 0)
		err = -EAGAIN;
errout:
	return err;
}
### LangChain 中查询路由的功能与实现 LangChain 的查询路由功能主要用于根据输入数据动态选择合适的模型或处理路径,从而提高系统的智能化程度和效率。这种机制可以通过结合 LangChain 表达式语言 (LCEL)[^1] 和其他模块来实现。 #### 查询路由的核心概念 查询路由通常涉及以下几个核心组件: 1. **条件判断**:基于输入内容的特点(如主题、长度、语义等),决定应调用哪个子链或模型。 2. **模型组合**:通过串联多个模型或工具形成复杂的处理流程。 3. **动态分支**:根据不同条件触发不同的执行路径。 这些功能可以在 `langchain` 库中找到支持,具体来说,`langchain-core` 提供了基础的抽象能力[^4],而高级应用则可能需要借助 `langchain-community` 或自定义逻辑。 #### 实现方法 以下是实现查询路由的一种常见方式: 1. **使用 ChainRouter** LangChain 支持通过路由器链 (`RouterChain`) 来管理不同类型的请求并分配给相应的处理器。这允许开发者定义一组规则,用于匹配特定模式并将任务委派至对应的子链。 下面是一个简单的 Python 示例展示如何设置基本的路由逻辑: ```python from langchain.chains.router import MultiPromptChain, RouterChain from langchain.prompts import PromptTemplate from langchain.llms import OpenAI # 创建两个独立的任务模板 math_template = PromptTemplate(template="Solve the following math problem: {question}", input_variables=["question"]) history_template = PromptTemplate(template="Answer this historical question: {question}", input_variables=["question"]) # 初始化 LLM llm = OpenAI() # 定义每种情况下的响应链条 math_chain = math_template | llm history_chain = history_template | llm # 设置路由器以区分不同类型的问题 router_chain = RouterChain( destination_chains={ "math": math_chain, "history": history_chain }, default_chain=llm # 如果无法分类,则默认交给通用LLM解答 ) result = router_chain.invoke({"input": "What is 2+2?"}) print(result) # 输出计算结果 ``` 上述代码片段展示了如何利用预设好的提示词分别应对数学类问题和历史事实询问的情景[^1]。 2. **嵌入 Function Calling 功能** 对于更灵活的需求场景,还可以引入 ChatGPT 所提供的 function calling 特性[^3]。这种方法让 AI 自己分析用户的意图,并主动挑选最恰当的服务接口或者算法来进行下一步操作。 3. **集成外部服务** 当某些领域知识超出了当前可用的大规模语言模型范围之外时,可以考虑接入专门领域的数据库或者其他形式的知识源作为补充材料参与决策过程。例如,在医疗诊断方面可能会涉及到大量的医学术语解释以及具体的诊疗指南检索等工作环节。 #### 使用教程推荐 对于初学者而言,可以从官方文档入手逐步掌握基础知识[^2],然后再尝试实践上述提到的各种技巧。此外还有许多社区贡献的学习资料可以帮助加深理解实际应用场景中的运用策略。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值