投屏是指将某个终端的音视频或者其他内容通过有线或者无线的形式投射到其他终端上的一种协议。目前常见的投屏协议有DLNA
/Airplay
/Mirracast
/Chromecast
:
这两天质量的同学反馈说iperf
测试时结果很差,跟实际的千兆带宽差别很大。确认了半天,发现内核的各项参数都已经完全按照千兆的目标速率进行配置了,那为什么还是会出现TCP/UDP
带宽不足的问题? 记得当时优化参数时,自己摸底测试的TCP
结果挺好的,都达到了预期的900Mbps
以上,看起来最近有什么修改导致了这个测试结果差异。
偶然的一个机会查看内核配置时,发现最近有人打开了trace
功能,看起来很可能是这个修改导致了网络性能的下降了。拿早前未开启trace
功能的版本一对比,果真是trace
功能影响了TCP
的带宽。
在前面的一篇文章Linux网络优化之链路层优化中,我们已经看到,随着网卡速率超过1Gbps
,增加到10Gbps/100Gbps
时,CPU已经很难处理如此大量的数据包了。总结来说,主要有如下瓶颈:
- 内核协议栈处理在
L3(IP)/L4(TCP)
的数据处理上,消耗了比较多的时间,会导致网络延迟与传输受限 - 高速网卡会在短时间内产生大量中断,导致CPU频繁发生上下文切换,性能收到影响,进而影响网络吞吐
针对10Gbps/100Gbps
等高速网卡中存在的延迟与带宽受限问题,Intel在2010年提出了DPDK(Data Plane Development Kit)
基于用户空间的解决方案,并开源了实现方案, 目前DPDK
支持包括Intel/ARM等多个芯片架构的指令集; 同样是Intel的工程师在2018年提出了XDP(eXpress Data Path)
,与DPDK
不一样的是,XDP
基于现有内核socket
接口,与eBPF
相结合实现网卡与用户空间的数据传输,从而避免了内核协议栈的处理延迟。
TCP(Transmision Control Protocol
)即传输控制协议, 位于TCP/IP协议栈的第三层(L3), 是一种提供了可靠连接的字节流协议; TCP是目前使用最为广泛的协议之一, HTTP/MQTT/FTP等诸多应用层协议都是基于TCP实现的, 更多关于TCP协议相关的具体内容可以参考标准文档RFC793以及早前写的一篇聊一聊TCP协议.
在上一篇文章中讲到了高速以太网如1Gbps/10Gpbs中Linux网络L2(链路层)的一些优化方法, 包括了offload(卸荷)
以及scaling(缩放)
两种技术. 随着高速网络的不断普及, 1Gbps/10Gpbs以太网已经被广泛使用, 40Gbps/100Gbps也已经制定标准, TCP也在随着网络带宽的提升而不断进化.这篇文章我们就来看下如何在高速以太网下对TCP相关的参数的进行调优.
现在车内网络都开始内卷到1Gbps
了, 有同学给我反馈说以太网的吞吐量上不来, 跟理论带宽差距很大, 之前虽然优化了一波TCP
相关的参数, 但估计不能解决全部问题. 遂决定重新学习下网络优化, 从底层链路对开发平台上的网络进行改善. 趁着这个机会, 索性写一个系列文章-Linux网络优化, 用来总结下Linux网络优化的一些方法与技术, 目前计划从如下几篇文章展开(希望不要放飞了):
- Linux网络优化之数据链路层优化: 数据链路层
L2
的优化, 如何从收发两个方面优化网卡吞吐量,即本篇。 - Linux网络优化之TCP优化: 以TCP协议为例, 说明
L3
协议栈优化 - Linux网络优化之高速网络优化: 基于
DPDK/XDP
解决高速网络传输延迟问题 - Linux网络优化之AVB: 介绍以太网中用于音视频传输的低时延
TSN/AVB
协议
这篇文章主要讲第一个话题: Linux是如何在数据链路层L2
对网络数据的接收与发送进行优化的.
在优化网络性能时, 不可避免要对网络的带宽进行测试. 通常大家可能都会使用iperf
来执行网络链路的吞吐量测试, 但iperf
只能测试TCP/IP
协议层的速度, 这个带宽数据跟TCP/UDP
协议的参数配置以及应用层缓冲区的大小都有关系. 有时, 我们希望直接测试网卡本身的实际吞吐量, 看看网卡实际的发包能力. Linux内核提供了pktgen
工具用以产生数据包, 向网卡注入TCP/UDP
数据. 这里, 我们就来看下具体如何通过pktgen
来测试网卡性能.
最近碰到了一个很奇怪的问题, Android系统(Linux内核4.15)唤醒后, SoC(高通平台)跟TBox(Telematics Box)TCP的连接会偶发变慢, 需要等超过10s才能连接上. 发送ping包给TBox, 通过strace
看进程一直提示EAGAIN
的错误.从字面意义来说EAGAIN
(Resource temporarily unavailable
)是内核告知ping进程当前没有可用的数据包可以接收. 可是, 问题来了:
- 为什么ping一直会收到
EAGAIN
的错误? 内核在什么时候会返回该错误? - 为什么ping收不到数据包, TBox回包到底去了哪里?
幸亏好这个问题比较容易重现, 折腾了两天才最终把问题的的来龙去脉搞清楚. 接下来就来看看这个问题的现象以及背后发生的根因, 最后给出几个相应的对策.
最近抽空学习下Linux网络协议栈, 读源码时总会前一天梳理完, 等两天再来看却发现又忘记的差不多, 只能再过一遍, 没有对协议栈构建一个系统性的框架. 于是想着要把看过的代码逻辑整理下来, 算是对这段时间学习的总结, 也方便后面的查阅.
在之前的一篇有关网络协议的文章从NAPI说一说Linux内核数据的接收流程简单的讲到了Linux的数据接收流程, 但主要是集中在数据链路层与设备驱动之间的交互, 并没有涉及到IP网络层以及TCP传输层的逻辑.对于Linux系统来说, TCP数据的传输大致要经历如下几个步骤:
- 用户进程创建
socket
并创建相应数据的buffer, 通过send
函数发送给服务端 - 内核收到数据后, 将用户空间的buffer数据拷贝到内核协议栈
- 内核协议栈需要经过TCP层(L4)/IP层(L3)/数据链路层(L2)最后发送到网卡
- CPU与网卡的数据传输一般通过
DMA
进行, 完成后网卡发送中断告知CPU, 此时内核会释放之前分配的buffer
这篇文章, 我们着重来看下数据传输中内核部分的流程, 并梳理下Linux协议栈大致的结构与初始化步骤, 主要分为如下两个部分:
- Linux内核协议栈的初始化流程
- 数据是如何从TCP传输层发送到设备驱动的
前阵子在Android下调试一个只有IPv6地址的网络设备时,发现通过ping6
来测试网络连通时提示错误:
1 |
|
stackoverflow上有人说这是一个link-local address
本地链路地址,