网卡丢包或性能问题排查思路


一般反馈网卡丢包或性能差,一般情况下并非是网卡本身造成的,尤其是当反馈大范围的网卡出现丢包的情况,这很大程度上与所安装的操作系统或者网络配置以及网络环境存在关联。

排查思路,按照顺序依次执行,若前一步可以解决,则后面的步骤可以忽略:

1、使用ifconfig或者netstat -i查看丢包的网口及类型,随后可以ethtool -i 网口查看网卡的驱动版本和FW版本;

也可以使用ethtool -S 查看网口收发包的统计情况;


2、升级驱动绑定中断

一般网卡使用的是系统自带的驱动,所以这里首先尝试升级驱动,并绑定网卡与cpu的中断,提高传输的效率;

以intel82599万兆网卡为例,去intel官网下载最新的驱动文件(或者浪潮官网)下载ixgbe驱动包,上传,解压,按照里面的readme进行安装;

安装完成之后重启,使用驱动包自带脚本set_irq_affinity进行绑定中断,绑定中断前注意需要停掉irqbalance 服务,然后再运行;(其他厂家的网卡,如mellanox、chelsio等万兆卡均存在相应的脚本或工具);

service irqbalance stop


3、检查网卡配置文件

bond、team的做法务必按照标准的配置方法进行配置,详见故障库其他页面;

假如客户使用的某种bond,客户存在丢包,可以尝试取消bond,单口测试;或者修改成mode1测试(mode1不需要交换机配合,便于排查网络环境造成的问题)

4、修改grub参数

rhel6系列的grub默认intel_iommu是开启的,如不使用虚拟化功能,建议将on改成off,否则很大程度上会降低万兆性能;

修改grub.conf和menu.lst文件中的intel_iommu=on amd_iommu=on中on改成off


5、关闭节能等

参考一揽子方案等,将CPU节能、pcie设备节能进行关闭;同时关闭虚拟化、超线程等选项;

6、优化io调度策略;

此策略一般是调整磁盘设备的IO调度算法,rhel6默认使用的是cfq,rhel7默认使用的deadline;在数据库及多磁盘设备的情况下deadline能够发挥机器的性能;

修改方法如下

临时生效

  • RHEL 5, RHEL 6, RHEL 7: via the /sys filesystem


永久生效

RHEL 4, RHEL 5, RHEL 6: add elevator=deadline to the end of the kernel line in /etc/grub.conf file:


RHEL 7: add `elevator=deadline` to `GRUB_CMDLINE_LINUX` in `/etc/default/grub`


  • and then rebuild the `/boot/grub2/grub.cfg` file to reflect the above changes:
    • On BIOS-based machines: ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
    • On UEFI-based machines: ~]# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

7、修改ring buffer

更改网卡的rx和tx ring buffer(通过ethtool –S ethx |grep rx_no_buffer_count 可以查看是否是因为buffer不足造成的丢包,如果这个数字不为零,则说明存在buffer满而丢包的情况),通过ethtool –g ethx可以查看该网卡的rx和tx ring buffer最大允许值和当前值,通过ethtool –G ethx rx xxx可以更改rx的ring buffer值,当丢包时可以适当增加,建议是在当前基础上按2倍方式逐渐增大,找到一个不丢包的临界值

如下图看到RX和TX最大都是4096,当前值均是256,通过命令全部更改为了512,若永久生效需要写入配置文件rc.local中,开机启动后执行



8、修改MTU与交换机匹配

MTU:Maximum transmission unit——the size of the largest packet that a network protocol can transmit

MTU是IP数据包每次能传输的最大数据单元,超过此大小将会进行分包,而若设置不能进行分包,则会导致丢包。

MSS就是IP数据包每次能传输的最大数据分段,这个值是MTU值减去IP数据包头大小20Byte和TCP数据段的包头20Byte。即Mss+40=MTU。

举例:如client机器的MTU是1500,Server机器的MTU是1440。之前一直认为MSS协商是client和server各自mss取最小值为这次tcp通讯的mss值。但是经过查资料才发现,client提供的mss是1460 (mss = mtu – 40 = 1500 – 40 = 1460)是表示从server到client的数据部分不能大于1460,整个IP包不能超过1500,而server提出的mss是1400(mss = mtu – 40 = 1440 – 40 = 1400)是表示从client到servr的数据部分不能大于1400,整个IP包不能超过1440。

需要关注在IP隧道技术,如LVS的LD到RS,IPSEC等使用IP隧道导致的MTU增大(注:IP隧道技术是使用IP传送IP包的技术,会在原来的IP包加上新的IP头等信息,导致IP包大小变大,可能超过了MTU的值),超过对应client或者server的最大MTU导致链接不通的情况,这个时候,一般会反向通过icmp包周知告诉发送端,比如:这个ICMP包告诉发送源端,下一跳的MTU是1450,你发送的包太大需要分片。但是你的包IP头里面设置了不可分片,所以我只能把包丢掉,通知你一下,重发小一点的包过来。

ifconfig命令修改

  1. ifconfig ${Interface} mtu ${SIZE} up
  2. ifconfig eth1 mtu 9000 up

这个是最通用的方法,对所有的linux 发行版本都有效。缺点就是重启后失效,需要在开机项中加载

修改配置文件

CentOS / RHEL / Fedora Linux下

  1. # vi /etc/sysconfig/network-scripts/ifcfg-eth0
  2. #增加如下内容
  3. MTU=”9000″
  4. #保存后重启网卡生效
  5. # service network restart
  6. #启用IPv6地址的,修改IPv6 mtu的参数为
  7. IPV6_MTU=”1280″

Debian / Ubuntu Linux下

  1. # vi /etc/network/interfaces
  2. #增加如下值
  3. mtu 9000
  4. #保存后,重启网络生效
  5. # /etc/init.d/networking restart

需要注意的是,在经过交换网络设备时,仅仅修改主机端的MTU值是不行的,还需要交换网络设备上开启jumbo frames功能。