Newshot
Account

Linux 上路由查找的性能演变

Translation(model translation, not the source's own text)

文章标题: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

IPv6 路由查找从 Linux 4.14 到 7.3 的性能演变
IPv6 路由查找从 Linux 4.14 到 7.3 的性能演变

我测试了四种场景:

  • 一份包含约 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

IPv4 路由查找从 Linux 4.14 到 7.3 的性能演变
IPv4 路由查找从 Linux 4.14 到 7.3 的性能演变

我测试了三种场景:

  • 一份包含超过 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/

The translation is machine-generated and individual terms may be off. Nothing is rewritten or cut; the original is authoritative.

Published by Lobsters
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗