Linux network optimization

linux下监控网卡时可用的工具

ethtool

真正实现都是在网卡驱动中,所以这个工具较为重要。

1
2
3
4
5
-i 显示网卡驱动的信息,名称,版本等
-S 查看收发包统计情况
-g/-G 查看或修改RingBuffer的大小
-l/-L 查看或修改网卡队列数
-c/-C 查看或修改硬中断合并策略

ifconfig

包含了一些网卡统计信息

1
2
3
4
5
RX packets:接收的总包数
RX bytes:接收的字节数
RX errors:表示总的收包的错误数量
RX dropped:数据包已经进入了 Ring Buffer,但是由于其它原因导致的丢包
RX overruns:表示了 fifo 的 overruns,这是由于 Ring Buffer不足导致的丢包
1
2
/proc/net/dev 下有节点可以统计网卡工作数据
/sys/class/net/eth0/statistics 下也包含了网卡的统计信息

RingBuffer的监控与调优

当数据帧到达网卡,第一站即为RingBuffer,网卡通过DMA机制将数据帧送到RingBuffer中。因此第一个要监控和调优的就是网卡的RingBuffer.

ethtool -g eth0 可以查看Ringbuffer的大小。

在Linux的整个网络栈中,RingBuffer起到一个任务的收发中转站的角色。对于接收过程来讲,网卡负责往RingBuffer中写入收到的数据帧,ksoftirqd内核线程负责从中取走处理。只要ksoftirqd线程工作的足够快,RingBuffer这个中转站就不会出现问题。但是我们设想一下,假如某一时刻,瞬间来了特别多的包,而ksoftirqd处理不过来了,会发生什么?这时RingBuffer可能瞬间就被填满了,后面再来的包网卡直接就会丢弃,不做任何处理!

ethtool -S xx 或者 ifconfig xx都可以查看是否是因为这个原因丢包。

rx_fifo_errors如果不为0的话(在 ifconfig 中体现为 overruns 指标增长),就表示有包因为RingBuffer装不下而被丢弃了。那么怎么解决这个问题呢?很自然首先我们想到的是,加大RingBuffer这个“中转仓库”的大小。通过ethtool就可以修改。

1
# ethtool -G eth1 rx 4096 tx 4096

这样网卡会被分配更大一点的”中转站“,可以解决偶发的瞬时的丢包。不过这种方法有个小副作用,那就是排队的包过多会增加处理网络包的延时。所以另外一种解决思路更好,那就是让内核处理网络包的速度更快一些,而不是让网络包傻傻地在RingBuffer中排队。

硬中断监控与调优

在数据被接收到RingBuffer之后,下一个执行的就是硬中断的发起。

监控

硬中断的情况 cat /proc/interrupts

对于收包情况,硬中断的总次数 不等于 Linux收包总数。因为,第一网卡可以设置中断合并,多个网络帧只可以发起一次中断,第二NAPI运行时 会关闭硬中断,通过poll来收包。

多队列网卡调优

目前主流网卡基本都是支持多队列的,可以通过将不同队列分为不同的CPU来处理,加快处理网络包的速度。(最为有用的一个优化手段)

每一个队列都有一个中断号,可以独立向某个CPU核心发起硬中断请求,让CPU来poll包。通过将接收进来的包被放到不同的内存队列里,多个CPU就可以同时分别向不同的队列发起消费了。这个特性叫做RSS(Receive Side Scaling,接收端扩展)。通过ethtool工具可以查看网卡的队列情况。

1
ethtool -l eth0

如果你想提高内核收包的能力,直接简单加大队列数就可以了,这比加大RingBuffer更为有用。因为加大RingBuffer只是给个更大的空间让网络帧能继续排队,而加大队列数则能让包更早地被内核处理。ethtool修改队列数量方法如下:

1
ethtool -L eth0 combined 32

硬中断合并

对于CPU来讲也是一样,CPU要做一件新的事情之前,要加载该进程的地址空间,load进程代码,读取进程数据,各级别cache要慢慢热身。因此如果能适当降低中断的频率,多攒几个包一起发出中断,对提升CPU的工作效率是有帮助的。所以,网卡允许我们对硬中断进行合并。

1
2
3
4
5
6
7
ethtool -c eth0

Adaptive RX: 自适应中断合并,网卡驱动自己判断啥时候该合并啥时候不合并
rx-usecs:当过这么长时间过后,一个RX interrupt就会被产生
rx-frames:当累计接收到这么多个帧后,一个RX interrupt就会被产生

ethtool -C eth0 adaptive-rx on可以直接修改。

软中断监控与调优

在硬中断之后,再接下来的处理过程就是ksoftirqd内核线程中处理的软中断了。之前我们说过,软中断和它对应的硬中断是在同一个核心上处理的。因此,前面硬中断分散到多核上处理的时候,软中断的优化其实也就跟着做了,也会被多核处理。不过软中断也还有自己的可优化选项。

监控设置

1
2
cat /proc/softirqs 可以查看软中断信息
cat /proc/sys/net/core/netdev_budget 内核参数

这个的意思说的是,ksoftirqd一次最多处理300个包,处理够了就会把CPU主动让出来,以便Linux上其它的任务可以得到处理。那么假如说,我们现在就是想提高内核处理网络包的效率。那就可以让ksoftirqd进程多干一会儿网络包的接收,再让出CPU。至于怎么提高,直接修改不这个参数的值就好了。

1
2
sysctl -w net.core.netdev_budget=600
(static struct ctl_table xxx注册后 就可以通过 sysctl -w xxx 来赋值)

如果要保证重启仍然生效,需要将这个配置写到/etc/sysctl.conf

软中断GRO合并

GRO和硬中断合并的思想很类似,不过阶段不同。硬中断合并是在中断发起之前,而GRO已经到了软中断上下文中了。

如果应用中是大文件的传输,大部分包都是一段数据,不用GRO的话,会每次都将一个小包传送到协议栈(IP接收函数、TCP接收)函数中进行处理。开启GRO的话,Linux就会智能进行包的合并,之后将一个大包传给协议处理函数。这样CPU的效率也是就提高了。

1
2
3
4
ethtool -k eth0 | grep generic-receive-offload
generic-receive-offload: on
ethtool -K eth0 gro on
GRO说的仅仅只是包的接收阶段的优化方式,对于发送来说是GSO。