一、概述
fib_multipath_hash() 是 ECMP 选路的第一阶段,负责根据数据包信息计算一个 hash 值,供第二阶段 fib_select_multipath() 据此选择 nexthop。
本文基于 Linux v6.16 源码(net/ipv4/route.c),逐一解析 4 种 hash 策略的完整实现。
关于 ECMP 选路机制的整体架构,参见 ECMP选路: fib_select_multipath Hash 机制深度解析。
fib_multipath_hash() 是 ECMP 选路的第一阶段,负责根据数据包信息计算一个 hash 值,供第二阶段 fib_select_multipath() 据此选择 nexthop。
本文基于 Linux v6.16 源码(net/ipv4/route.c),逐一解析 4 种 hash 策略的完整实现。
关于 ECMP 选路机制的整体架构,参见 ECMP选路: fib_select_multipath Hash 机制深度解析。
David Ahern 在 2017 年左右开始构思 nexthop 对象化 (nexthop objectification),核心动机来自大规模路由注入的性能瓶颈 (large-scale route injection performance bottleneck)。当时的状况:
| 场景 (Scenario) | 耗时 (Duration) |
|---|---|
| 注入 70 万+ IPv4 路由,单路径 (single path) | 18 秒 |
| 注入 70 万+ IPv4 路由,4 路径 ECMP | 28 秒 |
| 注入 70 万+ IPv4 路由,16 路径 ECMP | 72+ 秒 |
时间随 ECMP (Equal-Cost Multi-Path,等价多路径) 路径数急剧膨胀,这对 BGP 大表 (full internet table,完整互联网路由表) 场景完全不可接受。
以 tcp_v4_connect() 为例,一次 TCP 连接建立会触发 3 次路由查询,每次的目的和 flowi4 参数不同。这三次查询与 ECMP 多路径选路机制密切相关,参见 ECMP选路: fib_select_multipath Hash 机制深度解析。
Linux 内核中的 ECMP(Equal-Cost Multi-Path)选路机制允许将流量分布到多条等价路径上。
核心实现主要分为两个阶段, 分别对应两个函数。
fib_multipath_hash()(net/ipv4/route.c)—— 计算 hash 值fib_select_multipath()(net/ipv4/fib_semantics.c)—— 用 hash 选 nexthop本文基于 Linux v6.16 源码,逐层剖析 ECMP 的 hash 计算与路径选择全流程。
使用coebuddy+claude-4.6-ops辅助生成。
接上篇文章,我们提到在网口eth1 上增加一个 ip 地址,内核会生成 3 个路由。
为什么需要使用local/main 两个路由表呢? ip地址引发的路由变化或者手动添加一个目的网段的路由,这些场景看起来,完全可以使用一个路由表就能满足场景需求。那内核为什么要支持多个路由表?
其中一个场景就是 策略路由。
比如公司有两个网关, 其中一个网关GW1,网络质量比较高。我们希望对网络质量有较高要求的个别网段的外访流量,走GW1.其他网段都用 GW2.
这时,我们就不能仅仅依赖目前 IP 去做路由。我们需要:
那下面详细展开介绍下策略路由及内核实现。
策略路由是一个按优先级排列的规则链表。路由查找时,按优先级顺序遍历链。
每个策略路由规则,由match+action两部分组成。 match 也被称为SELECTOR。
ip rule show命令我们可以看到每条rule对应的优先级。添加rule时候,默认的是当前除0以外最高优先级的值-1, 即默认新建的rule优先级高。这部分用法详见ip rule命令帮助手册,https://man7.org/linux/man-pages/man8/ip-rule.8.html
Q1:ping 本机eth1口的ip地址时,对应的ICMP报文会被发送到eth1口上吗?

通过tcpdump抓包命令,我们发现报文被发送到lo上,而不是对应的物理口 eth1。
虽然ip 地址被配在本机的物理口上,但是报文并没有被发送到物理口。为了理解这个问题,我们需要先看下下面这个问题。
Q2: 当一个IP地址被添加到一个网口后,会引起哪些路由变化呢?
为一个网口增加一个 IP 地址是个很常见的网络操作。
具体添加方式有多种,包括命令行手动添加、通过配置文件在系统启动时候添加,还是通过dhcp自动获取并添加等。
无论哪种场景,添加完IP地址后,系统路由有什么变化。
场景:在本机物理口 eth1上配置192.168.8.8/24,网口状态正常(UP).
fib_unmerge 是内核路由子系统中一个精巧的按需优化设计:
fib_lookup 只需查一次表,性能最优fib_unmerge 将 local 路由从 main 表中切割出来,放入独立的 local 表,确保策略路由能正确匹配fib_trie_unmerge 检测到已分离,直接返回本文将从调用点入手,逐步分析 fib_unmerge 的实现细节。
接上篇文章 ping本机网口的IP地址,tcpdump在lo口才能抓到对应报文,我们知道在网口eth1上增加一个IP地址192.168.8.8/24后,内核会生成3条路由:
RTN_LOCAL)RTN_UNICAST)其中主机路由类型是RTN_LOCAL,网段路由类型是RTN_UNICAST。
那如果把IP地址配到lo口上,会有什么不同呢?