NDIS LWF全局状态重配置:如何临时断开数据路径?
NDIS过滤驱动全局状态重配置方案分析
核心约束
- 全局状态为所有过滤模块共享
- 配置变更由用户态IOCTL触发(操作频率极低)
- 数据路径严格禁止任何形式的锁
- 需临时断开RX/TX数据路径,完成重配置后恢复流量
原思路的风险点
直接在Restarting/Pausing状态过渡回调中使用信号量同步是高风险行为:
- NDIS状态过渡回调有严格的上下文与时序要求,强制同步等待极易打破NDIS内部状态机逻辑,大概率触发死锁(例如NDIS等待回调完成,而回调线程又等待IOCTL处理线程,形成循环等待)
- 即使处于APC_LEVEL及以下上下文,NDIS不保证所有过滤模块的状态过渡回调会在统一时间窗口执行,同步屏障的可靠性无法保障
可行方案优化与选型
方案a:全局入口无锁切换+批量模块重启(推荐)
基于你提出的思路优化,具体执行流程:
- 切断流量路径:IOCTL处理线程通过
InterlockedExchangePointer原子操作,将全局RX/TX回调指针切换为仅丢弃流量的轻量实现 - 等待活跃回调结束:通过全局原子计数器跟踪数据路径回调的活跃数(回调进入时原子+1,退出时原子-1),IOCTL线程循环等待计数器归0(用
KeDelayExecutionThread实现低延迟等待,避免忙等) - 安全重配置:此时数据路径无任何活跃执行逻辑,可直接修改全局状态
- 恢复流量:再次通过原子操作切换回正常RX/TX回调入口,随后遍历所有绑定的过滤模块实例,逐个调用
NdisFRestartFilter完成配置同步
该方案优势:
- 全程无锁,完全符合数据路径的约束要求
- 依赖NT内核原子原语保证操作原子性,状态一致性可靠
- 无需持久化运行时状态,业务中断时间极短
方案b:驱动重启(不推荐)
仅当全局状态逻辑极度复杂、无法通过模块重启完成同步时考虑:
- 需提前将关键运行时状态序列化到磁盘或注册表
- 卸载驱动后重新加载,从持久化存储恢复状态
- 缺点:业务中断时间长,状态持久化易引入一致性问题,用户体验差
额外注意事项
- 丢弃流量的回调需尽可能轻量化,仅执行包丢弃与必要统计,避免引入额外延迟
- 所有全局状态操作必须使用NT内核提供的无锁原子原语(如
Interlocked*系列),禁止自定义锁逻辑 - 批量重启模块时,需通过NDIS状态回调确认每个模块的重启操作完成,避免配置不一致
内容的提问来源于stack exchange,提问作者Emjayen
相关产品推荐
相关产品推荐

