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

面向10 GbE FPGA流量的NDIS过滤驱动高效ACK生成方案问询

高效ACK发送优化方案

针对10 GbE线速UDP场景下接收路径直接发送ACK的瓶颈问题,可通过以下几种方式优化:

  • 延迟批量发送ACK
    不要针对每个接收到的UDP包立即发送ACK,而是将生成好的ACK NBL暂存在队列中,当队列达到指定阈值(如64/128个)或经过固定短定时(如1ms)后再批量提交发送。这能大幅减少NdisFSendNetBufferLists()的调用次数,降低内核态调用的固定开销。可利用NDIS定时器(NdisSetTimerObject)定期触发批量发送,或在每次接收处理完成时检查队列长度,达到阈值就提交。

  • 将ACK发送移至独立工作上下文
    接收路径(FilterReceiveNetBufferLists)属于高优先级处理路径,在此处执行发送操作会抢占接收处理的CPU时间,还可能因发送阻塞导致接收延迟。建议:

    1. 创建NDIS工作项(NdisAllocateWorkItem)或内核线程;
    2. 接收路径中仅完成ACK NBL的生成与入队操作,快速返回以继续处理接收流量;
    3. 由工作项/独立线程在PASSIVE_LEVEL上下文下调用NdisFSendNetBufferLists()发送ACK队列中的数据包。
      示例代码片段:
    // 接收路径仅执行入队
    NdisAppendNblToCountedQueue(&ackQ, pAckNbl);
    // 触发工作项(避免重复触发)
    if (!InterlockedCompareExchange(&g_IsAckWorkerActive, 1, 0)) {
        NdisQueueWorkItem(pFilter->AckWorkItem);
    }
    
    // 工作项处理函数
    VOID AckWorkerRoutine(IN PVOID Context) {
        PNDIS_FILTER Filter = Context;
        do {
            PNBL_COUNTED_QUEUE tempQ = {0};
            // 原子转移队列至临时变量
            NdisAcquireSpinLock(&Filter->AckQueueLock);
            NdisTransferNblCountedQueue(&tempQ, &Filter->ackQ);
            NdisReleaseSpinLock(&Filter->AckQueueLock);
    
            if (!NdisIsNblCountedQueueEmpty(&tempQ)) {
                NdisFSendNetBufferLists(Filter->FilterHandle,
                                        NdisGetNblChainFromNblCountedQueue(&tempQ),
                                        PortNumber,
                                        NDIS_SEND_FLAGS_DISPATCH_LEVEL);
                // 发送完成后需回收NBL至复用池
            }
        } while (!NdisIsNblCountedQueueEmpty(&Filter->ackQ));
        InterlockedExchange(&g_IsAckWorkerActive, 0);
    }
    
  • 预分配ACK专用内存与NBL池
    动态分配内存是高开销操作,尤其在高吞吐量场景下。提前预分配固定资源:

    1. 使用NdisAllocateNetBufferListPool创建ACK专用的NBL池,设置匹配批量发送阈值的池大小;
    2. 预分配非分页内存作为ACK数据包缓冲区,绑定到NBL的NetBuffer中;
    3. 生成ACK时直接从池中取出空闲NBL,填充包头后入队,发送完成后回收复用,避免重复分配释放。
  • 优化发送标志与NBL链式提交

    • 适配上下文设置sendFlags:在DISPATCH_LEVEL发送时设置NDIS_SEND_FLAGS_DISPATCH_LEVEL避免IRQL切换开销;若ACK无需本地环回,添加NDIS_SEND_FLAGS_SKIP_LOOPBACK_CHECK跳过环回检测,减少处理步骤;
    • 始终以链式方式提交多个NBL,一次调用NdisFSendNetBufferLists()提交整个NBL链,利用NDIS批量处理优化。
  • 避免接收路径IRQL阻塞
    FilterReceiveNetBufferLists通常运行在DISPATCH_LEVEL IRQL,此时执行发送若遇资源等待(如发送队列满),会导致接收路径长时间阻塞。将发送移至PASSIVE_LEVEL上下文(如工作项),即使发送等待也不会阻塞高优先级的接收处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 03:14:55