Ring Buffer 相关监控及配置
收到数据包统计
ethtool -S eh0
NIC statistics:
rx_packets: 792819304215
tx_packets: 778772164692
rx_bytes: 172322607593396
tx_bytes: 201132602650411
rx_broadcast: 15118616
tx_broadcast: 2755615
rx_multicast: 0
tx_multicast: 10
RX 就是收到数据,TX 是发出数据。还会展示 NIC 每个队列收发消息情况。其中比较关键的是带有 drop 字样的统计和 fifo_errors 的统计 :
tx_dropped: 0
rx_queue_0_drops: 93
rx_queue_1_drops: 874
....
rx_fifo_errors: 2142
tx_fifo_errors: 0
看到发送队列和接收队列 drop 的数据包数量显示在这里。并且所有 queuedrops 加起来等于 rxfifoerrors。所以总体上能通过 rxfifo_errors 看到 Ring Buffer 上是否有丢包。如果有的话一方面是看是否需要调整一下每个队列数据的分配,或者是否要加大 Ring Buffer 的大小。
/proc/net/dev是另一个数据包相关统计,不过这个统计比较难看. 调整 Ring Buffer 队列数量
ethtool -l eth0
Channel parameters for eth0:
Pre-set maximums:
RX: 0
TX: 0
Other: 1
Combined: 8
Current hardware settings:
RX: 0
TX: 0
Other: 1
Combined: 8
看的是 Combined 这一栏是队列数量。Combined 按说明写的是多功能队列,猜想是能用作 RX 队列也能当做 TX 队列,但数量一共是 8 个?
如果不支持 mutiqueue 的话上面执行下来会是:
Channel parameters for eth0:
Cannot get device channel parameters
: Operation not supported
看到上面 Ring Buffer 数量有 maximums 和 current settings,所以能自己设置 Ring Buffer 数量,但最大不能超过 maximus 值:
sudo ethtool -L eth0 combined 8
如果支持对特定类型 RX 或 TX 设置队列数量的话可以执行:
sudo ethtool -L eth0 rx 8
需要注意的是,ethtool 的设置操作可能都要重启一下才能生效。
调整 Ring Buffer 队列大小 先查看当前 Ring Buffer 大小:
ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 512
RX Mini: 0
RX Jumbo: 0
TX: 512
看到 RX 和 TX 最大是 4096,当前值为 512。队列越大丢包的可能越小,但数据延迟会增加
设置 RX 队列大小:
ethtool -G eth0 rx 4096
调整 Ring Buffer 队列的权重 NIC 如果支持 mutiqueue 的话 NIC 会根据一个 Hash 函数对收到的数据包进行分发。能调整不同队列的权重,用于分配数据。
ethtool -x eth0
RX flow hash indirection table for eth0 with 8 RX ring(s):
0: 0 0 0 0 0 0 0 0
8: 0 0 0 0 0 0 0 0
16: 1 1 1 1 1 1 1 1
......
64: 4 4 4 4 4 4 4 4
72: 4 4 4 4 4 4 4 4
80: 5 5 5 5 5 5 5 5
......
120: 7 7 7 7 7 7 7 7
我的 NIC 一共有 8 个队列,一个有 128 个不同的 Hash 值,上面就是列出了每个 Hash 值对应的队列是什么。最左侧 0 8 16 是为了能让你快速的找到某个具体的 Hash 值。比如 Hash 值是 76 的话我们能立即找到 72 那一行:”72: 4 4 4 4 4 4 4 4”,从左到右第一个是 72 数第 5 个就是 76 这个 Hash 值对应的队列是 4 。
ethtool -X eth0 weight 6 2 8 5 10 7 1 5
设置 8 个队列的权重。加起来不能超过 128 。128 是 indirection table 大小,每个 NIC 可能不一样。
更改 Ring Buffer Hash Field 分配数据包的时候是按照数据包内的某个字段来进行的,这个字段能进行调整。
ethtool -n eth0 rx-flow-hash tcp4
TCP over IPV4 flows use these fields for computing Hash flow key:
IP SA
IP DA
L4 bytes 0 & 1 [TCP/UDP src port]
L4 bytes 2 & 3 [TCP/UDP dst port]
查看 tcp4 的 Hash 字段。
也可以设置 Hash 字段:
ethtool -N eth0 rx-flow-hash udp4 sdfn
sdfn 需要查看 ethtool 看其含义,还有很多别的配置值。
softirq 数统计
通过 /proc/softirqs 能看到每个 CPU 上 softirq 数量统计:
cat /proc/softirqs
CPU0 CPU1
HI: 1 0
TIMER: 1650579324 3521734270
NET_TX: 10282064 10655064
NET_RX: 3618725935 2446
BLOCK: 0 0
BLOCK_IOPOLL: 0 0
TASKLET: 47013 41496
SCHED: 1706483540 1003457088
HRTIMER: 1698047 11604871
RCU: 4218377992 3049934909
看到 NET_RX 就是收消息时候触发的 softirq,一般看这个统计是为了看看 softirq 在每个 CPU 上分布是否均匀,不均匀的话可能就需要做一些调整。比如上面看到 CPU0 和 CPU1 两个差距很大,原因是这个机器的 NIC 不支持 RSS,没有多个 Ring Buffer。开启 RPS 后就均匀多了。
IRQ 统计
/proc/interrupts 能看到每个 CPU 的 IRQ 统计。一般就是看看 NIC 有没有支持 multiqueue 以及 NAPI 的 IRQ 合并机制是否生效。看看 IRQ 是不是增长的很快。