复制 NetBufferListInfo 数组而不是调用 NdisCopySendNetBufferListInfo?

Copying the NetBufferListInfo array instead of calling NdisCopySendNetBufferListInfo?

我有一个内核驱动程序,它在每个 recv/send NBL 中分离每个网络缓冲区,并为每个 NB 分配一个本地结构,其中包含数据包内容和一些其他内容,并将其发送到用户缓冲区,并且completes/returns原来的NBL。然后用户服务将正常的数据包发送回驱动程序,然后我最终 send/indicate 它们,通过为每个数据包创建一个 NBL,然后将它们链接在一起。

这会导致有关数据包的一些元数据丢失,这些元数据似乎位于 NetBufferListInfo 内部(特别是 WFP 元数据)。

我的问题是,我是否可以只将NetBufferListInfo 的内容保存在相应NB 的原始NBL 中,并将其保存到代表NB 的本地结构中,并在创建包含该NBL 的NBL 时重新复制它注意?

我想我应该使用 NdisAllocateCloneNetBufferList + NetBufferListInfo 并将指向克隆的 NBL 的指针作为新成员复制到我的本地结构,但问题是使用 NdisFreeCloneNetBufferList 释放这些缓冲区将变得非常复杂,因为我创建每个网络缓冲区的本地结构并将它们插入发送给用户服务的列表中,并且它们中的每一个都可以指向任意 NBL(并且它们中的许多可以指向相同的 NBL,因为我克隆了 NBL 一次NBL 中的多个 NB),并且当用户发送对我来说可以的那些时,我需要注意不要在我 indicate/send NBL 之后两次释放克隆的 NBL(我认为这会导致双重免费 BSOD ).因此我需要为每个克隆的 NBL 保留一个引用计数,并确保在它达到 0 时释放它,还有一些其他并发症..

那么对我来说最简单的解决方案是什么?能不能只在本地结构中保存对应NBL的NetBufferListInfo数组的内容,在创建最终的NB对应的NBL时重新复制?

您可以复制完整记录且您在语义上理解的 NetBufferListInfo 字段。例如,您可以复制 TcpIpChecksumNetBufferListInfo,因为它有完整的文档,并且从语义上讲,将它传播到另一个具有相同有效负载的 NBL 是有意义的。

但是有一些字段是 OS 私有的,其中至少有一个是 refcounted 指针。因此,如果您要复制该字段,然后 return 原始 NBL,指针将悬空。影响引用计数的唯一方法是调用 NdisCopySendNetBufferListInfoNdisCopyReceiveNetBufferListInfo,它们会为您处理。

TL;DR:你可以这样写代码:

new_nbl->NetBufferListInfo[TcpIpChecksumNetBufferListInfo] = old_nbl->NetBufferListInfo[TcpIpChecksumNetBufferListInfo];
new_nbl->NetBufferListInfo[NetBufferListHashValue] = old_nbl->NetBufferListInfo[NetBufferListHashValue];
. . .

但是你不能这样写代码:

RtlCopyMemory(
    new_nbl->NetBufferListInfo,
    old_nbl->NetBufferListInfo,
    sizeof(old_nbl->NetBufferListInfo));

因为并非所有插槽都是 blittable。