Ord*_*per 1 windows kernel ndis driver
我有一个 NDIS 驱动程序,我将收到的数据包发送到用户服务,然后该服务标记那些正常的数据包(不是恶意的),然后我迭代可以很好接收的数据包,然后通过转换将它们一一发送它们中的每一个都返回到带有一个 NetBuffer 的正确 NetBufferList,然后我使用 NdisFIndicateReceiveNetBufferLists 指示它们。
这导致了通过 SMB(从共享复制文件)传输大文件时出现的问题,从而显着降低了传输速度。
作为一种解决方法,我现在将所有正常的 NBL 链接在一起(而不是逐个发送它们),然后通过 NdisFIndicateReceiveNetBufferLists 立即发送所有这些 NBL。
我的问题是,此更改会导致任何问题吗?逐一发送 X 数量的 NBL 与将它们链接在一起并一次发送所有之间有什么区别?(因为其中大多数可能与不同的流程/应用程序相关)
此外,与通过 FilterSendNetBufferLists 发送多数据包相比,在多数据包接收中将数据包链接在一起的好处要大得多,这是为什么呢?
NET_BUFFER 代表一个网络帧。(对 LSO/RSC 进行适当的挥手。)
NET_BUFFER_LIST 是相关 NET_BUFFER 的集合。同一 NET_BUFFER_LIST 上的每个 NET_BUFFER 都属于相同的“流量”(稍后会详细介绍),它们具有所有相同的元数据,并将对其执行所有相同的卸载。因此,我们使用 NET_BUFFER_LIST 对相关数据包进行分组并让它们共享元数据。
数据路径通常对多个 NET_BUFFER_LIST 进行批量操作。仅出于性能原因将整个批次分组在一起;批次中的多个 NBL 之间没有太多隐含关系。例外:大多数数据路径例程采用 Flags 参数,该参数可以保存对批处理中的所有 NBL 做出一些声明的标志,例如NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE.
总而言之,您确实可以安全地将多个 NET_BUFFER_LIST 分组为单个指示,这对于性能尤其重要。如果您愿意,您可以将不相关的 NBL 分组在一起。但是,如果您要合并多批 NBL,请确保清除任何 NDIS_XXX_FLAGS_SINGLE_XXX 样式标志。(当然,除非您知道这些标志的承诺仍然成立。例如,如果您要组合 2 批均具有 NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE 标志的 NBL,并且如果您验证每批中的第一个 NBL 具有相同的 EtherType ,那么保留 NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE 标志实际上是安全的。)
但请注意,您通常无法将多个 NET_BUFFER 组合到同一个 NET_BUFFER_LIST 中,除非您控制生成有效负载的应用程序并且您知道 NET_BUFFER 的有效负载属于同一流量。NDIS 层中流量的确切语义有点模糊,但您可以想象这意味着任何 NDIS 级硬件卸载都可以安全地将每个数据包视为相同的数据包。例如,IP 校验和卸载需要知道每个数据包具有相同的伪标头。如果所有数据包都属于同一个 TCP 或 UDP 套接字,则它们可以被视为同一流。
此外,与通过 FilterSendNetBufferLists 发送多数据包相比,在多数据包接收中将数据包链接在一起的好处要大得多,这是为什么呢?
接收是昂贵的路径,原因有两个。首先,操作系统必须花费 CPU 来分解来自网络的原始数据包流。网络可以从任何随机套接字向我们发送数据包,或者根本不匹配任何套接字的数据包,操作系统必须为任何可能性做好准备。其次,接收路径处理不受信任的数据,因此解析时必须谨慎。
相比之下,发送路径非常便宜:数据包只是落入微型端口驱动程序,后者设置 DMA,然后将它们发送到硬件。发送路径中没有人真正关心数据包中的实际内容(在 NDIS 看到数据包之前防火墙已经运行,因此您看不到该成本;如果微型端口正在执行任何卸载,则这是在硬件的内置处理器上支付的,因此它不会显示在您可以在任务管理器中看到的任何 CPU 上。)
因此,如果您获取一批 100 个数据包,并在接收路径上将其分解为 100 个数据包调用,则操作系统必须对一些昂贵的解析函数进行 100 次调用。同时,通过发送路径进行 100 个调用并不是很好,但这只是接收路径 CPU 成本的一小部分。
| 归档时间: |
|
| 查看次数: |
201 次 |
| 最近记录: |