RFC-0213:移除 devfs FIDL 多路复用

RFC-0213:移除 devfs FIDL 多路复用
状态已接受
区域
  • 驱动程序
说明

概述了移除 devfs 中的 FIDL 多路复用的原因和计划

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2023-03-28
审核日期(年-月-日)2023-03-17

摘要

此提案概述了移除 devfs 功能的过程,该功能会在单个连接上多路复用多个 FIDL 协议。该文档解释了移除此功能将解锁新驱动程序功能以及标准化驱动程序与 Fuchsia 其余部分的 FIDL 连接的原因。

设计初衷

驱动程序框架管理硬件设备与客户端之间的连接。历史上,此连接支持三种 FIDL 协议:

  • fuchsia.io/Node
  • fuchsia.device/Controller
  • 设备的实际 FIDL 协议

这种多路复用需要驱动程序框架拥有该通道,以便它可以处理节点和控制器协议。这可以防止底层驱动程序拥有该通道。这种设计意味着驱动程序框架必须在驱动程序和驱动程序主机之间维护一个 C FIDL 边界。这也意味着,驱动程序无法区分多个连接或存储每个连接的状态。这一限制导致出现了许多“跳板协议”,即驱动程序和客户端交换一对新通道,仅仅是为了避免使用多路复用通道。

这种多路复用违反了 FIDL 的组合设计原则。FIDL 设计原则规定,一个协议可以在编译时是多个协议的 composed。不过,驱动程序框架是在运行时执行此组合,并且不知道设备所使用的 FIDL 协议。在运行时进行多路复用时,多路复用协议中也可能会出现冲突的序数。

控制器协议的多路复用意味着无法使用 capability 路由来限制对 fuchsia.device/Controller 的访问。例如,/dev/class/input-report 的客户大多希望访问 fuchsia.input.report/Device。不过,fuchsia.device/Controller 会通过同一信道提供,因此能够解除绑定、重新绑定或设置这些设备的电源状态。如果设备的 FIDL 和控制器 FIDL 在同一信道上进行多路复用,则无法解决此路由问题。

在整个代码库中,Node 协议的多路复用用于克隆与设备的连接。虽然克隆设备连接的概念没问题,但这是底层驱动程序不支持的功能。此外,fuchsia.io/Node.Clone 的 API 会接受 fuchsia.io/Node 的服务器端,因此使用此 API 克隆设备的频道会导致频道的底层类型不准确。目前,有大量客户端代码通过直接调用 FIDL 或使用文件描述符来执行此操作。Fuchsia 已制定使用类型化通道的最佳实践,我们应在该领域强制执行这些最佳实践。

利益相关方

教员

  • abarth

Reviewers:

  • abarth
  • cja
  • csuter
  • surajmalhotra
  • tamird
  • yifei

咨询了

社交

此 RFC 起源于一份设计文档,该文档已通过驱动程序框架团队的设计审核。

要求

这些要求分为两类:迁移和最终状态。

Migration

迁移计划必须是包含许可名单的软迁移。Fuchsia 包含大量与树内和树外驱动程序客户端交互的代码。无法从所有 devfs 中同时移除多路复用。通过包含各个任务的许可名单,我们可以逐步推进迁移,并防止迁移出现倒退。

迁移应尽可能机械化。每个客户端更新都应足够简单,以便不熟悉驱动程序或驱动程序框架的用户能够执行迁移。每次更新的流程越机械化,迁移速度就越快。

结束状态

与设备的连接应明确说明。客户端是请求设备控制器还是底层设备协议,应该很明确。不会进行 FIDL 多路复用,因此客户端将能够使用类型化通道。

驱动程序框架不会在与设备的连接上提供 fuchsia.io/Node

驾驶员将能够拥有自己的客户端连接。移除 FIDL 多路复用后,还需要进行另一项迁移,将驱动程序移至 DDK API,以便在客户端尝试连接时为驱动程序提供通道。通过此次迁移,驱动程序将能够拥有每个连接的状态,并使用 Fuchsia 代码库的其余部分使用的 FIDL 绑定。

设计

连接到 fuchsia.device/Controller

为了连接到 fuchsia.device/Controller,客户端必须在 devfs 文件系统中打开特定节点。此节点将命名为 device_controller,并将同时在 devfs 类路径和 devfs 拓扑路径中提供。

如果客户端从 /dev/class/input-report/abcd 获取设备协议,则控制器将在 /dev/class/input-report/abcd/device_controller 处可用。

如果客户端从 /dev/sys/platform/pci/00:12 获取设备协议,则控制器将在 /dev/sys/platform/pci/00:12/device_controller 处可用。

从 /dev/class/ 中移除多路复用

devfs 类路径将有两个许可名单:一个用于 fuchsia.io/Node,另一个用于 fuchsia.device/Controller。这些许可名单将包含仍在多路复用相应协议的 /dev/class/{protocol} 的名称。

在客户端更新为停止依赖于多路复用行为后,此许可名单中的条目将被移除。

从拓扑路径中移除多路复用

移除类路径的许可名单中的条目后,拓扑路径中的相应条目也会被移除多路复用。

例如,如果 /dev/class/input-report 移除了 fuchsia.io/Node,则与这些输入设备对应的拓扑路径也不再提供 fuchsia.io/Node

实现

许可名单将在驱动程序框架中实现。从许可名单中移除条目需要更新依赖于此多路复用功能的客户端。

性能

移除 FIDL 多路复用对性能应该没有显著影响。由于不需要尝试将发送到设备的 FIDL 消息分派到节点或控制器 API,因此性能可能会略有提升。

工效学设计

驱动程序框架可能会决定添加一个辅助库来连接到 Controller API。这取决于前几次迁移。

如果客户端尝试在设备上调用未知的 FIDL 协议,驱动程序框架也会更新为记录错误。这意味着,如果客户端仍错误地依赖于多路复用,则会出现 ERROR 日志。遗憾的是,将错误日志正确归因于特定客户端并不容易。

向后兼容性

无法移除 FIDL 多路复用并保持向后兼容性。

安全注意事项

此提案没有安全注意事项。这项工作可以使客户端行为更明确、更易于理解,从而略微提高 devfs 的安全性。

将来,驱动程序框架将希望限制对 fuchsia.device/Controller 的访问。例如,获得对 /dev/class/input-report 访问权限的客户端无需访问控制器协议。限制这项功能有助于提高安全性,而移除 FIDL 多路复用功能可让驱动程序框架在未来限制此功能。限制此协议的实际计划不在本 RFC 的范围内,可以作为后续项目来处理。

隐私注意事项

此提案没有隐私权注意事项。

测试

我们将测试许可名单的驱动程序框架功能以及移除多路复用功能。

遗憾的是,每次移除许可名单都必须依赖 CQ 中的现有测试覆盖率。由于这种多路复用是在 FIDL 类型系统之外进行的,因此没有很好的方法可以静态确定哪些客户端依赖于多路复用行为。

文档

我们添加了“打开项目”页面形式的文档。此页面概述了许可名单、动机和更新步骤。项目完成后,任何客户端都不会依赖此行为,因此无需任何文档。

缺点、替代方案和未知情况

在 DFv2 中使用服务功能

目前,执行此工作的主要替代方案是等待“驱动程序作为组件 (DFv2)”工作完成,然后直接将客户端迁移为使用服务功能

不过,只有在所有可能的开发板上启用 DFv2 后,才能开始将客户端迁移到服务功能。在此期间,我们将添加更多依赖于多路复用功能的客户端,包括更难迁移的树外客户端。此外,DFv1 兼容性 shim 需要支持 FIDL 多路复用,以保留现有行为,并且将自己导出到 devfs 的 DFv2 驱动程序也需要支持多路复用。从 DFv1 中移除此技术债务将简化 DFv2 设计,而无需将此技术债务带入后续版本。

如果客户端同时需要解开 FIDL 多路复用,则将客户端迁移到服务功能会更加困难。如果一次解决一个问题,这些迁移会更快完成。

在先技术和参考文档

FIDL 概述了协议组合的最佳实践