DPDK rte_eth_tx_burst描述符与mbuf释放规则及阈值配置咨询
DPDK ixgbe驱动TX资源未自动回收问题解答
问题1:rte_eth_tx_burst() 释放资源的语义
rte_eth_tx_burst() 是无阻塞的快速发送接口,仅做有限的已完成描述符回收检查:
- 仅当当前可用TX描述符数量低于
tx_free_thresh阈值时,才会触发一次已完成传输的描述符和对应rte_mbuf回收,不会忙等报文传输完成 - 如果回收后可用描述符仍不足以承载本次要发送的报文,函数会直接返回实际发送成功的报文数,不会阻塞等待硬件完成传输
你遇到的发送到1086个就返回0的情况,和单包发送模式、rs阈值配置直接相关:ixgbe驱动每满tx_rs_thresh个描述符才会给硬件打Report Status标记,只有带RS标记的描述符完成传输后,硬件才会更新完成状态,驱动才能识别回收。每次只发1个包的场景下,前992个描述符里每32个才打一个RS标记,等发到1086的时候,最后一批不足32个的描述符没有打RS标记,驱动识别不到这些描述符已经完成传输,就不会回收,自然就没有可用描述符了。
问题2:默认TX队列阈值是否适配单包循环发送场景
默认阈值(tx_free_thresh=32、tx_rs_thresh=32)不适配单次发1个包的循环发送场景:
默认阈值是为批量发送场景优化的,默认一次发送至少32个包的场景下,刚好每批都能打上RS标记,回收逻辑能正常触发。单包发送时会频繁出现不足tx_rs_thresh个描述符的情况,导致大量已完成的描述符无法被识别回收。
适配单包发送的阈值调整方案:可以把tx_rs_thresh设为1,每个描述符都打RS标记,保证已完成的描述符都能被驱动识别,代价是会稍微降低发送性能,对于1GbE网卡的带宽来说完全可以忽略。
问题3:符合DPDK规范的TX资源回收实现方式
推荐两种标准实现方案:
- 批量发送优先:尽量攒一批报文再调用
rte_eth_tx_burst(),单次发送数量不小于tx_rs_thresh,既保证回收逻辑正常触发,也能最大化发送性能 - 定期强制回收:如果必须单包发送,可以在每次
rte_eth_tx_burst()返回值小于要发送的报文数时,调用rte_eth_tx_descriptor_status()检查队首描述符的状态,确认完成后手动移动队列的回收指针释放mbuf,不要依赖rte_eth_tx_done_cleanup(),这个接口对向量驱动的兼容性确实不好,你遇到的关闭校验和卸载时返回-ENOTSUP是ixgbe向量驱动的已知限制,向量模式下没有实现通用的done cleanup回调。
问题4:TX描述符少于mbuf池大小、发送失败就重试的方案是否合理
这个方案不完全合理:
- 首先TX描述符数量本身就应该小于mbuf池大小,避免把整个池的mbuf都挂在TX队列上导致RX方向没有可用mbuf,这个配置是对的
- 但发送失败直接重试
rte_eth_tx_burst()没有意义:此时没有可用描述符,重试多少次都不会发送成功,反而会空耗CPU,必须在重试之前先触发一次TX资源回收,等有可用描述符之后再重试。
场景临时修复方案
把TX队列的tx_rs_thresh设为1即可快速解决单包发送无法回收的问题,配置示例:
struct rte_eth_txconf tx_conf = dev_info.default_txconf; tx_conf.tx_rs_thresh = 1; // 再调用rte_eth_tx_queue_setup完成队列配置
内容的提问来源于stack exchange,提问作者maxschlepzig
相关产品推荐
相关产品推荐

