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 是不是增长的很快。

来自