接收端缩放版本 2 (RSSv2)

接收端缩放可提高与处理多处理器系统上网络数据相关的系统性能。 NDIS 6.80 及更高版本支持 RSS 版本 2 (RSSv2),它通过提供队列的动态、按 VPort 分布来扩展 RSS。

概述

与 RSSv1 相比,RSSv2 缩短了 CPU 负载测量和更新间接表之间的时间。 这可以避免在高流量情况下变慢。 为此,RSSv2 在处理请求的处理器上下文中,在 IRQL = DISPATCH_LEVEL 执行其操作,并且仅对指向当前处理器的间接表条目的子集进行操作。 这意味着 RSSv2 可以比 RSSv1 更快速地将接收队列动态分散到多个处理器上。

RSSv2 中引入了两个 OID,OID_GEN_RECEIVE_SCALE_PARAMETERS_V2OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES,以便微型端口驱动程序分别设置适当的 RSS 功能和控制间接表。 OID_GEN_RECEIVE_SCALE_PARAMETERS_V2是常规 OID,而OID_GEN_RSS_标准版T_INDIRECTION_ENTRIES是无法返回NDIS_STATUS_PENDING的同步 OID。 有关这些 OID 的详细信息,请参阅其单独的参考页。 有关同步 OID 的详细信息,请参阅 NDIS 6.80 中的同步 OID 请求接口。

RSSv2 术语

本主题使用以下术语:

术语 定义
RSSv1 第一代接收方缩放机制。 使用 OID_GEN_RECEIVE_SCALE_PARAMETERS
RSSv2 本主题中所述的 Windows 10 版本 1803 及更高版本中支持的第二代接收端缩放机制。
缩放实体 本机 RSS 模式下的微型端口适配器本身或 RSSv2 模式下的 VPort。
这儿 给定缩放实体的间接表条目(ITE)。 每个 VPort 的 ITE 总数不能超过 NumberOfIndirectionTableEntriesPerNonDefaultPFVPort 或 NumberOfIndirectionTableEntriesForDefaultVPort(在 VMQ 模式下)或本机 RSS 案例中的 128。 NumberOfIndirectionTableEntriesPerNonDefaultPFVPortNumberOfIndirectionTableEntriesForDefaultVPort 是NDIS_NIC_SWITCH_CAPABILITIES结构的成员
缩放模式 每个 VPort vmswitch 策略,用于控制其 ITE 在运行时的处理方式。 这可能是静态的(由于负载更改而没有 ITE 移动)或动态(扩展和合并,具体取决于当前的流量负载)。
队列 一个基础硬件对象(队列),用于备份 ITE。 根据硬件和间接表,配置队列可能会支持多个 ITE。 队列总数(包括默认队列使用的队列)不能超过通常由管理员设置的预配置限制。
默认处理器 接收无法计算其哈希的数据包的处理器。 每个 VPort 都有一个默认处理器。
主处理器 在 VPort 创建期间,指定为 NDIS_NIC_SWITCH_VPORT_PARAMETERS 结构的 ProcessorAffinity 成员的处理器。 可以在运行时更新此处理器,并指定 VMQ 流量的定向位置。
源 CPU ITE 当前映射到的处理器。
目标 CPU ITE 要重新映射到的处理器(使用 RSSv2)。
执行组件 CPU 要对其发出 RSSv2 请求的处理器。

在微型端口驱动程序中播发 RSSv2 功能

微型端口驱动程序使用 NDIS_RSS_CAPS_SUPPORTS_INDEPENDENT_ENTRY_MOVE 标志设置 NDIS_RECEIVE_SCALE_CAPABILITIES 结构的 CapabilitiesFlags 成员来播发 RSSv2 支持。 若要启用 RSSv2 的 CPU 负载均衡功能,以及 启用非默认 VPorts(VMQs)的 RSSv1 动态均衡的NDIS_RECEIVE_FILTER_DYNAMIC_PROCESSOR_AFFINITY_CHANGE_SUPPORTED 标志,则需要此功能。

注意

上层协议假定默认 VPort 的主处理器可以移动 RSSv2 微型端口驱动程序。

如果微型端口适配器未播发 RSSv2 功能,即使请求这些 VPort 执行动态分布,所有已启用 VMQ 的 VPort 仍处于静态分布模式。 RSSv1 OID 用于配置 RSS 参数( OID_GEN_RECEIVE_SCALE_PARAMETERS)用于仍处于静态分布模式的这些 VPort。

微型端口驱动程序只需实现一个 RSS 控制机制 - RSSv1 或 RSSv2。 如果驱动程序播发 RSSv2 支持,则 NDIS 将 RSSv1 OID 转换为 RSSv2 OID(如有必要)来配置 per-VPort 分布。 微型端口驱动程序必须支持这两个新的 OID,并修改 RSSv1 OID_GEN_RECEIVE_SCALE_PARAMETERS OID 的行为,如下所示:

  • OID_GEN_RECEIVE_SCALE_PARAMETERS仅用于 RSSv2 中的查询请求,而不适用于设置 RSS 参数。
  • OID_GEN_RECEIVE_SCALE_PARAMETERS_V2是一个查询和一个 Set OID,用于配置缩放实体的参数,例如队列数、ITE 数、RSS 启用/禁用数和哈希密钥更新。
  • OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES是用于执行间接表项修改的方法 OID。

处理 RSSv2 OID

OID_GEN_RECEIVE_SCALE_PARAMETERS仅用于查询给定缩放实体的当前 RSS 参数。 在 RSSv1 中,此 OID 用于设置参数。 对于支持 RSSv2 的微型端口驱动程序,NDIS 会自动为驱动程序执行此角色转换,并发出以下两个 OID 来设置参数。

OID_GEN_RECEIVE_SCALE_PARAMETERS_V2是常规 OID,处理方式与 RSSv1 中处理 OID_GEN_RECEIVE_SCALE_PARAMETERS OID 相同。 NDIS 6.80 之前的 NDIS 轻型筛选器驱动程序(LFS)看不到此 OID。

但是,OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES是无法返回NDIS_STATUS_PENDING的同步 OID。 必须在发起 OID 的处理器上下文中执行并完成此 OID。 与OID_GEN_RECEIVE_SCALE_PARAMETERS_V2一样,NDIS 6.80 之前的 NDIS LDF 也看不到它。 不允许 NDIS 6.80 及更高版本中的 LDF 延迟此 OID 或移动到另一个处理器。 其有效负载包含一组简单的“移动 ITE”操作,其中每个操作都包含一个命令,用于将单个 ITE 移动到不同的目标 CPU。 数组的元素可以引用不同的缩放实体(VPorts)。

每种 NDIS 驱动程序、微型端口、筛选器和协议都有支持同步 OID 请求接口的入口点:

NDIS 驱动程序类型 同步 OID 处理程序(s) 用于发起同步 OID 的函数
微型端口 MiniportSynchronousOidRequest 空值
筛选器 NdisFSynchronousOidRequest
协议 空值 NdisSynchronousOidRequest

RSS 状态转换、ITE 更新和主/默认处理器

转向参数

在 RSSv2 中,不同的参数用于根据 RSS 状态(启用或禁用)将流量定向到正确的 CPU。 禁用 RSS 后,仅使用主处理器来定向流量。 启用 RSS 后,默认处理器和所有 ITE 都用于定向流量。 下表汇总了这些 转向参数 标记为“活动”或“非活动”:

转向参数 RSS 已禁用 已启用 RSS
主处理器 活动 非活动
默认处理器 未激活 活动
ITE[0..N] 未激活 活动

当转向参数处于 活动 状态时,它将定向流量。 从使参数 处于非活动状态的 RSS 状态转换的那一刻起,微型端口驱动程序必须跟踪参数的更改,直到反向转换再次激活它。 这意味着微型端口驱动程序需要跟踪默认处理器和间接表条目的所有更新,而 RSS 则为该缩放实体禁用。 启用 RSS 后,默认处理器和间接表的当前跟踪状态应生效。

例如,考虑软件 vRSS 已启用的情况。 在这种情况下,间接表已存在于上层协议中,并且由上层的软件分布代码主动使用。 如果在硬件 RSS 启用期间,在更新 以移动 间接表条目之前指向主处理器的所有条目都由硬件发出和执行,则主处理器可能会遇到短暂的堵塞。 如果微型端口驱动程序跟踪了默认处理器和 ITE 信息,则可以将流量定向到上层已预期到的位置。

请注意,虽然微型端口驱动程序必须跟踪对非活动转向参数的所有更新,但它们应延迟对这些参数的验证,直到 RSS 状态更改尝试使这些参数 处于活动状态。 例如,在禁用硬件 RSS 时进行软件传播时,上层协议可以使用任何处理器进行传播(包括适配器的 RSS 集外部)。 上层可确保在 RSS 状态转换时,所有 非活动 参数都对新的 RSS 状态有效。 但是,如果微型端口驱动程序发现任何跟踪 的非活动 转向参数无效,仍应验证参数,并失败 RSS 状态转换。

指导参数的初始状态和更新

下表描述了创建后缩放实体的初始状态(例如 VPort 创建后),以及如何更新参数:

参数 说明
主处理器
默认处理器
间接表
  • NumberOfIndirectionTableEntries 设置为 1
  • 唯一的条目是使用 VPort 创建期间指定的地缘 处理器初始化的。
  • 可以使用 OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES OID 进行更新

汇报 ITE 和主/默认处理器(使用OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES)从相应入口当前指向的处理器调用。 对于给定的 VPort,上层可确保在以下情况下不会发出任何OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES OID 来移动 ITE 或设置主/默认处理器:

  1. OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 正在进行时。
  2. 启动 VPort 删除序列后。 例如,上层仅在最后一个 OID 完成移动 ITE 之后才会发出设置筛选器 OID。

RSS 禁用

在 RSS 禁用期间,上层协议可以选择将所有 ITE 指向主处理器,然后发出 OID 以禁用 RSS,或者可能选择按原样保留间接表并禁用 RSS。 无论哪种情况,接收流量都应面向主处理器。

RSSv2 维护 RSSv1 的要求,该要求允许上层协议在不首先禁用 RSS 的情况下删除 VPort。 上层可以将 VPort 上的接收筛选器设置为零,从而确保没有接收流量流经 VPort,然后在不禁用 RSS 的情况下继续删除 VPort。 上层保证在 VPort 删除期间或之后不会发出任何OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES OID。

在 RSS 禁用和 VPort 删除期间,微型端口驱动程序应处理由于以前的队列移动而可能存在的任何挂起的内部操作。

RSSv2 固定

上层协议确保在执行管理功能或 ITE 移动之前不会违反重要的固定项。 例如:

  1. 在减少队列数之前,上层可确保间接表引用的处理器数不会超过 VPort 的新队列数。
  2. 上层不应请求间接表更新,该更新违反了 VPort 当前配置的队列数。 微型端口驱动程序应强制实施此操作并返回失败。
  3. 在更改 VMMQ-RESTRICTED 适配器的间接表条目数之前,上层可确保间接表的内容规范化为 2 的电源。

OID_GEN_RECEIVE_SCALE_PARAMETERS_V2

OID_GEN_RSS_标准版T_INDIRECTION_TABLE_ENTRIES

NDIS 6.80 中的同步 OID 请求接口