国产化硬件设备性能追踪

问题:目前设备进行1g吞吐测试时,时不时出现tx流量最大700M

首先查看dev 收发包:

sar -n DEV   同时 cat /proc/net/dev

 

 

 

 

 

 可以看出实际上没有出现丢包(eth7 eth8)

接收数据包的流程

  1. 网卡收到数据包。
  2. 将数据包从网卡硬件缓存转移到服务器内存中。
  3. 通知内核处理。
  4. 经过TCP/IP协议逐层处理。
  5. 应用程序通过read()socket buffer读取数据。

将网卡收到的数据包转移到主机内存(NIC与驱动交互)

  NIC在接收到数据包之后,首先需要将数据同步到内核中,这中间的桥梁是rx ring buffer。它是由NIC和驱动程序共享的一片区域,事实上,rx ring buffer存储的并不是实际的packet数据,而是一个描述符,这个描述符指向了它真正的存储地址,具体流程如下:

  1. 驱动在内存中分配一片缓冲区用来接收数据包,叫做sk_buffer
  2. 将上述缓冲区的地址和大小(即接收描述符),加入到rx ring buffer。描述符中的缓冲区地址是DMA使用的物理地址;
  3. 驱动通知网卡有一个新的描述符;
  4. 网卡从rx ring buffer中取出描述符,从而获知缓冲区的地址和大小;
  5. 网卡收到新的数据包;
  6. 网卡将新数据包通过DMA直接写到sk_buffer中。

 

  在Linux的整个网络栈中,Ring-Buffer起到一个任务的收发中转站的角色。对于接收过程来讲,网卡负责往Ring-Buffer中写入收到的数据帧,ksoftirqd内核线程(软中断)负责从中取走处理。只要软中断/ksoftirqd线程工作的足够快,RingBuffer这个中转站就不会出现问题

  当驱动处理速度跟不上网卡收包速度时,驱动来不及分配缓冲区,NIC接收到的数据包无法及时写到sk_buffer,就会产生堆积,当NIC内部缓冲区写满后,就会丢弃部分数据,引起丢包。这部分丢包为rx_fifo_errors,在/proc/net/dev中体现为fifo字段增长,在ifconfig中体现为overruns指标增长。

ethtool -S eth0  也能看到

通知系统内核处理(驱动与Linux内核交互)

 

这个时候,数据包已经被转移到了sk_buffer中。前文提到,这是驱动程序在内存中分配的一片缓冲区,并且是通过DMA写入的,这种方式不依赖CPU直接将数据写到了内存中,意味着对内核来说,其实并不知道已经有新数据到了内存中。那么如何让内核知道有新数据进来了呢?答案就是中断,通过中断告诉内核有新数据进来了,并需要进行后续处理。

 

提到中断,就涉及到硬中断和软中断,首先需要简单了解一下它们的区别:

 

  • 硬中断: 由硬件自己生成,具有随机性,硬中断被CPU接收后,触发执行中断处理程序。中断处理程序只会处理关键性的、短时间内可以处理完的工作,剩余耗时较长工作,会放到中断之后,由软中断来完成。硬中断也被称为上半部分。
  • 软中断: 由硬中断对应的中断处理程序生成,往往是预先在代码里实现好的,不具有随机性。(除此之外,也有应用程序触发的软中断,与本文讨论的网卡收包无关。)也被称为下半部分。

 

当NIC把数据包通过DMA复制到内核缓冲区sk_buffer后,NIC立即发起一个硬件中断。CPU接收后,首先进入上半部分,网卡中断对应的中断处理程序是网卡驱动程序的一部分,之后由它发起软中断,进入下半部分,开始消费sk_buffer中的数据,交给内核协议栈处理。

根据:这篇文章介绍以及内核代码可知:

  内核会为每个CPU Core都实例化一个softnet_data对象,这个对象中的input_pkt_queue用于管理接收的数据包。假如所有的中断都由一个CPU Core来处理的话,那么所有数据包只能经由这个CPU的input_pkt_queue,如果接收的数据包数量非常大,超过中断处理速度,那么input_pkt_queue中的数据包就会堆积,直至超过netdev_max_backlog,引起丢包。这部分丢包可以在cat /proc/net/softnet_stat的输出结果中进行确认:

 

查看:cat /proc/net/softnet_stat  结果可知 并没有出现丢包

ifconfig 等也没有看出丢包,所以认为不是丢包引起,

根据收发包流程:网卡收包  到 拷贝到内存 然后递交协议栈处理  再就是应用层处理,查看app log也没出现异常;

所以认为是协议栈问题::::

TCP/IP协议栈逐层处理,最终交给用户空间读取

数据包进到IP层之后,经过IP层、TCP层处理(校验、解析上层协议,发送给上层协议),放入socket membuffer,在应用程序执行read() 系统调用时,就能从socket buffer中将新数据从内核区拷贝到用户区,完成读取。

所以只能抓包查看了!!!!2021-01-08

抓包结果:2021-01-11: tcp重传导致

 

问题:目前网卡开启RSS 多队列, 那么是不是需要开启RFS/RPS???

 

PS:看到了老外的一篇分析 其中几个图片不错;copy过来

 

 

 

 

posted @ 2021-01-08 12:19  codestacklinuxer  阅读(346)  评论(0编辑  收藏  举报