You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NDIS 6网络过滤驱动:X540网卡NET_BUFFER一次性读取问题及差异原因

问题解答

原因分析

X540网卡的Miniport驱动采用了Scatter-Gather(分散-聚集)缓冲区策略,这是万兆网卡常见的性能优化手段:

  • 为提升大流量下的接收效率,驱动会将超过预设阈值(比如2048字节)的数据包拆分成多个小MDL片段存储,而非用单个MDL承载完整数据包。
  • I350作为千兆网卡,其驱动默认使用单MDL承载数据包的策略,所以MmGetMdlByteCount返回值与MTU一致。

此外,NDIS的**接收合并(Receive Coalescing)或RSS(接收端缩放)**配置可能间接影响这一行为,但核心差异来自网卡驱动的缓冲区分配逻辑。

解决方案

以下是几种可行的优化方案,按兼容性和推荐度排序:

1. 使用NDIS标准API批量拷贝数据

直接调用NdisCopyFromNetBufferToBuffer API,它会自动遍历NET_BUFFER的所有MDL片段,将完整数据包一次性拷贝到你指定的缓冲区中,无需手动处理MDL遍历逻辑。示例代码片段:

ULONG totalBytes = NET_BUFFER_DATA_LENGTH(pNetBuffer);
PUCHAR pBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, totalBytes, YOUR_POOL_TAG);
if (pBuffer != NULL) {
    NdisCopyFromNetBufferToBuffer(pNetBuffer, 0, totalBytes, pBuffer, NULL);
    // 处理拷贝后的pBuffer数据
    ExFreePoolWithTag(pBuffer, YOUR_POOL_TAG);
}

这个API内部做了优化,性能优于手动循环拷贝MDL片段。

2. 手动遍历所有MDL片段(兼容所有场景)

如果需要更精细的内存控制,可以手动遍历NET_BUFFER的MDL链:

PMDL pMdl = NET_BUFFER_FIRST_MDL(pNetBuffer);
ULONG offset = NET_BUFFER_DATA_OFFSET(pNetBuffer);
ULONG remainingBytes = NET_BUFFER_DATA_LENGTH(pNetBuffer);

while (pMdl != NULL && remainingBytes > 0) {
    PUCHAR pMdlData = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
    if (pMdlData != NULL) {
        ULONG copyBytes = min(MmGetMdlByteCount(pMdl) - offset, remainingBytes);
        // 拷贝pMdlData+offset处的copyBytes字节到目标缓冲区
        remainingBytes -= copyBytes;
        offset = 0; // 后续MDL的偏移量重置为0
    }
    pMdl = MDL_NEXT(pMdl);
}

这种方式兼容性最好,不受网卡驱动策略影响。

3. 禁用网卡的Scatter-Gather特性

部分Intel网卡驱动的高级配置界面中提供了“Scatter/Gather”开关,禁用后驱动会尝试用单个MDL承载完整数据包。但注意:

  • 该操作会降低万兆网卡的接收性能,因为Scatter-Gather是为大流量优化的特性;
  • 不同版本的Intel驱动可能位置不同,需参考网卡驱动文档。

4. 检查过滤驱动初始化配置

确保你的过滤驱动在NDIS_FILTER_ATTRIBUTES中正确设置了相关标志,比如:

NDIS_FILTER_ATTRIBUTES FilterAttributes = {0};
FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
FilterAttributes.Header.Size = NDIS_SIZEOF_FILTER_ATTRIBUTES_REVISION_1;
FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
// 确保启用对所有NET_BUFFER类型的支持
FilterAttributes.Flags = NDIS_FILTER_ATTRIBUTE_SUPPORTS_NDIS_6_0;

错误的标志设置可能导致驱动无法正确处理多片段的NET_BUFFER。

内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:20:28