mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 09:09:55 -04:00
Merge tag 'chinese-doc-6.16-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/alexs/linux into docs-mw
Chinese translation docs for 6.16-rc1 from Alex Shi
This is the Chinese translation subtree for 6.16-rc1. It
includes few changes:
- Updates to the process documentation
- Added translations for network and speculation docs
- Polished zh_CN/how-to.rst
The above patches have been tested by 'make htmldocs'
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================
|
||||
Linux内核中文文档翻译规范
|
||||
=========================
|
||||
==========================
|
||||
Linux 内核中文文档翻译规范
|
||||
==========================
|
||||
|
||||
修订记录:
|
||||
- v1.0 2025年3月28日,司延腾、慕冬亮共同编写了该规范。
|
||||
- v1.0 2025 年 3 月 28 日,司延腾、慕冬亮共同编写了该规范。
|
||||
|
||||
制定规范的背景
|
||||
==============
|
||||
|
||||
过去几年,在广大社区爱好者的友好合作下,Linux 内核中文文档迎来了蓬勃的发
|
||||
展。在翻译的早期,一切都是混乱的,社区对译稿只有一个准确翻译的要求,以鼓
|
||||
励更多的开发者参与进来,这是从0到1的必然过程,所以早期的中文文档目录更加
|
||||
具有多样性,不过好在文档不多,维护上并没有过大的压力。
|
||||
励更多的开发者参与进来,这是从 0 到 1 的必然过程,所以早期的中文文档目录
|
||||
更加具有多样性,不过好在文档不多,维护上并没有过大的压力。
|
||||
|
||||
然而,世事变幻,不觉有年,现在内核中文文档在前进的道路上越走越远,很多潜
|
||||
在的问题逐渐浮出水面,而且随着中文文档数量的增加,翻译更多的文档与提高中
|
||||
@@ -34,7 +34,7 @@ reviewer 们只能耐心地指导他们如何与社区更好地合作,但是
|
||||
========
|
||||
|
||||
工欲善其事必先利其器,如果您目前对内核文档翻译满怀热情,并且会独立地安装
|
||||
linux 发行版和简单地使用 linux 命令行,那么可以迅速开始了。若您尚不具备该
|
||||
Linux 发行版和简单地使用 Linux 命令行,那么可以迅速开始了。若您尚不具备该
|
||||
能力,很多网站上会有详细的手把手教程,最多一个上午,您应该就能掌握对应技
|
||||
能。您需要注意的一点是,请不要使用 root 用户进行后续步骤和文档翻译。
|
||||
|
||||
@@ -66,11 +66,18 @@ linux 发行版和简单地使用 linux 命令行,那么可以迅速开始了
|
||||
cd linux
|
||||
./scripts/sphinx-pre-install
|
||||
|
||||
以Fedora为例,它的输出是这样的::
|
||||
以 Fedora 为例,它的输出是这样的::
|
||||
|
||||
You should run:
|
||||
|
||||
sudo dnf install -y dejavu-sans-fonts dejavu-sans-mono-fonts dejavu-serif-fonts google-noto-sans-cjk-fonts graphviz-gd latexmk librsvg2-tools texlive-anyfontsize texlive-capt-of texlive-collection-fontsrecommended texlive-ctex texlive-eqparbox texlive-fncychap texlive-framed texlive-luatex85 texlive-multirow texlive-needspace texlive-tabulary texlive-threeparttable texlive-upquote texlive-wrapfig texlive-xecjk
|
||||
sudo dnf install -y dejavu-sans-fonts dejavu-sans-mono-fonts \
|
||||
dejavu-serif-fonts google-noto-sans-cjk-fonts graphviz-gd \
|
||||
latexmk librsvg2-tools texlive-anyfontsize texlive-capt-of \
|
||||
texlive-collection-fontsrecommended texlive-ctex \
|
||||
texlive-eqparbox texlive-fncychap texlive-framed \
|
||||
texlive-luatex85 texlive-multirow texlive-needspace \
|
||||
texlive-tabulary texlive-threeparttable texlive-upquote \
|
||||
texlive-wrapfig texlive-xecjk
|
||||
|
||||
Sphinx needs to be installed either:
|
||||
1) via pip/pypi with:
|
||||
@@ -92,7 +99,8 @@ linux 发行版和简单地使用 linux 命令行,那么可以迅速开始了
|
||||
https://github.com/sphinx-doc/sphinx/pull/8313
|
||||
|
||||
请您按照提示复制打印的命令到命令行执行,您必须具备 root 权限才能执行 sudo
|
||||
开头的命令。
|
||||
开头的命令。**请注意**,最新版本 Sphinx 的文档编译速度有极大提升,强烈建议
|
||||
您通过 pip/pypi 安装最新版本 Sphinx。
|
||||
|
||||
如果您处于一个多用户环境中,为了避免对其他人造成影响,建议您配置单用户
|
||||
sphinx 虚拟环境,即只需要执行::
|
||||
@@ -126,11 +134,11 @@ sphinx 虚拟环境,即只需要执行::
|
||||
检查编译结果
|
||||
------------
|
||||
|
||||
编译输出在Documentation/output/目录下,请用浏览器打开该目录下对应
|
||||
编译输出在 Documentation/output/ 目录下,请用浏览器打开该目录下对应
|
||||
的文件进行检查。
|
||||
|
||||
git和邮箱配置
|
||||
-------------
|
||||
Git 和邮箱配置
|
||||
--------------
|
||||
|
||||
打开命令行执行::
|
||||
|
||||
@@ -150,11 +158,11 @@ git和邮箱配置
|
||||
smtpencryption = ssl
|
||||
smtpserver = smtp.migadu.com
|
||||
smtpuser = si.yanteng@linux.dev
|
||||
smtppass = <passwd> # 建议使用第三方客户端专用密码
|
||||
smtppass = <passwd> # 建议使用第三方客户端专用密码
|
||||
chainreplyto = false
|
||||
smtpserverport = 465
|
||||
|
||||
关于邮件客户端的配置,请查阅Documentation/translations/zh_CN/process/email-clients.rst。
|
||||
关于邮件客户端的配置,请查阅 Documentation/translations/zh_CN/process/email-clients.rst。
|
||||
|
||||
开始翻译文档
|
||||
============
|
||||
@@ -162,8 +170,8 @@ git和邮箱配置
|
||||
文档索引结构
|
||||
------------
|
||||
|
||||
目前中文文档是在Documentation/translations/zh_CN/目录下进行,该
|
||||
目录结构最终会与Documentation/结构一致,所以您只需要将您感兴趣的英文
|
||||
目前中文文档是在 Documentation/translations/zh_CN/ 目录下进行,该
|
||||
目录结构最终会与 Documentation/ 结构一致,所以您只需要将您感兴趣的英文
|
||||
文档文件和对应的 index.rst 复制到 zh_CN 目录下对应的位置,然后修改更
|
||||
上一级的 index 即可开始您的翻译。
|
||||
|
||||
@@ -177,13 +185,12 @@ git和邮箱配置
|
||||
请执行以下命令,新建开发分支::
|
||||
|
||||
git checkout docs-next
|
||||
git branch my-trans
|
||||
git checkout my-trans
|
||||
git checkout -b my-trans
|
||||
|
||||
译文格式要求
|
||||
------------
|
||||
|
||||
- 每行长度最多不超过40个字符
|
||||
- 每行长度最多不超过 40 个字符
|
||||
- 每行长度请保持一致
|
||||
- 标题的下划线长度请按照一个英文一个字符、一个中文两个字符与标题对齐
|
||||
- 其它的修饰符请与英文文档保持一致
|
||||
@@ -192,7 +199,7 @@ git和邮箱配置
|
||||
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst #您需要了解该文件的路径,根
|
||||
据您实际翻译的文档灵活调整
|
||||
据您实际翻译的文档灵活调整
|
||||
|
||||
:Original: Documentation/xxx/xxx.rst #替换为您翻译的英文文档路径
|
||||
|
||||
@@ -203,11 +210,11 @@ git和邮箱配置
|
||||
翻译技巧
|
||||
--------
|
||||
|
||||
中文文档有每行40字符限制,因为一个中文字符等于2个英文字符。但是社区并没有
|
||||
那么严格,一个诀窍是将您的翻译的内容与英文原文的每行长度对齐即可,这样,
|
||||
中文文档有每行 40 字符限制,因为一个中文字符等于 2 个英文字符。但是社区并
|
||||
没有那么严格,一个诀窍是将您的翻译的内容与英文原文的每行长度对齐即可,这样,
|
||||
您也不必总是检查有没有超限。
|
||||
|
||||
如果您的英文阅读能力有限,可以考虑使用辅助翻译工具,例如 deepseek 。但是您
|
||||
如果您的英文阅读能力有限,可以考虑使用辅助翻译工具,例如 deepseek。但是您
|
||||
必须仔细地打磨,使译文达到“信达雅”的标准。
|
||||
|
||||
**请注意** 社区不接受纯机器翻译的文档,社区工作建立在信任的基础上,请认真对待。
|
||||
@@ -248,14 +255,17 @@ git和邮箱配置
|
||||
|
||||
Translate .../security/self-protection.rst into Chinese.
|
||||
|
||||
Update the translation through commit b080e52110ea #请执行git log <您翻译的英文文档路径> 复制最顶部第一个补丁的sha值的前12位,替换掉12位sha值。
|
||||
Update the translation through commit b080e52110ea
|
||||
("docs: update self-protection __ro_after_init status")
|
||||
# 请执行 git log --oneline <您翻译的英文文档路径>,并替换上述内容
|
||||
|
||||
Signed-off-by: Yanteng Si <si.yanteng@linux.dev> #如果您前面的步骤正确执行,该行会自动显示,否则请检查gitconfig文件。
|
||||
Signed-off-by: Yanteng Si <si.yanteng@linux.dev>
|
||||
# 如果您前面的步骤正确执行,该行会自动显示,否则请检查 gitconfig 文件
|
||||
|
||||
保存并退出。
|
||||
|
||||
**请注意** 以上四行,缺少任何一行,您都将会在第一轮审阅后返工,如果您需要一个更加明确的示例,请对 zh_CN 目录执行 git log。
|
||||
**请注意** 以上四行,缺少任何一行,您都将会在第一轮审阅后返工,如果您需要一个
|
||||
更加明确的示例,请对 zh_CN 目录执行 git log。
|
||||
|
||||
导出补丁和制作封面
|
||||
------------------
|
||||
@@ -263,6 +273,7 @@ git和邮箱配置
|
||||
这个时候,可以导出补丁,做发送邮件列表最后的准备了。命令行执行::
|
||||
|
||||
git format-patch -N
|
||||
# N 要替换为补丁数量,一般 N 大于等于 1
|
||||
|
||||
然后命令行会输出类似下面的内容::
|
||||
|
||||
@@ -286,13 +297,13 @@ warning 不需要解决::
|
||||
然后执行以下命令为补丁追加更改::
|
||||
|
||||
git checkout docs-next
|
||||
git branch test-trans
|
||||
git checkout -b test-trans-new
|
||||
git am 0001-xxxxx.patch
|
||||
./scripts/checkpatch.pl 0001-xxxxx.patch
|
||||
直接修改您的翻译
|
||||
# 直接修改您的翻译
|
||||
git add .
|
||||
git am --amend
|
||||
保存退出
|
||||
# 保存退出
|
||||
git am 0002-xxxxx.patch
|
||||
……
|
||||
|
||||
@@ -301,28 +312,30 @@ warning 不需要解决::
|
||||
最后,如果检测时没有 warning 和 error 需要被处理或者您只有一个补丁,请跳
|
||||
过下面这个步骤,否则请重新导出补丁制作封面::
|
||||
|
||||
git format-patch -N --cover-letter --thread=shallow #N为您的补丁数量,N一般要大于1。
|
||||
git format-patch -N --cover-letter --thread=shallow
|
||||
# N 要替换为补丁数量,一般 N 大于 1
|
||||
|
||||
然后命令行会输出类似下面的内容::
|
||||
|
||||
0000-cover-letter.patch
|
||||
0001-docs-zh_CN-add-xxxxxxxx.patch
|
||||
0002-docs-zh_CN-add-xxxxxxxx.patch
|
||||
……
|
||||
|
||||
您需要用编辑器打开0号补丁,修改两处内容::
|
||||
您需要用编辑器打开 0 号补丁,修改两处内容::
|
||||
|
||||
vim 0000-cover-letter.patch
|
||||
|
||||
...
|
||||
Subject: [PATCH 0/1] *** SUBJECT HERE *** #修改该字段,概括您的补丁集都做了哪些事情
|
||||
Subject: [PATCH 0/N] *** SUBJECT HERE *** #修改该字段,概括您的补丁集都做了哪些事情
|
||||
|
||||
*** BLURB HERE *** #修改该字段,详细描述您的补丁集做了哪些事情
|
||||
*** BLURB HERE *** #修改该字段,详细描述您的补丁集做了哪些事情
|
||||
|
||||
Yanteng Si (1):
|
||||
docs/zh_CN: add xxxxx
|
||||
...
|
||||
|
||||
如果您只有一个补丁,则可以不制作封面,即0号补丁,只需要执行::
|
||||
如果您只有一个补丁,则可以不制作封面,即 0 号补丁,只需要执行::
|
||||
|
||||
git format-patch -1
|
||||
|
||||
@@ -345,9 +358,10 @@ warning 不需要解决::
|
||||
|
||||
打开上面您保存的邮件地址,执行::
|
||||
|
||||
git send-email *.patch --to <maintainer email addr> --cc <others addr> #一个to对应一个地址,一个cc对应一个地址,有几个就写几个。
|
||||
git send-email *.patch --to <maintainer email addr> --cc <others addr>
|
||||
# 一个 to 对应一个地址,一个 cc 对应一个地址,有几个就写几个
|
||||
|
||||
执行该命令时,请确保网络通常,邮件发送成功一般会返回250。
|
||||
执行该命令时,请确保网络通常,邮件发送成功一般会返回 250。
|
||||
|
||||
您可以先发送给自己,尝试发出的 patch 是否可以用 'git am' 工具正常打上。
|
||||
如果检查正常, 您就可以放心的发送到社区评审了。
|
||||
@@ -382,15 +396,15 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
|
||||
每次迭代一个补丁,不要一次多个::
|
||||
|
||||
git am <您要修改的补丁>
|
||||
直接对文件进行您的修改
|
||||
# 直接对文件进行您的修改
|
||||
git add .
|
||||
git commit --amend
|
||||
|
||||
当您将所有的评论落实到位后,导出第二版补丁,并修改封面::
|
||||
|
||||
git format-patch -N -v 2 --cover-letter --thread=shallow
|
||||
git format-patch -N -v 2 --cover-letter --thread=shallow
|
||||
|
||||
打开0号补丁,在 BLURB HERE 处编写相较于上个版本,您做了哪些改动。
|
||||
打开 0 号补丁,在 BLURB HERE 处编写相较于上个版本,您做了哪些改动。
|
||||
|
||||
然后执行::
|
||||
|
||||
@@ -414,7 +428,7 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
|
||||
如果您发送到邮件列表之后。发现发错了补丁集,尤其是在多个版本迭代的过程中;
|
||||
自己发现了一些不妥的翻译;发送错了邮件列表……
|
||||
|
||||
git email默认会抄送给您一份,所以您可以切换为审阅者的角色审查自己的补丁,
|
||||
git email 默认会抄送给您一份,所以您可以切换为审阅者的角色审查自己的补丁,
|
||||
并留下评论,描述有何不妥,将在下个版本怎么改,并付诸行动,重新提交,但是
|
||||
注意频率,每天提交的次数不要超过两次。
|
||||
|
||||
@@ -425,9 +439,9 @@ git email默认会抄送给您一份,所以您可以切换为审阅者的角
|
||||
|
||||
./script/checktransupdate.py -l zh_CN``
|
||||
|
||||
该命令会列出需要翻译或更新的英文文档。
|
||||
该命令会列出需要翻译或更新的英文文档,结果同时保存在 checktransupdate.log 中。
|
||||
|
||||
关于详细操作说明,请参考: Documentation/translations/zh_CN/doc-guide/checktransupdate.rst\
|
||||
关于详细操作说明,请参考:Documentation/translations/zh_CN/doc-guide/checktransupdate.rst。
|
||||
|
||||
进阶
|
||||
----
|
||||
@@ -439,8 +453,8 @@ git email默认会抄送给您一份,所以您可以切换为审阅者的角
|
||||
常见的问题
|
||||
==========
|
||||
|
||||
Maintainer回复补丁不能正常apply
|
||||
-------------------------------
|
||||
Maintainer 回复补丁不能正常 apply
|
||||
---------------------------------
|
||||
|
||||
这通常是因为您的补丁与邮件列表其他人的补丁产生了冲突,别人的补丁先被 apply 了,
|
||||
您的补丁集就无法成功 apply 了,这需要您更新本地分支,在本地解决完冲突后再次提交。
|
||||
@@ -455,5 +469,5 @@ Maintainer回复补丁不能正常apply
|
||||
大部分情况下,是由于您发送了非纯文本格式的信件,请尽量避免使用 webmail,推荐
|
||||
使用邮件客户端,比如 thunderbird,记得在设置中的回信配置那改为纯文本发送。
|
||||
|
||||
如果超过了24小时,您依旧没有在<https://lore.kernel.org/linux-doc/>发现您的邮
|
||||
件,请联系您的网络管理员帮忙解决。
|
||||
如果超过了 24 小时,您依旧没有在<https://lore.kernel.org/linux-doc/>发现您的
|
||||
邮件,请联系您的网络管理员帮忙解决。
|
||||
|
||||
56
Documentation/translations/zh_CN/networking/alias.rst
Normal file
56
Documentation/translations/zh_CN/networking/alias.rst
Normal file
@@ -0,0 +1,56 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/alias.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
邱禹潭 Qiu Yutan <qiu.yutan@zte.com.cn>
|
||||
|
||||
:校译:
|
||||
|
||||
======
|
||||
IP别名
|
||||
======
|
||||
|
||||
IP别名是管理每个接口存在多个IP地址/子网掩码的一种过时方法。
|
||||
虽然更新的工具如iproute2支持每个接口多个地址/前缀,
|
||||
但为了向后兼容性,别名仍被支持。
|
||||
|
||||
别名通过在使用 ifconfig 时在接口名后添加冒号和一个字符串来创建。
|
||||
这个字符串通常是数字,但并非必须。
|
||||
|
||||
|
||||
别名创建
|
||||
========
|
||||
|
||||
别名的创建是通过“特殊的”接口命名机制完成的:例如,
|
||||
要为eth0创建一个 200.1.1.1 的别名...
|
||||
::
|
||||
|
||||
# ifconfig eth0:0 200.1.1.1 等等
|
||||
~~ -> 请求为eth0创建别名#0(如果尚不存在)
|
||||
|
||||
该命令也会设置相应的路由表项。请注意:路由表项始终指向基础接口。
|
||||
|
||||
|
||||
别名删除
|
||||
========
|
||||
|
||||
通过关闭别名即可将其删除::
|
||||
|
||||
# ifconfig eth0:0 down
|
||||
~~~~~~~~~~ -> 将删除别名
|
||||
|
||||
|
||||
别名(重新)配置
|
||||
================
|
||||
|
||||
别名不是真实的设备,但程序应该能够正常配置和引用它们(ifconfig、route等)。
|
||||
|
||||
|
||||
与主设备的关系
|
||||
==============
|
||||
|
||||
如果基础设备被关闭,则其上添加的所有别名也将被删除。
|
||||
@@ -21,6 +21,12 @@
|
||||
:maxdepth: 1
|
||||
|
||||
msg_zerocopy
|
||||
napi
|
||||
vxlan
|
||||
netif-msg
|
||||
xfrm_proc
|
||||
netmem
|
||||
alias
|
||||
|
||||
Todolist:
|
||||
|
||||
@@ -45,7 +51,6 @@ Todolist:
|
||||
* page_pool
|
||||
* phy
|
||||
* sfp-phylink
|
||||
* alias
|
||||
* bridge
|
||||
* snmp_counter
|
||||
* checksum-offloads
|
||||
@@ -94,14 +99,11 @@ Todolist:
|
||||
* mptcp-sysctl
|
||||
* multiqueue
|
||||
* multi-pf-netdev
|
||||
* napi
|
||||
* net_cachelines/index
|
||||
* netconsole
|
||||
* netdev-features
|
||||
* netdevices
|
||||
* netfilter-sysctl
|
||||
* netif-msg
|
||||
* netmem
|
||||
* nexthop-group-resilient
|
||||
* nf_conntrack-sysctl
|
||||
* nf_flowtable
|
||||
@@ -142,11 +144,9 @@ Todolist:
|
||||
* tuntap
|
||||
* udplite
|
||||
* vrf
|
||||
* vxlan
|
||||
* x25
|
||||
* x25-iface
|
||||
* xfrm_device
|
||||
* xfrm_proc
|
||||
* xfrm_sync
|
||||
* xfrm_sysctl
|
||||
* xdp-rx-metadata
|
||||
|
||||
362
Documentation/translations/zh_CN/networking/napi.rst
Normal file
362
Documentation/translations/zh_CN/networking/napi.rst
Normal file
@@ -0,0 +1,362 @@
|
||||
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/napi.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Yaxin Wang <wang.yaxin@zte.com.cn>
|
||||
|
||||
====
|
||||
NAPI
|
||||
====
|
||||
|
||||
NAPI 是 Linux 网络堆栈中使用的事件处理机制。NAPI 的名称现在不再代表任何特定含义 [#]_。
|
||||
|
||||
在基本操作中,设备通过中断通知主机有新事件发生。主机随后调度 NAPI 实例来处理这些事件。
|
||||
该设备也可以通过 NAPI 进行事件轮询,而无需先接收中断信号(:ref:`忙轮询<poll_zh_CN>`)。
|
||||
|
||||
NAPI 处理通常发生在软中断上下文中,但有一个选项,可以使用 :ref:`单独的内核线程<threaded_zh_CN>`
|
||||
来进行 NAPI 处理。
|
||||
|
||||
总的来说,NAPI 为驱动程序抽象了事件(数据包接收和发送)处理的上下文环境和配置情况。
|
||||
|
||||
驱动程序API
|
||||
===========
|
||||
|
||||
NAPI 最重要的两个元素是 struct napi_struct 和关联的 poll 方法。struct napi_struct
|
||||
持有 NAPI 实例的状态,而方法则是与驱动程序相关的事件处理器。该方法通常会释放已传输的发送
|
||||
(Tx)数据包并处理新接收的数据包。
|
||||
|
||||
.. _drv_ctrl_zh_CN:
|
||||
|
||||
控制API
|
||||
-------
|
||||
|
||||
netif_napi_add() 和 netif_napi_del() 用于向系统中添加/删除一个 NAPI 实例。实例会被
|
||||
附加到作为参数传递的 netdevice上(并在 netdevice 注销时自动删除)。实例在添加时处于禁
|
||||
用状态。
|
||||
|
||||
napi_enable() 和 napi_disable() 管理禁用状态。禁用的 NAPI 不会被调度,并且保证其
|
||||
poll 方法不会被调用。napi_disable() 会等待 NAPI 实例的所有权被释放。
|
||||
|
||||
这些控制 API 并非幂等的。控制 API 调用在面对数据路径 API 的并发使用时是安全的,但控制
|
||||
API 调用顺序错误可能会导致系统崩溃、死锁或竞态条件。例如,连续多次调用 napi_disable()
|
||||
会造成死锁。
|
||||
|
||||
数据路径API
|
||||
-----------
|
||||
|
||||
napi_schedule() 是调度 NAPI 轮询的基本方法。驱动程序应在其中断处理程序中调用此函数
|
||||
(更多信息请参见 :ref:`drv_sched_zh_CN`)。成功的 napi_schedule() 调用将获得 NAPI 实例
|
||||
的所有权。
|
||||
|
||||
之后,在 NAPI 被调度后,驱动程序的 poll 方法将被调用以处理事件/数据包。该方法接受一个
|
||||
``budget`` 参数 - 驱动程序可以处理任意数量的发送 (Tx) 数据包完成,但处理最多处理
|
||||
``budget`` 个接收 (Rx) 数据包。处理接收数据包通常开销更大。
|
||||
|
||||
换句话说,对于接收数据包的处理,``budget`` 参数限制了驱动程序在单次轮询中能够处理的数
|
||||
据包数量。当 ``budget`` 为 0 时,像页面池或 XDP 这类专门用于接收的 API 根本无法使用。
|
||||
无论 ``budget`` 的值是多少,skb 的发送处理都应该进行,但是如果 ``budget`` 参数为 0,
|
||||
驱动程序就不能调用任何 XDP(或页面池)API。
|
||||
|
||||
.. warning::
|
||||
|
||||
如果内核仅尝试处理skb的发送完成情况,而不处理接收 (Rx) 或 XDP 数据包,那么 ``budget``
|
||||
参数可能为 0。
|
||||
|
||||
轮询方法会返回已完成的工作量。如果驱动程序仍有未完成的工作(例如,``budget`` 已用完),
|
||||
轮询方法应精确返回 ``budget`` 的值。在这种情况下,NAPI 实例将再次被处理 / 轮询(无需
|
||||
重新调度)。
|
||||
|
||||
如果事件处理已完成(所有未处理的数据包都已处理完毕),轮询方法在返回之前应调用 napi_complete_done()。
|
||||
napi_complete_done() 会释放实例的所有权。
|
||||
|
||||
.. warning::
|
||||
|
||||
当出现既完成了所有事件处理,又恰好达到了 ``budget`` 数量的情况时,必须谨慎处理。因为没
|
||||
有办法将这种(很少出现的)情况报告给协议栈,所以驱动程序要么不调用 napi_complete_done()
|
||||
并等待再次被调用,要么返回 ``budget - 1``。
|
||||
|
||||
当 ``budget`` 为 0 时,napi_complete_done() 绝对不能被调用。
|
||||
|
||||
调用序列
|
||||
--------
|
||||
|
||||
驱动程序不应假定调用的顺序是固定不变的。即使驱动程序没有调度该实例,轮询方法也可能会被调用
|
||||
(除非该实例处于禁用状态)。同样,即便 napi_schedule() 调用成功,也不能保证轮询方法一定
|
||||
会被调用(例如,如果该实例被禁用)。
|
||||
|
||||
正如在 :ref:`drv_ctrl_zh_CN` 部分所提到的,napi_disable() 以及后续对轮询方法的调用,
|
||||
仅会等待该实例的所有权被释放,而不会等待轮询方法退出。这意味着,驱动程序在调用 napi_complete_done()
|
||||
之后,应避免访问任何数据结构。
|
||||
|
||||
.. _drv_sched_zh_CN:
|
||||
|
||||
调度与IRQ屏蔽
|
||||
-------------
|
||||
|
||||
驱动程序应在调度 NAPI 实例后保持中断屏蔽 - 直到 NAPI 轮询完成,任何进一步的中断都是不必要的。
|
||||
|
||||
显式屏蔽中断的驱动程序(而非设备自动屏蔽 IRQ)应使用 napi_schedule_prep() 和
|
||||
__napi_schedule() 调用:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (napi_schedule_prep(&v->napi)) {
|
||||
mydrv_mask_rxtx_irq(v->idx);
|
||||
/* 在屏蔽后调度以避免竞争 */
|
||||
__napi_schedule(&v->napi);
|
||||
}
|
||||
|
||||
IRQ 仅应在成功调用 napi_complete_done() 后取消屏蔽:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (budget && napi_complete_done(&v->napi, work_done)) {
|
||||
mydrv_unmask_rxtx_irq(v->idx);
|
||||
return min(work_done, budget - 1);
|
||||
}
|
||||
|
||||
napi_schedule_irqoff() 是 napi_schedule() 的一个变体,它利用了在中断请求(IRQ)上下文
|
||||
环境中调用所带来的特性(无需屏蔽中断)。如果中断请求(IRQ)是通过线程处理的(例如启用了
|
||||
``PREEMPT_RT`` 时的情况),napi_schedule_irqoff() 会回退为使用 napi_schedule() 。
|
||||
|
||||
实例到队列的映射
|
||||
----------------
|
||||
|
||||
现代设备每个接口有多个 NAPI 实例(struct napi_struct)。关于实例如何映射到队列和中断没有
|
||||
严格要求。NAPI 主要是事件处理/轮询抽象,没有用户可见的语义。也就是说,大多数网络设备最终以
|
||||
非常相似的方式使用 NAPI。
|
||||
|
||||
NAPI 实例最常以 1:1:1 映射到中断和队列对(队列对是由一个接收队列和一个发送队列组成的一组
|
||||
队列)。
|
||||
|
||||
在不太常见的情况下,一个 NAPI 实例可能会用于处理多个队列,或者在单个内核上,接收(Rx)队列
|
||||
和发送(Tx)队列可以由不同的 NAPI 实例来处理。不过,无论队列如何分配,通常 NAPI 实例和中断
|
||||
之间仍然保持一一对应的关系。
|
||||
|
||||
值得注意的是,ethtool API 使用了 “通道” 这一术语,每个通道可以是 ``rx`` (接收)、``tx``
|
||||
(发送)或 ``combined`` (组合)类型。目前尚不清楚一个通道具体由什么构成,建议的理解方式是
|
||||
将一个通道视为一个为特定类型队列提供服务的 IRQ(中断请求)/ NAPI 实例。例如,配置为 1 个
|
||||
``rx`` 通道、1 个 ``tx`` 通道和 1 个 ``combined`` 通道的情况下,预计会使用 3 个中断、
|
||||
2 个接收队列和 2 个发送队列。
|
||||
|
||||
持久化NAPI配置
|
||||
--------------
|
||||
|
||||
驱动程序常常会动态地分配和释放 NAPI 实例。这就导致每当 NAPI 实例被重新分配时,与 NAPI 相关
|
||||
的用户配置就会丢失。netif_napi_add_config() API接口通过将每个 NAPI 实例与基于驱动程序定义
|
||||
的索引值(如队列编号)的持久化 NAPI 配置相关联,从而避免了这种配置丢失的情况。
|
||||
|
||||
使用此 API 可实现持久化的 NAPI 标识符(以及其他设置),这对于使用 ``SO_INCOMING_NAPI_ID``
|
||||
的用户空间程序来说是有益的。有关其他 NAPI 配置的设置,请参阅以下章节。
|
||||
|
||||
驱动程序应尽可能尝试使用 netif_napi_add_config()。
|
||||
|
||||
用户API
|
||||
=======
|
||||
|
||||
用户与 NAPI 的交互依赖于 NAPI 实例 ID。这些实例 ID 仅通过 ``SO_INCOMING_NAPI_ID`` 套接字
|
||||
选项对用户可见。
|
||||
|
||||
用户可以使用 Netlink 来查询某个设备或设备队列的 NAPI 标识符。这既可以在用户应用程序中通过编程
|
||||
方式实现,也可以使用内核源代码树中包含的一个脚本:tools/net/ynl/pyynl/cli.py 来完成。
|
||||
|
||||
例如,使用该脚本转储某个设备的所有队列(这将显示每个队列的 NAPI 标识符):
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ kernel-source/tools/net/ynl/pyynl/cli.py \
|
||||
--spec Documentation/netlink/specs/netdev.yaml \
|
||||
--dump queue-get \
|
||||
--json='{"ifindex": 2}'
|
||||
|
||||
有关可用操作和属性的更多详细信息,请参阅 ``Documentation/netlink/specs/netdev.yaml``。
|
||||
|
||||
软件IRQ合并
|
||||
-----------
|
||||
|
||||
默认情况下,NAPI 不执行任何显式的事件合并。在大多数场景中,数据包的批量处理得益于设备进行
|
||||
的中断请求(IRQ)合并。不过,在某些情况下,软件层面的合并操作也很有帮助。
|
||||
|
||||
可以将 NAPI 配置为设置一个重新轮询定时器,而不是在处理完所有数据包后立即取消屏蔽硬件中断。
|
||||
网络设备的 ``gro_flush_timeout`` sysfs 配置项可用于控制该定时器的延迟时间,而 ``napi_defer_hard_irqs``
|
||||
则用于控制在 NAPI 放弃并重新启用硬件中断之前,连续进行空轮询的次数。
|
||||
|
||||
上述参数也可以通过 Netlink 的 netdev-genl 接口,基于每个 NAPI 实例进行设置。当通过
|
||||
Netlink 进行配置且是基于每个 NAPI 实例设置时,上述参数使用连字符(-)而非下划线(_)
|
||||
来命名,即 ``gro-flush-timeout`` 和 ``napi-defer-hard-irqs``。
|
||||
|
||||
基于每个 NAPI 实例的配置既可以在用户应用程序中通过编程方式完成,也可以使用内核源代码树中的
|
||||
一个脚本实现,该脚本为 ``tools/net/ynl/pyynl/cli.py``。
|
||||
|
||||
例如,通过如下方式使用该脚本:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ kernel-source/tools/net/ynl/pyynl/cli.py \
|
||||
--spec Documentation/netlink/specs/netdev.yaml \
|
||||
--do napi-set \
|
||||
--json='{"id": 345,
|
||||
"defer-hard-irqs": 111,
|
||||
"gro-flush-timeout": 11111}'
|
||||
|
||||
类似地,参数 ``irq-suspend-timeout`` 也可以通过 netlink 的 netdev-genl 设置。没有全局
|
||||
的 sysfs 参数可用于设置这个值。
|
||||
|
||||
``irq-suspend-timeout`` 用于确定应用程序可以完全挂起 IRQ 的时长。与 SO_PREFER_BUSY_POLL
|
||||
结合使用,后者可以通过 ``EPIOCSPARAMS`` ioctl 在每个 epoll 上下文中设置。
|
||||
|
||||
.. _poll_zh_CN:
|
||||
|
||||
忙轮询
|
||||
------
|
||||
|
||||
忙轮询允许用户进程在设备中断触发前检查传入的数据包。与其他忙轮询一样,它以 CPU 周期换取更低
|
||||
的延迟(生产环境中 NAPI 忙轮询的使用尚不明确)。
|
||||
|
||||
通过在选定套接字上设置 ``SO_BUSY_POLL`` 或使用全局 ``net.core.busy_poll`` 和 ``net.core.busy_read``
|
||||
等 sysctls 启用忙轮询。还存在基于 io_uring 的 NAPI 忙轮询 API 可使用。
|
||||
|
||||
基于epoll的忙轮询
|
||||
-----------------
|
||||
|
||||
可以从 ``epoll_wait`` 调用直接触发数据包处理。为了使用此功能,用户应用程序必须确保添加到
|
||||
epoll 上下文的所有文件描述符具有相同的 NAPI ID。
|
||||
|
||||
如果应用程序使用专用的 acceptor 线程,那么该应用程序可以获取传入连接的 NAPI ID(使用
|
||||
SO_INCOMING_NAPI_ID)然后将该文件描述符分发给工作线程。工作线程将该文件描述符添加到其
|
||||
epoll 上下文。这确保了每个工作线程的 epoll 上下文中所包含的文件描述符具有相同的 NAPI ID。
|
||||
|
||||
或者,如果应用程序使用 SO_REUSEPORT,可以插入 bpf 或 ebpf 程序来分发传入连接,使得每个
|
||||
线程只接收具有相同 NAPI ID 的连接。但是必须谨慎处理系统中可能存在多个网卡的情况。
|
||||
|
||||
为了启用忙轮询,有两种选择:
|
||||
|
||||
1. ``/proc/sys/net/core/busy_poll`` 可以设置为微秒数以在忙循环中等待事件。这是一个系统
|
||||
范围的设置,将导致所有基于 epoll 的应用程序在调用 epoll_wait 时忙轮询。这可能不是理想
|
||||
的情况,因为许多应用程序可能不需要忙轮询。
|
||||
|
||||
2. 使用最新内核的应用程序可以在 epoll 上下文的文件描述符上发出 ioctl 来设置(``EPIOCSPARAMS``)
|
||||
或获取(``EPIOCGPARAMS``) ``struct epoll_params``,用户程序定义如下:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct epoll_params {
|
||||
uint32_t busy_poll_usecs;
|
||||
uint16_t busy_poll_budget;
|
||||
uint8_t prefer_busy_poll;
|
||||
|
||||
/* 将结构填充到 64 位的倍数 */
|
||||
uint8_t __pad;
|
||||
};
|
||||
|
||||
IRQ缓解
|
||||
-------
|
||||
|
||||
虽然忙轮询旨在用于低延迟应用,但类似的机制可用于减少中断请求。
|
||||
|
||||
每秒高请求的应用程序(尤其是路由/转发应用程序和特别使用 AF_XDP 套接字的应用程序)
|
||||
可能希望在处理完一个请求或一批数据包之前不被中断。
|
||||
|
||||
此类应用程序可以向内核承诺会定期执行忙轮询操作,而驱动程序应将设备的中断请求永久屏蔽。
|
||||
通过使用 ``SO_PREFER_BUSY_POLL`` 套接字选项可启用此模式。为避免系统出现异常,如果
|
||||
在 ``gro_flush_timeout`` 时间内没有进行任何忙轮询调用,该承诺将被撤销。对于基于
|
||||
epoll 的忙轮询应用程序,可以将 ``struct epoll_params`` 结构体中的 ``prefer_busy_poll``
|
||||
字段设置为 1,并使用 ``EPIOCSPARAMS`` 输入 / 输出控制(ioctl)操作来启用此模式。
|
||||
更多详情请参阅上述章节。
|
||||
|
||||
NAPI 忙轮询的 budget 低于默认值(这符合正常忙轮询的低延迟意图)。减少中断请求的场景中
|
||||
并非如此,因此 budget 可以通过 ``SO_BUSY_POLL_BUDGET`` 套接字选项进行调整。对于基于
|
||||
epoll 的忙轮询应用程序,可以通过调整 ``struct epoll_params`` 中的 ``busy_poll_budget``
|
||||
字段为特定值,并使用 ``EPIOCSPARAMS`` ioctl 在特定 epoll 上下文中设置。更多详细信
|
||||
息请参见上述部分。
|
||||
|
||||
需要注意的是,为 ``gro_flush_timeout`` 选择较大的值会延迟中断请求,以实现更好的批
|
||||
量处理,但在系统未满载时会增加延迟。为 ``gro_flush_timeout`` 选择较小的值可能会因
|
||||
设备中断请求和软中断处理而干扰尝试进行忙轮询的用户应用程序。应权衡这些因素后谨慎选择
|
||||
该值。基于 epoll 的忙轮询应用程序可以通过为 ``maxevents`` 选择合适的值来减少用户
|
||||
处理的干扰。
|
||||
|
||||
用户可能需要考虑使用另一种方法,IRQ 挂起,以帮助应对这些权衡问题。
|
||||
|
||||
IRQ挂起
|
||||
-------
|
||||
|
||||
IRQ 挂起是一种机制,其中设备 IRQ 在 epoll 触发 NAPI 数据包处理期间被屏蔽。
|
||||
|
||||
只要应用程序对 epoll_wait 的调用成功获取事件,内核就会推迟 IRQ 挂起定时器。如果
|
||||
在忙轮询期间没有获取任何事件(例如,因为网络流量减少),则会禁用IRQ挂起功能,并启
|
||||
用上述减少中断请求的策略。
|
||||
|
||||
这允许用户在 CPU 消耗和网络处理效率之间取得平衡。
|
||||
|
||||
要使用此机制:
|
||||
|
||||
1. 每个 NAPI 的配置参数 ``irq-suspend-timeout`` 应设置为应用程序可以挂起
|
||||
IRQ 的最大时间(纳秒)。这通过 netlink 完成,如上所述。此超时时间作为一
|
||||
种安全机制,如果应用程序停滞,将重新启动中断驱动程序的中断处理。此值应选择
|
||||
为覆盖用户应用程序调用 epoll_wait 处理数据所需的时间,需注意的是,应用程
|
||||
序可通过在调用 epoll_wait 时设置 ``max_events`` 来控制获取的数据量。
|
||||
|
||||
2. sysfs 参数或每个 NAPI 的配置参数 ``gro_flush_timeout`` 和 ``napi_defer_hard_irqs``
|
||||
可以设置为较低值。它们将用于在忙轮询未找到数据时延迟 IRQs。
|
||||
|
||||
3. 必须将 ``prefer_busy_poll`` 标志设置为 true。如前文所述,可使用 ``EPIOCSPARAMS``
|
||||
ioctl操作来完成此设置。
|
||||
|
||||
4. 应用程序按照上述方式使用 epoll 触发 NAPI 数据包处理。
|
||||
|
||||
如上所述,只要后续对 epoll_wait 的调用向用户空间返回事件,``irq-suspend-timeout``
|
||||
就会被推迟并且 IRQ 会被禁用。这允许应用程序在无干扰的情况下处理数据。
|
||||
|
||||
一旦 epoll_wait 的调用没有找到任何事件,IRQ 挂起会被自动禁用,并且 ``gro_flush_timeout``
|
||||
和 ``napi_defer_hard_irqs`` 缓解机制将开始起作用。
|
||||
|
||||
预期是 ``irq-suspend-timeout`` 的设置值会远大于 ``gro_flush_timeout``,因为 ``irq-suspend-timeout``
|
||||
应在一个用户空间处理周期内暂停中断请求。
|
||||
|
||||
虽然严格来说不必通过 ``napi_defer_hard_irqs`` 和 ``gro_flush_timeout`` 来执行 IRQ 挂起,
|
||||
但强烈建议这样做。
|
||||
|
||||
中断请求挂起会使系统在轮询模式和由中断驱动的数据包传输模式之间切换。在网络繁忙期间,``irq-suspend-timeout``
|
||||
会覆盖 ``gro_flush_timeout``,使系统保持忙轮询状态,但是当 epoll 未发现任何事件时,``gro_flush_timeout``
|
||||
和 ``napi_defer_hard_irqs`` 的设置将决定下一步的操作。
|
||||
|
||||
有三种可能的网络处理和数据包交付循环:
|
||||
|
||||
1) 硬中断 -> 软中断 -> NAPI 轮询;基本中断交付
|
||||
2) 定时器 -> 软中断 -> NAPI 轮询;延迟的 IRQ 处理
|
||||
3) epoll -> 忙轮询 -> NAPI 轮询;忙循环
|
||||
|
||||
循环 2 可以接管循环 1,如果设置了 ``gro_flush_timeout`` 和 ``napi_defer_hard_irqs``。
|
||||
|
||||
如果设置了 ``gro_flush_timeout`` 和 ``napi_defer_hard_irqs``,循环 2 和 3 将互相“争夺”控制权。
|
||||
|
||||
在繁忙时期,``irq-suspend-timeout`` 用作循环 2 的定时器,这基本上使网络处理倾向于循环 3。
|
||||
|
||||
如果不设置 ``gro_flush_timeout`` 和 ``napi_defer_hard_irqs``,循环 3 无法从循环 1 接管。
|
||||
|
||||
因此,建议设置 ``gro_flush_timeout`` 和 ``napi_defer_hard_irqs``,因为若不这样做,设置
|
||||
``irq-suspend-timeout`` 可能不会有明显效果。
|
||||
|
||||
.. _threaded_zh_CN:
|
||||
|
||||
线程化NAPI
|
||||
----------
|
||||
|
||||
线程化 NAPI 是一种操作模式,它使用专用的内核线程而非软件中断上下文来进行 NAPI 处理。这种配置
|
||||
是针对每个网络设备的,并且会影响该设备的所有 NAPI 实例。每个 NAPI 实例将生成一个单独的线程
|
||||
(称为 ``napi/${ifc-name}-${napi-id}`` )。
|
||||
|
||||
建议将每个内核线程固定到单个 CPU 上,这个 CPU 与处理中断的 CPU 相同。请注意,中断请求(IRQ)
|
||||
和 NAPI 实例之间的映射关系可能并不简单(并且取决于驱动程序)。NAPI 实例 ID 的分配顺序将与内
|
||||
核线程的进程 ID 顺序相反。
|
||||
|
||||
线程化 NAPI 是通过向网络设备的 sysfs 目录中的 ``threaded`` 文件写入 0 或 1 来控制的。
|
||||
|
||||
.. rubric:: 脚注
|
||||
|
||||
.. [#] NAPI 最初在 2.4 Linux 中被称为 New API。
|
||||
92
Documentation/translations/zh_CN/networking/netif-msg.rst
Normal file
92
Documentation/translations/zh_CN/networking/netif-msg.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/netif-msg.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Wang Yaxin <wang.yaxin@zte.com.cn>
|
||||
|
||||
================
|
||||
网络接口消息级别
|
||||
================
|
||||
|
||||
网络接口消息级别设置的设计方案。
|
||||
|
||||
历史背景
|
||||
--------
|
||||
|
||||
调试消息接口的设计遵循并受制于向后兼容性及历史实践。理解其发展历史有助于把握
|
||||
当前实践,并将其与旧版驱动代码相关联。
|
||||
|
||||
自Linux诞生之初,每个网络设备驱动均包含一个本地整型变量以控制调试消息级别。
|
||||
消息级别范围为0至7,数值越大表示输出越详细。
|
||||
|
||||
消息级别的定义在3级之后未明确细化,但实际实现通常与指定级别相差±1。驱动程序
|
||||
成熟后,冗余的详细级别消息常被移除。
|
||||
|
||||
- 0 最简消息,仅显示致命错误的关键信息。
|
||||
- 1 标准消息,初始化状态。无运行时消息。
|
||||
- 2 特殊介质选择消息,通常由定时器驱动。
|
||||
- 3 接口开启和停止消息,包括正常状态信息。
|
||||
- 4 Tx/Rx帧错误消息及异常驱动操作。
|
||||
- 5 Tx数据包队列信息、中断事件。
|
||||
- 6 每个完成的Tx数据包和接收的Rx数据包状态。
|
||||
- 7 Tx/Rx数据包初始内容。
|
||||
|
||||
最初,该消息级别变量在各驱动中具有唯一名称(如"lance_debug"),便于通过
|
||||
内核符号调试器定位和修改其设置。模块化内核出现后,变量统一重命名为"debug",
|
||||
并作为模块参数设置。
|
||||
|
||||
这种方法效果良好。然而,人们始终对附加功能存在需求。多年来,以下功能逐渐
|
||||
成为合理且易于实现的增强方案:
|
||||
|
||||
- 通过ioctl()调用修改消息级别。
|
||||
- 按接口而非驱动设置消息级别。
|
||||
- 对发出的消息类型进行更具选择性的控制。
|
||||
|
||||
netif_msg 建议添加了这些功能,仅带来了轻微的复杂性增加和代码规模增长。
|
||||
|
||||
推荐方案如下:
|
||||
|
||||
- 保留驱动级整型变量"debug"作为模块参数,默认值为'1'。
|
||||
|
||||
- 添加一个名为 "msg_enable" 的接口私有变量。该变量是位图而非级别,
|
||||
并按如下方式初始化::
|
||||
|
||||
1 << debug
|
||||
|
||||
或更精确地说::
|
||||
|
||||
debug < 0 ? 0 : 1 << min(sizeof(int)-1, debug)
|
||||
|
||||
消息应从以下形式更改::
|
||||
|
||||
if (debug > 1)
|
||||
printk(MSG_DEBUG "%s: ...
|
||||
|
||||
改为::
|
||||
|
||||
if (np->msg_enable & NETIF_MSG_LINK)
|
||||
printk(MSG_DEBUG "%s: ...
|
||||
|
||||
消息级别命名对应关系
|
||||
|
||||
|
||||
========= =================== ============
|
||||
旧级别 名称 位位置
|
||||
========= =================== ============
|
||||
1 NETIF_MSG_PROBE 0x0002
|
||||
2 NETIF_MSG_LINK 0x0004
|
||||
2 NETIF_MSG_TIMER 0x0004
|
||||
3 NETIF_MSG_IFDOWN 0x0008
|
||||
3 NETIF_MSG_IFUP 0x0008
|
||||
4 NETIF_MSG_RX_ERR 0x0010
|
||||
4 NETIF_MSG_TX_ERR 0x0010
|
||||
5 NETIF_MSG_TX_QUEUED 0x0020
|
||||
5 NETIF_MSG_INTR 0x0020
|
||||
6 NETIF_MSG_TX_DONE 0x0040
|
||||
6 NETIF_MSG_RX_STATUS 0x0040
|
||||
7 NETIF_MSG_PKTDATA 0x0080
|
||||
========= =================== ============
|
||||
92
Documentation/translations/zh_CN/networking/netmem.rst
Normal file
92
Documentation/translations/zh_CN/networking/netmem.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/netmem.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Wang Yaxin <wang.yaxin@zte.com.cn>
|
||||
|
||||
==================
|
||||
网络驱动支持Netmem
|
||||
==================
|
||||
|
||||
本文档概述了网络驱动支持netmem(一种抽象内存类型)的要求,该内存类型
|
||||
支持设备内存 TCP 等功能。通过支持netmem,驱动可以灵活适配不同底层内
|
||||
存类型(如设备内存TCP),且无需或仅需少量修改。
|
||||
|
||||
Netmem的优势:
|
||||
|
||||
* 灵活性:netmem 可由不同内存类型(如 struct page、DMA-buf)支持,
|
||||
使驱动程序能够支持设备内存 TCP 等各种用例。
|
||||
* 前瞻性:支持netmem的驱动可无缝适配未来依赖此功能的新特性。
|
||||
* 简化开发:驱动通过统一API与netmem交互,无需关注底层内存的实现差异。
|
||||
|
||||
驱动RX要求
|
||||
==========
|
||||
|
||||
1. 驱动必须支持page_pool。
|
||||
|
||||
2. 驱动必须支持tcp-data-split ethtool选项。
|
||||
|
||||
3. 驱动必须使用page_pool netmem API处理有效载荷内存。当前netmem API
|
||||
与page API一一对应。转换时需要将page API替换为netmem API,并用驱动
|
||||
中的netmem_refs跟踪内存而非 `struct page *`:
|
||||
|
||||
- page_pool_alloc -> page_pool_alloc_netmem
|
||||
- page_pool_get_dma_addr -> page_pool_get_dma_addr_netmem
|
||||
- page_pool_put_page -> page_pool_put_netmem
|
||||
|
||||
目前并非所有页 pageAPI 都有对应的 netmem 等效接口。如果你的驱动程序
|
||||
依赖某个尚未实现的 netmem API,请直接实现并提交至 netdev@邮件列表,
|
||||
或联系维护者及 almasrymina@google.com 协助添加该 netmem API。
|
||||
|
||||
4. 驱动必须设置以下PP_FLAGS:
|
||||
|
||||
- PP_FLAG_DMA_MAP:驱动程序无法对 netmem 执行 DMA 映射。此时驱动
|
||||
程序必须将 DMA 映射操作委托给 page_pool,由其判断何时适合(或不适合)
|
||||
进行 DMA 映射。
|
||||
- PP_FLAG_DMA_SYNC_DEV:驱动程序无法保证 netmem 的 DMA 地址一定能
|
||||
完成 DMA 同步。此时驱动程序必须将 DMA 同步操作委托给 page_pool,由
|
||||
其判断何时适合(或不适合)进行 DMA 同步。
|
||||
- PP_FLAG_ALLOW_UNREADABLE_NETMEM:仅当启用 tcp-data-split 时,
|
||||
驱动程序必须显式设置此标志。
|
||||
|
||||
5. 驱动不得假设netmem可读或基于页。当netmem_address()返回NULL时,表示
|
||||
内存不可读。驱动需正确处理不可读的netmem,例如,当netmem_address()返回
|
||||
NULL时,避免访问内容。
|
||||
|
||||
理想情况下,驱动程序不应通过netmem_is_net_iov()等辅助函数检查底层
|
||||
netmem 类型,也不应通过netmem_to_page()或netmem_to_net_iov()将
|
||||
netmem 转换为其底层类型。在大多数情况下,系统会提供抽象这些复杂性的
|
||||
netmem 或 page_pool 辅助函数(并可根据需要添加更多)。
|
||||
|
||||
6. 驱动程序必须使用page_pool_dma_sync_netmem_for_cpu()代替dma_sync_single_range_for_cpu()。
|
||||
对于某些内存提供者,CPU 的 DMA 同步将由 page_pool 完成;而对于其他提供者
|
||||
(特别是 dmabuf 内存提供者),CPU 的 DMA 同步由使用 dmabuf API 的用户空
|
||||
间负责。驱动程序必须将整个 DMA 同步操作委托给 page_pool,以确保操作正确执行。
|
||||
|
||||
7. 避免在 page_pool 之上实现特定于驱动程序内存回收机制。由于 netmem 可能
|
||||
不由struct page支持,驱动程序不能保留struct page来进行自定义回收。不过,
|
||||
可为此目的通过page_pool_fragment_netmem()或page_pool_ref_netmem()保留
|
||||
page_pool 引用,但需注意某些 netmem 类型的循环时间可能更长(例如零拷贝场景
|
||||
下用户空间持有引用的情况)。
|
||||
|
||||
驱动TX要求
|
||||
==========
|
||||
|
||||
1. 驱动程序绝对不能直接把 netmem 的 dma_addr 传递给任何 dma-mapping API。这
|
||||
是由于 netmem 的 dma_addr 可能源自 dma-buf 这类和 dma-mapping API 不兼容的
|
||||
源头。
|
||||
|
||||
应当使用netmem_dma_unmap_page_attrs()和netmem_dma_unmap_addr_set()等辅助
|
||||
函数来替代dma_unmap_page[_attrs]()、dma_unmap_addr_set()。不管 dma_addr
|
||||
来源如何,netmem 的这些变体都能正确处理 netmem dma_addr,在合适的时候会委托给
|
||||
dma-mapping API 去处理。
|
||||
|
||||
目前,并非所有的 dma-mapping API 都有对应的 netmem 版本。要是你的驱动程序需要
|
||||
使用某个还不存在的 netmem API,你可以自行添加并提交到 netdev@,也可以联系维护
|
||||
人员或者发送邮件至 almasrymina@google.com 寻求帮助。
|
||||
|
||||
2. 驱动程序应通过设置 netdev->netmem_tx = true 来表明自身支持 netmem 功能。
|
||||
85
Documentation/translations/zh_CN/networking/vxlan.rst
Normal file
85
Documentation/translations/zh_CN/networking/vxlan.rst
Normal file
@@ -0,0 +1,85 @@
|
||||
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/vxlan.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
范雨 Fan Yu <fan.yu9@zte.com.cn>
|
||||
|
||||
:校译:
|
||||
|
||||
- 邱禹潭 Qiu Yutan <qiu.yutan@zte.com.cn>
|
||||
- 徐鑫 xu xin <xu.xin16@zte.com.cn>
|
||||
|
||||
==========================
|
||||
虚拟扩展本地局域网协议文档
|
||||
==========================
|
||||
|
||||
VXLAN 协议是一种隧道协议,旨在解决 IEEE 802.1q 中 VLAN ID(4096)有限的问题。
|
||||
VXLAN 将标识符的大小扩展到 24 位(16777216)。
|
||||
|
||||
VXLAN 在 IETF RFC 7348 中进行了描述,并已由多家供应商设计实现。
|
||||
该协议通过 UDP 协议运行,并使用特定目的端口。
|
||||
本文档介绍了 Linux 内核隧道设备,Openvswitch 也有单独的 VXLAN 实现。
|
||||
|
||||
与大多数隧道不同,VXLAN 是 1 对 N 的网络,而不仅仅是点对点网络。
|
||||
VXLAN 设备可以通过类似于学习桥接器的方式动态学习另一端点的 IP 地址,也可以利用静态配置的转发条目。
|
||||
|
||||
VXLAN 的管理方式与它的两个近邻 GRE 和 VLAN 相似。
|
||||
配置 VXLAN 需要 iproute2 的版本与 VXLAN 首次向上游合并的内核版本相匹配。
|
||||
|
||||
1. 创建 vxlan 设备::
|
||||
|
||||
# ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev eth1 dstport 4789
|
||||
|
||||
这将创建一个名为 vxlan0 的网络设备,该设备通过 eth1 使用组播组 239.1.1.1 处理转发表中没有对应条目的流量。
|
||||
目标端口号设置为 IANA 分配的值 4789,VXLAN 的 Linux 实现早于 IANA 选择标准目的端口号的时间。
|
||||
因此默认使用 Linux 选择的值,以保持向后兼容性。
|
||||
|
||||
2. 删除 vxlan 设备::
|
||||
|
||||
# ip link delete vxlan0
|
||||
|
||||
3. 查看 vxlan 设备信息::
|
||||
|
||||
# ip -d link show vxlan0
|
||||
|
||||
使用新的 bridge 命令可以创建、销毁和显示 vxlan 转发表。
|
||||
|
||||
1. 创建vxlan转发表项::
|
||||
|
||||
# bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
|
||||
|
||||
2. 删除vxlan转发表项::
|
||||
|
||||
# bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
|
||||
|
||||
3. 显示vxlan转发表项::
|
||||
|
||||
# bridge fdb show dev vxlan0
|
||||
|
||||
以下网络接口控制器特性可能表明对 UDP 隧道相关的卸载支持(最常见的是 VXLAN 功能,
|
||||
但是对特定封装协议的支持取决于网络接口控制器):
|
||||
|
||||
- `tx-udp_tnl-segmentation`
|
||||
- `tx-udp_tnl-csum-segmentation`
|
||||
对 UDP 封装帧执行 TCP 分段卸载的能力
|
||||
|
||||
- `rx-udp_tunnel-port-offload`
|
||||
在接收端解析 UDP 封装帧,使网络接口控制器能够执行协议感知卸载,
|
||||
例如内部帧的校验和验证卸载(只有不带协议感知卸载的网络接口控制器才需要)
|
||||
|
||||
对于支持 `rx-udp_tunnel-port-offload` 的设备,可使用 `ethtool` 查询当前卸载端口的列表::
|
||||
|
||||
$ ethtool --show-tunnels eth0
|
||||
Tunnel information for eth0:
|
||||
UDP port table 0:
|
||||
Size: 4
|
||||
Types: vxlan
|
||||
No entries
|
||||
UDP port table 1:
|
||||
Size: 4
|
||||
Types: geneve, vxlan-gpe
|
||||
Entries (1):
|
||||
port 1230, vxlan-gpe
|
||||
126
Documentation/translations/zh_CN/networking/xfrm_proc.rst
Normal file
126
Documentation/translations/zh_CN/networking/xfrm_proc.rst
Normal file
@@ -0,0 +1,126 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/xfrm_proc.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Wang Yaxin <wang.yaxin@zte.com.cn>
|
||||
|
||||
=================================
|
||||
XFRM proc - /proc/net/xfrm_* 文件
|
||||
=================================
|
||||
|
||||
作者:Masahide NAKAMURA <nakam@linux-ipv6.org>
|
||||
|
||||
|
||||
转换统计信息
|
||||
------------
|
||||
|
||||
`xfrm_proc` 提供一组统计计数器,显示转换过程中丢弃的数据包及其原因。
|
||||
这些计数器属于Linux私有MIB的一部分,可通过 `/proc/net/xfrm_stat`
|
||||
查看。
|
||||
|
||||
入站错误
|
||||
~~~~~~~~
|
||||
|
||||
XfrmInError:
|
||||
未匹配其他类别的所有错误
|
||||
|
||||
XfrmInBufferError:
|
||||
缓冲区不足
|
||||
|
||||
XfrmInHdrError:
|
||||
头部错误
|
||||
|
||||
XfrmInNoStates:
|
||||
未找到状态
|
||||
(入站SPI、地址或SA的IPsec协议不匹配)
|
||||
|
||||
XfrmInStateProtoError:
|
||||
转换协议相关的错误
|
||||
(如SA密钥错误)
|
||||
|
||||
XfrmInStateModeError:
|
||||
转换模式相关的错误
|
||||
|
||||
XfrmInStateSeqError:
|
||||
序列号错误
|
||||
序列号超出窗口范围
|
||||
|
||||
XfrmInStateExpired:
|
||||
状态已过期
|
||||
|
||||
XfrmInStateMismatch:
|
||||
状态选项不匹配
|
||||
(如UDP封装类型不匹配)
|
||||
|
||||
XfrmInStateInvalid:
|
||||
无效状态
|
||||
|
||||
XfrmInTmplMismatch:
|
||||
状态模板不匹配
|
||||
(如入站SA正确但SP规则错误)
|
||||
|
||||
XfrmInNoPols:
|
||||
未找到状态的对应策略
|
||||
(如入站SA正确但无SP规则)
|
||||
|
||||
XfrmInPolBlock:
|
||||
丢弃的策略
|
||||
|
||||
XfrmInPolError:
|
||||
错误的策略
|
||||
|
||||
XfrmAcquireError:
|
||||
状态未完全获取即被使用
|
||||
|
||||
XfrmFwdHdrError:
|
||||
转发路由禁止
|
||||
|
||||
XfrmInStateDirError:
|
||||
状态方向不匹配
|
||||
(输入路径查找到输出状态,预期是输入状态或者无方向)
|
||||
|
||||
出站错误
|
||||
~~~~~~~~
|
||||
XfrmOutError:
|
||||
未匹配其他类别的所有错误
|
||||
|
||||
XfrmOutBundleGenError:
|
||||
捆绑包生成错误
|
||||
|
||||
XfrmOutBundleCheckError:
|
||||
捆绑包校验错误
|
||||
|
||||
XfrmOutNoStates:
|
||||
未找到状态
|
||||
|
||||
XfrmOutStateProtoError:
|
||||
转换协议特定错误
|
||||
|
||||
XfrmOutStateModeError:
|
||||
转换模式特定错误
|
||||
|
||||
XfrmOutStateSeqError:
|
||||
序列号错误
|
||||
(序列号溢出)
|
||||
|
||||
XfrmOutStateExpired:
|
||||
状态已过期
|
||||
|
||||
XfrmOutPolBlock:
|
||||
丢弃策略
|
||||
|
||||
XfrmOutPolDead:
|
||||
失效策略
|
||||
|
||||
XfrmOutPolError:
|
||||
错误策略
|
||||
|
||||
XfrmOutStateInvalid:
|
||||
无效状态(可能已过期)
|
||||
|
||||
XfrmOutStateDirError:
|
||||
状态方向不匹配(输出路径查找到输入状态,预期为输出状态或无方向)
|
||||
@@ -182,11 +182,11 @@ Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
|
||||
可以获得所有版权所有者的同意(或者从内核中删除他们的代码)。因此,尤其是在
|
||||
可预见的将来,许可证不大可能迁移到GPL的版本3。
|
||||
|
||||
所有贡献给内核的代码都必须是合法的免费软件。因此,不接受匿名(或化名)贡献
|
||||
者的代码。所有贡献者都需要在他们的代码上“sign off(签发)”,声明代码可以
|
||||
在GPL下与内核一起分发。无法提供未被其所有者许可为免费软件的代码,或可能为
|
||||
内核造成版权相关问题的代码(例如,由缺乏适当保护的反向工程工作派生的代码)
|
||||
不能被接受。
|
||||
所有贡献给内核的代码都必须是合法的免费软件。因此,出于这个原因,身份不明的
|
||||
贡献者或匿名贡献者提交的代码将不予接受。所有贡献者都需要在他们的代码上
|
||||
“sign off(签发)”,声明代码可以在GPL下与内核一起分发。无法提供未被其所有者
|
||||
许可为免费软件的代码,或可能为内核造成版权相关问题的代码(例如,由缺乏适当
|
||||
保护的反向工程工作派生的代码)不能被接受。
|
||||
|
||||
有关版权问题的提问在Linux开发邮件列表中很常见。这样的问题通常会得到不少答案,
|
||||
但请记住,回答这些问题的人不是律师,不能提供法律咨询。如果您有关于Linux源代码
|
||||
|
||||
@@ -292,12 +292,11 @@ Quilt 是一个补丁管理系统,而不是源代码管理系统。它不会
|
||||
一个潜在的危险,他们可能会被一堆电子邮件淹没、违反Linux列表上使用的约定,
|
||||
或者两者兼而有之。
|
||||
|
||||
大多数内核邮件列表都在vger.kernel.org上运行;主列表位于:
|
||||
大多数内核邮件列表都托管在 kernel.org;主列表位于:
|
||||
|
||||
http://vger.kernel.org/vger-lists.html
|
||||
https://subspace.kernel.org
|
||||
|
||||
不过,也有一些列表托管在别处;其中一些列表位于
|
||||
redhat.com/mailman/listinfo。
|
||||
其他地方也有邮件列表;请查看 MAINTAINERS 文件,获取与特定子系统相关的列表。
|
||||
|
||||
当然,内核开发的核心邮件列表是linux-kernel。这个列表是一个令人生畏的地方:
|
||||
每天的信息量可以达到500条,噪音很高,谈话技术性很强,且参与者并不总是表现出
|
||||
|
||||
@@ -177,10 +177,21 @@
|
||||
|
||||
- Reported-by: 指定报告此补丁修复的问题的用户;此标记用于表示感谢。
|
||||
|
||||
- Suggested-by: 表示该补丁思路由所提及的人提出,确保其创意贡献获得认可。
|
||||
这有望激励他们在未来继续提供帮助。
|
||||
|
||||
- Cc:指定某人收到了补丁的副本,并有机会对此发表评论。
|
||||
|
||||
在补丁中添加标签时要小心:只有Cc:才适合在没有指定人员明确许可的情况下添加。
|
||||
|
||||
在补丁中添加上述标签时需谨慎,因为除了 Cc:、Reported-by: 和 Suggested-by:,
|
||||
所有其他标签都需要被提及者的明确许可。对于这三个标签,若根据 lore 归档或提交
|
||||
历史记录,相关人员使用该姓名和电子邮件地址为 Linux 内核做出过贡献,则隐含许可
|
||||
已足够 -- 对于 Reported-by: 和 Suggested-by:,需确保报告或建议是公开进行的。
|
||||
请注意,从这个意义上讲,bugzilla.kernel.org 属于公开场合,但其使用的电子邮件地址
|
||||
属于私人信息;因此,除非相关人员曾在早期贡献中使用过这些邮箱,否则请勿在标签中
|
||||
公开它们。
|
||||
|
||||
寄送补丁
|
||||
--------
|
||||
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
变。他们真的,几乎毫无例外地,致力于创造他们所能做到的最好的内核;他们并
|
||||
没有试图给雇主的竞争对手造成不适。
|
||||
|
||||
- 请准备好应对看似“愚蠢”的代码风格修改请求,以及将部分代码拆分到内核
|
||||
共享模块的要求。维护者的职责之一是保持整体风格的一致性。有时这意味着,
|
||||
你在驱动中为解决某一问题而采用的巧妙取巧方案,实际上需要被提炼为通用的
|
||||
内核特性,以便未来复用。
|
||||
|
||||
所有这些归根结底就是,当审阅者向您发送评论时,您需要注意他们正在进行的技术
|
||||
评论。不要让他们的表达方式或你自己的骄傲阻止此事。当你在一个补丁上得到评论
|
||||
时,花点时间去理解评论人想说什么。如果可能的话,请修复审阅者要求您修复的内
|
||||
|
||||
@@ -113,6 +113,8 @@ Git提供了一些强大的工具,可以让您重写开发历史。一个不
|
||||
更改。在这方面 git request-pull 命令非常有用;它将按照其他开发人员所期望的
|
||||
格式化请求,并检查以确保您已记得将这些更改推送到公共服务器。
|
||||
|
||||
.. _cn_development_advancedtopics_reviews:
|
||||
|
||||
审阅补丁
|
||||
--------
|
||||
|
||||
@@ -126,8 +128,20 @@ Git提供了一些强大的工具,可以让您重写开发历史。一个不
|
||||
的建议是:把审阅评论当成问题而不是批评。询问“在这条路径中如何释放锁?”
|
||||
总是比说“这里的锁是错误的”更好。
|
||||
|
||||
当出现分歧时,另一个有用的技巧是邀请他人参与讨论。如果交流数次后讨论陷入僵局,
|
||||
可征求其他评审者或维护者的意见。通常,与某一评审者意见一致的人往往会保持沉默,
|
||||
除非被主动询问。众人意见会产生成倍的影响力。
|
||||
|
||||
不同的开发人员将从不同的角度审查代码。部分人会主要关注代码风格以及代码行是
|
||||
否有尾随空格。其他人会主要关注补丁作为一个整体实现的变更是否对内核有好处。
|
||||
同时也有人会检查是否存在锁问题、堆栈使用过度、可能的安全问题、在其他地方
|
||||
发现的代码重复、足够的文档、对性能的不利影响、用户空间ABI更改等。所有类型
|
||||
的检查,只要它们能引导更好的代码进入内核,都是受欢迎和值得的。
|
||||
|
||||
使用诸如 ``Reviewed-by`` 这类特定标签并无严格要求。事实上,即便提供了标签,也
|
||||
更鼓励用平实的英文撰写评审意见,因为这样的内容信息量更大,例如,“我查看了此次
|
||||
提交中 A、B、C 等方面的内容,认为没有问题。”显然,以某种形式提供评审信息或回复
|
||||
是必要的,否则维护者将完全无法知晓评审者是否已查看过补丁!
|
||||
|
||||
最后但同样重要的是,补丁评审可能会变成一个聚焦于指出问题的负面过程。请偶尔给予
|
||||
称赞,尤其是对新手贡献者!
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
speculation
|
||||
xz
|
||||
|
||||
TODOList:
|
||||
@@ -21,6 +22,5 @@ TODOList:
|
||||
* lzo
|
||||
* remoteproc
|
||||
* rpmsg
|
||||
* speculation
|
||||
* static-keys
|
||||
* tee
|
||||
|
||||
85
Documentation/translations/zh_CN/staging/speculation.rst
Normal file
85
Documentation/translations/zh_CN/staging/speculation.rst
Normal file
@@ -0,0 +1,85 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/staging/speculation.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
崔巍 Cui Wei <chris.wei.cui@gmail.com>
|
||||
|
||||
========
|
||||
推测执行
|
||||
========
|
||||
|
||||
本文档解释了推测执行的潜在影响,以及如何使用通用API来减轻不良影响。
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
为提高性能并减少平均延迟,许多现代处理器都采用分支预测等推测执行技术,执行结果
|
||||
可能在后续阶段被丢弃。
|
||||
|
||||
通常情况下,我们无法从架构状态(如寄存器内容)观察到推测执行。然而,在某些情况
|
||||
下从微架构状态观察其影响是可能的,例如数据是否存在于缓存中。这种状态可能会形成
|
||||
侧信道,通过观察侧信道可以提取秘密信息。
|
||||
|
||||
例如,在分支预测存在的情况下,边界检查可能被推测执行的代码忽略。考虑以下代码::
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else
|
||||
return array[index];
|
||||
}
|
||||
|
||||
在arm64上,可以编译成如下汇编序列::
|
||||
|
||||
CMP <index>, #MAX_ARRAY_ELEMS
|
||||
B.LT less
|
||||
MOV <returnval>, #0
|
||||
RET
|
||||
less:
|
||||
LDR <returnval>, [<array>, <index>]
|
||||
RET
|
||||
|
||||
处理器有可能误预测条件分支,并推测性装载array[index],即使index >= MAX_ARRAY_ELEMS。
|
||||
这个值随后会被丢弃,但推测的装载可能会影响微架构状态,随后可被测量到。
|
||||
|
||||
涉及多个依赖内存访问的更复杂序列可能会导致敏感信息泄露。以前面的示例为基础,考虑
|
||||
以下代码::
|
||||
|
||||
int load_dependent_arrays(int *arr1, int *arr2, int index)
|
||||
{
|
||||
int val1, val2,
|
||||
|
||||
val1 = load_array(arr1, index);
|
||||
val2 = load_array(arr2, val1);
|
||||
|
||||
return val2;
|
||||
}
|
||||
|
||||
根据推测,对load_array()的第一次调用可能会返回一个越界地址的值,而第二次调用将影响
|
||||
依赖于该值的微架构状态。这可能会提供一个任意读取原语。
|
||||
|
||||
缓解推测执行侧信道
|
||||
==================
|
||||
|
||||
内核提供了一个通用API以确保即使在推测情况下也能遵守边界检查。受推测执行侧信道影响
|
||||
的架构应当实现这些原语。
|
||||
|
||||
<linux/nospec.h>中的array_index_nospec()辅助函数可用于防止信息通过侧信道泄漏。
|
||||
|
||||
调用array_index_nospec(index, size)将返回一个经过净化的索引值,即使在CPU推测执行
|
||||
条件下,该值也会被严格限制在[0, size)范围内。
|
||||
|
||||
这可以用来保护前面的load_array()示例::
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else {
|
||||
index = array_index_nospec(index, MAX_ARRAY_ELEMS);
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user