使用 NetAdapterCx PLDR 恢复无响应的 NIC
NetAdapterCx 提供了一种通过平台级设备重置 (PLDR) 重置和恢复故障网络设备的有效方法。 在不重新启动整个 Windows 系统的情况下,PLDR 操作会拆除受影响的网络设备的堆栈,确保其硬件和驱动程序从空白状态重启。 NetAdapterCx 还允许客户端驱动程序在进行平台级重置之前从故障设备收集诊断。
检测到异常设备行为时,将触发 PLDR。 它可以通过以下任一方式触发:
操作系统 (OS) 。 例如,当传输中的数据包在驱动程序中卡住太长时间时,OS 端可能会触发 PLDR。
独立硬件供应商 (IHV) 客户端驱动程序。 例如,当驱动程序检测到其设备对其控制命令无响应时,客户端驱动程序可能会请求 NetAdapterCx 触发 PLDR。
为了提供用户友好的设备故障和恢复,我们建议 IHV 和原始设备制造商 (OEM) 为其网络设备支持 PLDR。 有关 PLDR 的详细信息,请参阅 重置和恢复设备。 NetAdapterCx 不会通过功能级设备重置来恢复网络设备。
注册可选的 诊断 集合回调
作为 NetAdapterCx 重置和恢复过程的一部分,客户端驱动程序可以在设备进行平台级重置之前从故障设备收集特定于设备的诊断。 IHV 和 Microsoft 可以在故障后分析中使用此数据来提高其产品质量。
注册NET_DEVICE_RESET_CAPABILITIES
客户端驱动程序需要在其EVT_WDF_DRIVER_DEVICE_ADD回调函数中初始化和注册NET_DEVICE_RESET_CAPABILITIES结构,以便收集特定于设备的诊断。
NET_DEVICE_RESET_CAPABILITIES 包含:
唯一 GUID。 IHV 指定此 GUID,稍后使用它从内存转储识别和检索重置诊断。 例如,.enumtag 命令可用于检索诊断。
EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS事件回调函数。 NetAdapterCx 调用此回调来收集诊断。 如果客户端驱动程序提供 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS 回调,NetAdapterCx 将使用 专用 线程在客户端驱动程序上调用它。
以下示例演示如何 将NET_DEVICE_RESET_CAPABILITIES 注册到 NetAdapterCx:
EVT_WDF_DRIVER_DEVICE_ADD EvtWdfDriverDeviceAdd;
EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS EvtDeviceCollectResetDiagnostics;
NTSTATUS EvtWdfDriverDeviceAdd(
WDFDRIVER Driver,
PWDFDEVICE_INIT DeviceInit
)
{
...
NET_DEVICE_RESET_CAPABILITIES resetCapabilities;
NET_DEVICE_RESET_CAPABILITIES_INIT(
&resetCapabilities,
DUMMY_GUID,
EvtDeviceCollectResetDiagnostics);
NetDeviceInitSetResetCapabilities(DeviceInit, &resetCapabilities);
...
}
有关如何初始化 NET_DEVICE_RESET_CAPABILITIES 结构的信息,请参阅 NET_DEVICE_RESET_CAPABILITIES_INIT。
若要了解如何将 NET_DEVICE_RESET_CAPABILITIES 结构播发到 NetAdapterCx,请参阅 NetDeviceInitSetResetCapabilities。
实现 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS
重置和恢复顺序可以随时发生。 因此,客户端驱动程序的 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS 回调实现必须考虑以下事项:
NetAdapterCx 将 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS 回调与 关机序列期间可能发生的其他回调同步。 客户端驱动程序可以假定 NetAdapterCx 不会调用数据包队列取消/停止、硬件释放和设备对象删除等回调,直到 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS 返回。
客户端驱动程序在处理诊断集合时必须格外小心,以避免死锁。 必须考虑到硬件可能已处于故障状态。
EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS尽快完成这一点至关重要,以便 PLDR 过程的其余部分可以继续进行。 EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS 必须可靠,并且必须在 3 秒内返回。
NetAdapterCx 始终在 PASSIVE_LEVEL 调用EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS。
若要将诊断提交到 NetAdapterCx,客户端驱动程序执行以下步骤:
从分页池或非分页池中预分配平面缓冲区,以收集重置诊断。 驱动程序应预先分配此缓冲区,以避免在设备重置期间出现内存不足错误。
在EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS回调中,通过调用 NetDeviceStoreResetDiagnostics API 将诊断作为平面数据缓冲区提交。 客户端驱动程序必须在 PASSIVE_LEVEL 调用 NetDeviceStoreResetDiagnostics API。
在 NetDeviceStoreResetDiagnostics 返回后释放数据缓冲区。
重要
NetDeviceStoreResetDiagnostics API 只能在EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS回调中调用。 在以前的 NetDeviceStoreResetDiagnostics 返回后,它也不能用于重新提交诊断数据。 违反上述任一情况都将导致 bug 检查。
重要
重置诊断的大小限制为 1 MB。
客户端驱动程序如何请求 PLDR
客户端驱动程序在检测到设备故障时使用 NetAdapterCx NetDeviceRequestReset API 触发 PLDR。 NetDeviceRequestReset 立即返回到客户端驱动程序。 NetAdapterCx 重置和恢复序列中所述的重置和恢复序列将触发,并且与 NetDeviceRequestReset 调用异步。
任何给定时间只能发生一个 PLDR 操作。 因此,当 PLDR 操作已启动时, 对 NetDeviceRequestReset 的后续调用不起作用。
如果已启动关机序列,则调用 NetDeviceRequestReset 也不起作用。
NetAdapterCx 重置和恢复序列
当 OS 或客户端驱动程序触发 PLDR 时,将发生以下顺序:
收集重置诊断:NetAdapterCx 调用客户端驱动程序的EVT_NET_DEVICE_COLLECT_RESET_DIAGNOSTICS回调,以从故障设备收集诊断。 例如,驱动程序可能会收集设备固件的快照。 此步骤是可选的,仅当客户端驱动程序已注册 NET_DEVICE_RESET_CAPABILITIES 结构时才会发生。 否则,NetAdapterCx 将跳过此步骤。
执行 PLDR:NetAdapterCx 执行平台级设备重置操作。 NetAdapterCx 电源回收硬件并拆除软件设备堆栈。
下图演示了 NetAdapterCx 重置和恢复顺序: