解决树莓派HW CSum问题
起因
之前把办公室的树莓派换成了2代的B型版,配置完之后起初一直都比较顺畅,但是奇葩的是每次我到外地出差的时候就会连不回树莓派。每次回来检查都发现设备确实是莫名其妙卡死了,由于办公室最近闹老鼠,一开始怀疑是老鼠扰动影响了树莓派稳定,结果采取防鼠措施确认老鼠不影响之后,仍然会出现整个设备间歇性无响应的情况。随后将系统换回了树莓派自家的系统Raspbian,问题依旧……本来还以为是设备硬件问题准备放弃的,结果偶然发现/var/log目录下的message和kern.log中竟然充斥着大量如下的错误提示:
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295601] eth0: hw csum failure
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295722] [<7f22f994>] (nf_conntrack_in [nf_conntrack]) from [<7f2732dc>] (ipv4_conntrack_in+0x28/0x2c [nf_conntrack_ipv4])
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295755] [<7f2732dc>] (ipv4_conntrack_in [nf_conntrack_ipv4]) from [<806cfe38>] (nf_hook_slow+0x4c/0xd0)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295778] [<806cfe38>] (nf_hook_slow) from [<806d8750>] (ip_rcv+0x460/0x514)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295799] [<806d8750>] (ip_rcv) from [<8068b784>] (__netif_receive_skb_core+0x2dc/0xc84)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295822] [<8068b784>] (__netif_receive_skb_core) from [<8068e380>] (__netif_receive_skb+0x20/0x7c)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295843] [<8068e380>] (__netif_receive_skb) from [<8068e474>] (process_backlog+0x98/0x148)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295863] [<8068e474>] (process_backlog) from [<8069278c>] (net_rx_action+0x2e8/0x45c)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295882] [<8069278c>] (net_rx_action) from [<80101694>] (__do_softirq+0x18c/0x3d8)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295902] [<80101694>] (__do_softirq) from [<80123870>] (irq_exit+0x108/0x164)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295923] [<80123870>] (irq_exit) from [<80175984>] (__handle_domain_irq+0x70/0xc4)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295944] [<80175984>] (__handle_domain_irq) from [<80101504>] (bcm2836_arm_irqchip_handle_irq+0xa8/0xac)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295962] [<80101504>] (bcm2836_arm_irqchip_handle_irq) from [<807a3abc>] (__irq_svc+0x5c/0x7c)
Nov 5 06:50:54 dtgs-pi kernel: [1179419.295971] Exception stack(0x80c01ef0 to 0x80c01f38)
在 raspberrypi 官方的一个issues中找到类似的 hw csum failure 问题,这是由于有线网卡接口部分的 HW CSum 错误导致内核在不断地在日志打 Stack trace ,看来设备停止响应有很大概率跟这个问题相关。
解决方案
就目前的情况分析,这应该是硬件驱动程序的问题,要彻底解决只能依靠官方的补丁。我当前升级到最新的 kernel (4.14.71)和pakeage问题依旧。临时的解决方案只能先通过ethtool关闭rx的offload功能了:
单次关闭
安装好ethtool之后,使用命令关闭rx和tx的offload功能:
ethtool -K eth0 rx off tx off
永久关闭
编辑/etc/network/interfaces.d/eth0 ,添加下列内容:(其中eth0为网络接口名称)
allow-hotplug eth0
iface eth0 inet dhcp
offload-rx off
offload-tx off
关于HW CSum
“HW CSum”全称为“Hardware Checksum Offloading”,即将报文的ip,tcp, udp校验和的计算交给网卡芯片,从而达到降低 CPU 占用的目的。
顺便再补充一下TSO (TCP Segmentation Offload) ,这是利用网卡芯片替代CPU对大数据包进行分片,降低CPU负载的技术。如果数据包的类型只能是TCP,则被称之为TSO,硬件功能需要网卡提供支持。TSO 是使得网络协议栈能够将大块 buffer 推送至网卡,然后网卡执行分片工作,这样减轻了CPU的负荷,其本质实际是延缓分片。这种技术在Linux中被叫做GSO(Generic Segmentation Offload),它不需要硬件的支持分片就可使用。对于支持TSO功能的硬件,则先经过GSO功能处理,然后使用网卡的硬件分片能力进行分片。
关于ethtool
ethtool是一个强大的工具,主要用于获取以太网卡的配置信息,或者修改这些配置,相关的参数有点复杂,功能特别多。
这里用到的有:
-k 显示网卡Offload参数的状态:on 或 off,包括rx-checksumming、tx-checksumming等。
-K 修改网卡Offload参数的状态。(功能和 --offload 一致,可以调整的参数有[rx on|off] [tx on|off] [sg on|off] [tso on|off])
凡是参数后面有“[fixed]”标示的参数,说明不可以通过ethtool进行调整,这大多是因为驱动层面没有提供可以修改的接口导致的。要查看当前网卡可以修改的 offload 相关全部参数可以用命令:
ethtool -k eth0 |grep -v fixed