txqueuelen是内核qdisc层软件发送队列长度,控制协议栈到网卡dma前的最大排队包数;合理调优可减少软丢包(tx dropped),但无法消除由硬件环形缓冲区、驱动能力、中断响应等导致的物理丢包。

txqueuelen 是内核网络设备层的软件发送队列长度,它控制的是数据包从协议栈进入网卡驱动 DMA 区域前,在 qdisc 层排队的最大包数。它不能直接消除物理丢包,但合理调优可显著减少因驱动层队列溢出导致的软丢包(TX dropped),从而逼近物理链路的真实吞吐上限。
真正决定是否发生物理丢包的,是网卡硬件环形缓冲区(Ring Buffer)、驱动处理能力、中断响应及时性、TSO/GSO 卸载状态、以及对端流控(如 Pause Frame)等底层机制。txqueuelen 只是其中一环——调得过小会提前丢包;调得过大则可能掩盖真实瓶颈、增加延迟甚至触发驱动异常。
以下是围绕 txqueuelen 的精细调优路径,聚焦高带宽大吞吐场景(如 10G/25G/40G 网卡 + 高并发 TCP/RPC/UDP 流量):
明确 txqueuelen 的作用边界和常见误判
txqueuelen不等于硬件 TX Ring Buffer:
后者用ethtool -g eth0查看,是网卡芯片级缓存;前者是内核驱动层排队深度,单位是数据包个数(非字节数)。
若ethtool -S eth0 | grep tx_discard中tx_discard_vport或tx_busy持续增长,说明硬件或微码已开始丢包,此时调txqueuelen无效。-
ifconfig eth0或ip link show eth0显示的txqueuelen值,仅反映当前 qdisc 队列容量。
若TX errors或TX dropped在ifconfig输出中持续上升,需先区分来源:-
TX dropped:通常是txqueuelen溢出或 qdisc full(如pfifo_fast队列满); -
TX errors:多为驱动/硬件问题(如校验失败、DMA 错误); -
carrier/collisions:物理链路或交换机侧问题(全双工不匹配、光纤衰减等)。
-
针对不同网卡类型设定合理 txqueuelen 初始值
| 场景 | 推荐值 | 说明 |
|---|---|---|
| 千兆网卡(e1000e, r8169) | 2000–3000 | 默认 1000 易在突发流量下溢出;超过 5000 可能引发软中断延迟升高 |
| 万兆网卡(ixgbe, i40e) | 4000–6000 | 多数厂商驱动实测稳定上限;设为 10000 需同步验证 dmesg | grep "tx busy" 和重传率 |
| 25G/40G 网卡(mlx5, ice) | 5000–8000 | 配合开启 XPS(Transmit Packet Steering)与多 TX 队列绑定 CPU,避免单队列瓶颈 |
| veth pair(容器/VM 网络) | 5000–10000(两端一致) | veth 是纯内存设备,无硬件限制;必须 host 侧和 namespace 侧同时设置,否则瓶颈卡在弱侧 |
⚠️ 注意:盲目设为 10000+ 并不安全。部分驱动(如旧版
igb)在txqueuelen > 8192时会触发 ring buffer 映射异常,导致tx_dropped反而飙升。
结合硬件 Ring Buffer 与中断调度协同调优
仅改 txqueuelen 是“单点优化”,必须联动以下三者:
-
扩大硬件 TX Ring Buffer(需
ethtool -G支持):ethtool -G eth0 tx 4096 # 将 TX ring 设为 4096(需 ≤ Pre-set maximums)
若
ethtool -g eth0显示当前 TX 仅为 512,即使txqueuelen=10000,驱动仍无法将包全部送入硬件队列,多余包会在驱动入口被丢弃。 -
启用并绑定多 TX 队列(XPS):
# 查看 TX 队列数 ls /sys/class/net/eth0/queues/tx-* # 绑定 tx-0 → CPU0, tx-1 → CPU1(按 NUMA 节点分配更佳) echo f > /sys/class/net/eth0/queues/tx-0/xps_cpus # 十六进制掩码,f=CPU0-3
否则所有 TX 包都压在默认队列(tx-0),
txqueuelen再大也只服务一个队列,无法发挥多核并行能力。 -
确认 TSO/GSO 已启用(减少发包频率):
ethtool -k eth0 | grep tcp-segmentation-offload # 应显示 on;若 off,大量小包涌入 txqueuelen,极易填满
验证是否真正消除了 txqueuelen 相关丢包
不要只看 ifconfig 的 TX dropped,要分层验证:
-
驱动层是否还在丢?
ethtool -S eth0 | grep -E "(tx_discard|tx_busy|tx_timeout)" # tx_discard_vport > 0 → 微码丢包(需查交换机/对端) # tx_busy > 0 → 驱动提交失败(Ring Buffer 满或 DMA 故障) # tx_timeout > 0 → 硬件未及时完成发送(物理链路或驱动 bug)
-
qdisc 层是否溢出?
tc -s qdisc show dev eth0 # 关注 pfifo_fast 的 `drops` 字段;若持续增长,说明 txqueuelen 仍不足或 qdisc 类型不合适 # 可换用 `fq_codel`:tc qdisc replace dev eth0 root fq_codel
-
内核是否因 backlog 拥塞丢包?(尤其 veth 或高并发收包场景)
cat /proc/net/softnet_stat | awk '{print $2}' | tail -n +2 | sum # 第2列是 dropped sysctl net.core.netdev_max_backlog # 建议设为 2000–3000,但勿超 5000(防 softirq 延迟)
持久化配置与自动化验证
ip link set dev eth0 txqueuelen XXX 是临时命令,重启即失效。生产环境必须持久化:
-
NetworkManager 管理的网卡:用 dispatcher 脚本(推荐)
/etc/NetworkManager/dispatcher.d/99-txqueuelen:#!/bin/bash if [ "$1" = "eth0" ] && [ "$2" = "up" ]; then ip link set dev eth0 txqueuelen 6000 2>/dev/null ethtool -G eth0 tx 4096 2>/dev/null fichmod +x后生效。 systemd-networkd 或手动配置:在
.link文件中加TxQueueLength=(仅新版 systemd 支持)。上线前必做压力验证:
用iperf3 -c <server> -t 300 -P 32</server>或pktgen模拟真实流量,同时监控:watch -n1 'cat /proc/net/dev | grep eth0; ethtool -S eth0 | grep -E "(tx_discard|tx_busy)"'
确保TX dropped停止增长,且tx_discard_vport == 0。
不复杂但容易忽略。











