文章标题:Linux 上路由查找的性能演变
正文: 在之前的文章中,我解释了 Linux 内核如何实现 IPv4[1] 和 IPv6[2] 路由表,并展示了从 Linux 2.6.32 到 4.16 的 IPv4[3] 路由查找性能提升——包括 Meltdown 和 Spectre 缓解措施的影响[4]——以及从 Linux 2.6.39 到 4.18 的 IPv6[5] 路由查找性能提升。本文将这些数据更新到 Linux 7.3,并调查造成性能回退的罪魁祸首!🕵️♂️
我在一台 AMD EPYC 8024P[6](Zen 4c CPU[7],从 Scaleway[8] 租用)上运行了以下基准测试,主频 2.4 GHz,并禁用了 CPU boost。我使用 GCC 10.2 编译内核:该版本既能编译较旧的内核,也能编译当前的内核。
IPv6
我测试了四种场景:
- 一份包含约 260,000 个前缀的近期 full view,
- 一份来自 2017 年、包含约 40,000 个前缀的 full view,
- 一组 40,000 个 /48 前缀,使得 3 次查找中有 2 次匹配,
- 一组 40,000 个随机 /128 前缀,使得 400 次查找中有 1 次匹配。
在 Linux 4.15 中,Wei Wang 在提交 66f5d6ce53e6[9] 中用 RCU 和 spinlock 替换了读写锁,从而提升了查找性能。在 Linux 4.18 中,David Ahern 改进了路由查找所用的数据结构[10]。在 Linux 5.9 中,Brian Vazquez 在提交 55cced4f813b[11] 中移除了开销高昂的间接调用。
Linux 6.5 引入的约 200 ns 的回退抹掉了所有这些改进。该版本在提交 fb3bd914b3ec[13] 中为“Speculative Return Stack Overflow[12]”(一个影响 AMD 处理器的漏洞)实现了缓解措施。该缓解措施在每次函数返回时增加约 20 个周期。它被向后移植到了较旧的内核(5.10、5.15、6.1 和 6.4)。为了让结果易于阅读,我对这些版本在内核命令行上使用 spec_rstack_overflow=off 禁用了该缓解措施。
你可以用 lscpu 检查影响你的 CPU 的漏洞及其缓解措施。部分缓解措施可能依赖于微码或固件。1
$ lscpu | grep '^Vuln'
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Mitigation; Safe RET
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; Retpolines; IBPB conditional; IBRS_FW; STIBP always-on; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds: Not affected
Vulnerability Tsa: Vulnerable: Clear CPU buffers attempted, no microcode
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Mitigation; IBPB before exit to userspace
IPv4
我测试了三种场景:
- 一份包含超过 1,000,000 个前缀的近期 full view,
- 一份来自 2017 年、包含 500,000 个前缀的 full view 子集,
- 一组 500,000 个连续的 /32 前缀。
Linux 6.5 中针对 SRSO 的缓解措施带来的 30 ns 影响比 IPv6 更小,因为 IPv4 路由查找经过的函数更少:IPv4 大约需要 4 次函数调用,而 IPv6 需要 25 次。
在 Linux 5.11 中,我在修复 net.ipv4.conf.all.ignore_routes_with_linkdown 的行为之后,于提交 c0c5a60f0f13[17] 中引入了一处回归!2 结果,ip_ignore_linkdown()[18] 函数要多花大约 5 个周期才能返回结果,因为它需要多跟随三个指针。最终由 fib_lookup()[19] 在下面的代码中调用它[20]:
if (ip_ignore_linkdown(nhc->nhc_dev) &&
nhc->nhc_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
return false;
如果我们调整这些条件的顺序,就能在链路未断开这一最常见情况下避免调用 ip_ignore_linkdown():
if (nhc->nhc_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE) &&
ip_ignore_linkdown(nhc->nhc_dev))
return false;
以下是在 net-next 之上应用该补丁[22]之前的查找耗时分布:3
min=128 max=4657 count=994104 95th=134 90th=133 50th=132 mad=0
value │ ┊ count
128 │ 120
129 │ 2232
130 │▒ 25224
131 │▒▒▒▒▒▒▒▒▒▒▒▒▒░ 264264
132 │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░ 516480
133 │▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 126864
134 │▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 21624
较浅的色块表示累积分布函数。应用补丁后,中位数从 132 个周期改善到 126 个周期:4
min=124 max=208839 count=994104 95th=128 90th=127 50th=126 mad=0
value │ ┊ count
124 │ 576
125 │▒▒ 49440
126 │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░ 584904
127 │▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 284592
128 │▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 45288
缓解措施的影响
要降低缓解措施的影响,可以用 mitigations=off 将它们全部禁用,也可以只禁用某一项,例如 spec_rstack_overflow=off,或者从 Linux 6.17 起用 mitigations=auto,no_user_kernel 只针对部分攻击向量[23]进行防护。
影响也因 CPU 不同而差异很大。例如,在 Xeon W-2295[24] 这款 2020 年的 Intel 桌面 CPU 上,这些缓解措施对 IPv4 的影响只有几个周期,对 IPv6 的影响不到 3%。主要贡献者是针对 Indirect Target Selection[25] 漏洞的缓解措施,该漏洞自 Sapphire Rapids[26] 架构起已被修复。
如果把针对 CPU 攻击的缓解措施[27]所引入的回归放在一边,IPv4 的性能随时间在缓慢下降,而 IPv6 过去有所改善,目前则保持稳定。如果路由性能很重要,你有几个选择:换一款不同的 CPU,例如 AMD Zen 5 CPU[28]、第四代 Xeon CPU[26],或者也许是 ARM Neoverse V2[29];禁用部分或全部缓解措施;用 XDP/eBPF 绕过路由;5 或者把路由[30]卸载到网卡上。
Maytham Alsudany[32] 审阅了本文的初稿。任何错误仍然是我的!
- https://vincent.bernat.ch/en/blog/2017-ipv4-route-lookup-linux
- https://vincent.bernat.ch/en/blog/2017-ipv6-route-lookup-linux
- https://vincent.bernat.ch/en/blog/2017-performance-progression-ipv4-route-lookup-linux
- https://meltdownattack.com/
- https://vincent.bernat.ch/en/blog/2017-performance-progression-ipv6-route-lookup-linux
- https://www.amd.com/en/products/processors/server/epyc/4th-generation-9004-and-8004-series/amd-epyc-8024p.html
- https://en.wikipedia.org/wiki/Zen_4#Zen_4c
- https://www.scaleway.com/en/elastic-metal/
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=66f5d6ce53e665477d2a33e8f539d4fa4ca81c83
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0565de29cbd65b378147d36f9642f93a046240dc
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55cced4f813bece01f96256d96f283b9210d19ee
- https://docs.kernel.org/admin-guide/hw-vuln/srso.html
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fb3bd914b3ec28f5fb697ac55c4846ac2d542855
- https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e7862eda309ecfccc36bb5558d937ed3ace07f3f
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acaa4b5c4c854b5009f4d4a5395b2609ad0f4937
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c0c5a60f0f1311bcf08bbe735122096d6326fb5b
- https://elixir.bootlin.com/linux/v7.3.1/source/include/linux/inetdevice.h#L265
- https://elixir.bootlin.com/linux/v7.3.1/source/include/net/ip_fib.h#L374
- https://elixir.bootlin.com/linux/v7.3.1/source/net/ipv4/fib_trie.c#L1406
- https://elixir.bootlin.com/linux/v7.3.1/source/net/ipv6/addrconf.c#L940
- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=5fe3653f13b9d0549d8e8f6c181cf2dcbc67b06a
- https://docs.kernel.org/admin-guide/hw-vuln/attack_vector_controls.html
- https://www.intel.com/content/www/us/en/products/sku/198011/intel-xeon-w2295-processor-24-75m-cache-3-00-ghz/specifications.html
- https://docs.kernel.org/admin-guide/hw-vuln/indirect-target-selection.html
- https://en.wikipedia.org/wiki/Sapphire_Rapids
- https://docs.kernel.org/admin-guide/hw-vuln/
- https://en.wikipedia.org/wiki/Zen_5
- https://en.wikipedia.org/wiki/ARM_Neoverse#Neoverse_V2
- https://www.gtp-guard.org/articles/5g-upf-pump-up-the-volume/
- https://docs.ebpf.io/linux/helper-function/bpf_fib_lookup/
- https://maytham.aezign.au/