首先来看看网卡收发包的处理流程:
收包:
网线上的packet首先被网卡获取,网卡会检查packet的CRC校验,保证完整性,然后将packet头去掉,得到frame。网卡会检查MAC包内的目的MAC地址,如果和本网卡的MAC地址不一样则丢弃(混杂模式除外)。
网卡将frame拷贝到网卡内部的FIFO缓冲区,触发硬件中断。(如有ring buffer的网卡,好像frame可以先存在ring buffer里再触发软件中断(下篇文章将详细解释Linux中frame的走向),ring buffer是网卡和驱动程序共享,是设备里的内存,但是对操作系统是可见的,因为看到linux内核源码里网卡驱动程序是使用kcalloc来分配的空间,所以ring buffer一般都有上限,另外这个ring buffer size,表示的应该是能存储的frame的个数,而不是字节大小。另外有些系统的 ethtool 命令 并不能改变ring parameters来设置ring buffer的大小,暂时不知道为什么,可能是驱动不支持。)
网卡驱动程序通过硬中断处理函数,构建sk_buff,把frame从网卡FIFO拷贝到内存skb中,接下来交给内核处理。(支持napi的网卡应该是直接放在ring buffer,不触发硬中断,直接使用软中断,拷贝ring buffer里的数据,直接输送给上层处理,每个网卡在一次软中断处理过程能处理weight个frame)
过程中,网卡芯片对frame进行了MAC过滤,以减小系统负荷。(除了混杂模式)
发包:
网卡驱动程序将IP包添加14字节的MAC头,构成frame(暂无CRC)。Frame(暂无CRC)中含有发送端和接收端的MAC地址,由于是驱动程序创建MAC头,所以可以随便输入地址,也可以进行主机伪装。
驱动程序将frame(暂无CRC)拷贝到网卡芯片内部的缓冲区,由网卡处理。
网卡芯片将未完全完成的frame(缺CRC)再次封装为可以发送的packet,也就是添加头部同步信息和CRC校验,然后丢到网线上,就完成一个IP报的发送了,所有接到网线上的网卡都可以看到该packet。
(原文:https://blog.csdn.net/u011857683/article/details/83758869)
遇到网络丢包问题,首先检查系统的性能,cpu负载、cpu使用率、内存使用率、网卡流量等。如果在系统负载低的情况下出现丢包,可按以下步骤排查:
1、检查网卡是否做了bond
如果做了负载均衡的bond方式,注意查看bind的两块网卡的mac地址一样,如果不一样就会出现丢包。
2、检查驱动和FW
#ethtool -i eth0
driver: ixgbe
version: 4.0.1-k-rh7.2
firmware-version: 0x800003df
bus-info: 0000:06:00.0
一般网卡使用的是系统自带的驱动,所以这里首先尝试升级驱动。去intel官网下载最新的驱动文件下载ixgbe驱动包,上传,解压,按照里面的readme进行安装;
3、ifconfig
drop表面是内存不够,导致包拷贝到内存时被丢弃。
overrun,表示cpu不能及时处理,导致ring buffer满,这时候可以考虑增加buffer或者修改网卡cpu的亲和性。
4、ethtool
根据之前的经验总结, 一般情况下,如果看到了不少 rx_no_buffer_count,则表明需要增加 ring buffer;而如果看到 tx_deferred_ok 表示传输被延迟,不算 errors; rx_missed_errors, rx_fw_discards 这个表示包满了,多出的全被 drop 掉了。
参考链接:
https://server.zzidc.com/fwqcjwt/2497.html
https://blog.csdn.net/u011857683/article/details/83758869
https://blog.csdn.net/anghlq/article/details/17302151
https://blog.csdn.net/laoxiao1987/article/details/41958231/
https://blog.51cto.com/tenderrain/2096108
https://segmentfault.com/a/1190000008836467?utm_source=tag-newest