在筛选器驱动程序中接收数据

筛选器驱动程序可以启动接收指示,也可以从基础驱动程序启动筛选器接收指示。 当微型端口驱动程序调用 NdisMIndicateReceiveNetBufferLists 函数时,NDIS 会将指定的 NET_BUFFER_LIST 结构提交到驱动程序堆栈中最低的过度筛选模块。

接收筛选器驱动程序启动的指示

下图演示了筛选器驱动程序启动的接收指示。

说明筛选器驱动程序启动的接收指示的示意图。

筛选器驱动程序调用 NdisFIndicateReceiveNetBufferLists 函数来指示收到的数据。 NdisFIndicateReceiveNetBufferLists 函数将堆栈上NET_BUFFER_LIST结构的指示列表传递给超载驱动程序。 筛选器驱动程序从它在初始化期间创建的池中分配结构。

如果筛选器驱动程序在 NdisFIndicateReceiveNetBufferListsReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_RESOURCES标志,则表示筛选器驱动程序必须立即重新获得NET_BUFFER_LIST结构的所有权。 在这种情况下,NDIS 不会调用筛选器驱动程序的 FilterReturnNetBufferLists 函数来返回 NET_BUFFER_LIST 结构。 筛选器驱动程序在 NdisFIndicateReceiveNetBufferLists 返回后立即重新获得所有权。

如果筛选器驱动程序未在 NdisFIndicateReceiveNetBufferListsReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_RESOURCES标志,则 NDIS 会将指示的NET_BUFFER_LIST结构返回到筛选器驱动程序的 FilterReturnNetBufferLists 函数。 在这种情况下,筛选器驱动程序将放弃所指示结构的所有权,直到 NDIS 将它们返回到 FilterReturnNetBufferLists

注意 筛选器驱动程序应跟踪它启动的接收指示,并确保它在接收操作完成时不调用 NdisFReturnNetBufferLists 函数。

筛选接收指示

下图演示了基础驱动程序启动的筛选接收指示。

说明基础驱动程序启动的筛选接收指示的示意图。

NDIS 调用筛选器驱动程序的 FilterReceiveNetBufferLists 函数来处理来自基础驱动程序的接收指示。 NDIS 在基础驱动程序调用接收指示函数后调用 FilterReceiveNetBufferLists , (例如 ,NdisMIndicateReceiveNetBufferLists) 来指示接收的网络数据或环回数据。

如果未设置 FilterReceiveNetBufferListsReceiveFlags 参数中的NDIS_RECEIVE_FLAGS_RESOURCES标志,筛选器驱动程序将保留NET_BUFFER_LIST结构的所有权,直到调用 NdisFReturnNetBufferLists 函数。

如果设置了 ReceiveFlags 参数中的NDIS_RECEIVE_FLAGS_RESOURCES标志,则筛选器驱动程序无法保留NET_BUFFER_LIST结构和关联的基础驱动程序分配的资源。 此标志可以指示基础驱动程序的接收资源不足。 FilterReceiveNetBufferLists 函数应尽快返回。

注意 如果设置了 NDIS_RECEIVE_FLAGS_RESOURCES 标志,筛选器驱动程序必须在链接列表中保留原始 NET_BUFFER_LIST 结构集。 例如,当设置此标志时,驱动程序可能会处理结构,并一次一个地在堆栈上指示它们,但在函数返回之前,它必须还原原始链接列表。

筛选器驱动程序可以先对收到的数据执行筛选操作,然后再将数据指示给过度覆盖的驱动程序。 对于提交到 FilterReceiveNetBufferLists 函数的每个缓冲区,筛选器驱动程序可以执行以下操作:

  • 通过调用 NdisFIndicateReceiveNetBufferLists,将其传递给下一个过度覆盖的驱动程序。 驱动程序可以修改缓冲区的内容。 NDIS 保证上下文空间的可用性, (看到 NET_BUFFER_LIST_CONTEXT结构) 。

    筛选器驱动程序可以更改 NDIS 传递到 FilterReceiveNetBufferLists 的状态,也可以直接将其传递给 NdisFIndicateReceiveNetBufferLists

    注意即使 NDIS 在 FilterReceiveNetBufferLists 的ReceiveFlags 参数中设置了 NDIS_RECEIVE_FLAGS_RESOURCES 标志,筛选器驱动程序也可以使用 NdisFIndicateReceiveNetBufferLists 传递缓冲区。 在这种情况下,筛选器驱动程序不得从 FilterReceiveNetBufferLists 返回,直到它重新获得缓冲区的所有权。

  • 放弃缓冲区。 如果 NDIS 清除 FilterReceiveNetBufferListsReceiveFlags 参数中的NDIS_RECEIVE_FLAGS_RESOURCES标志,请调用 NdisFReturnNetBufferLists 函数以放弃缓冲区。 如果 NDIS 在 FilterReceiveNetBufferListsReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_RESOURCES标志,则不执行任何操作,并从 FilterReceiveNetBufferLists 返回以放弃缓冲区。

  • 在本地数据结构中将缓冲区排队,供以后处理。 如果 NDIS 在 FilterReceiveNetBufferListsReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_RESOURCES标志,则筛选器驱动程序必须在从 FilterReceiveNetBufferLists 返回之前创建副本。

  • 复制缓冲区,并使用副本生成接收指示。 接收指示类似于筛选器驱动程序启动的接收指示。 在这种情况下,驱动程序必须将原始缓冲区返回到基础驱动程序。

NdisFIndicateReceiveNetBufferLists 函数将指示的NET_BUFFER_LIST结构列表传递到驱动程序堆栈上到过度覆盖的驱动程序。 接收操作的继续方式类似于筛选器驱动程序发起的接收操作。

如果过分驱动程序保留了缓冲区的所有权,NDIS 会为筛选器模块调用 FilterReturnNetBufferLists 函数。 在其 FilterReturnNetBufferLists 函数中,筛选器驱动程序将撤消它在接收指示路径上的缓冲区上执行的操作。

当最低层筛选器模块指示它已使用缓冲区完成时,NDIS 会将缓冲区返回到微型端口驱动程序。 如果 NDIS 清除 FilterReceiveNetBufferListsReceiveFlags 参数中的 NDIS_RECEIVE_FLAGS_RESOURCES 标志,则筛选器驱动程序会调用 NdisFReturnNetBufferLists 以返回缓冲区。 如果 NDIS 在 FilterReceiveNetBufferListsReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_RESOURCES标志,则从 FilterReceiveNetBufferLists 返回将返回缓冲区。