网络协议栈基础回顾:OSI模型与TCP/IP模型、数据包封装与解封装、MAC与PHY芯片角色分工
做网卡驱动这些年,我越来越觉得一个道理很实在:不懂协议栈,驱动写不深。你想想看,网卡驱动说白了就是协议栈和硬件之间的翻译官。你要是连两边在说什么都不清楚,这翻译肯定翻得稀里糊涂。
今天咱们就把协议栈这块儿捋一捋。我不打算照本宣科,而是结合我实际调驱动时踩过的坑,把OSI模型、TCP/IP模型、数据包怎么封装解封装,还有MAC和PHY到底谁干谁的活,一次性说清楚。
OSI模型:七层架构,理想很丰满
OSI模型是国际标准化组织搞出来的。七层,从下往上分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
说实话,我在实际工作中几乎没见过哪个产品是严格按照OSI七层来做的。但为什么还要学它?因为它的分层思想太经典了。每一层只管自己的事,层与层之间通过接口通信。这种解耦的设计,你写驱动时也会用到——比如把PHY驱动和MAC驱动分开写,互不干扰。
我个人习惯:调试网络问题时,脑子里先过一遍OSI模型。物理层不通查硬件,链路层不通查MAC地址和VLAN,网络层不通查IP和路由。一层一层往上排查,效率最高。
TCP/IP模型:四层架构,现实很骨感
TCP/IP模型是实际互联网用的。它把OSI的七层压缩成了四层:网络接口层、网络层、传输层、应用层。
你注意看,TCP/IP模型的网络接口层,其实对应了OSI的物理层和数据链路层。为什么合并?因为在实际的硬件实现中,这两层经常是集成在一起的。比如你买个以太网控制器芯片,它内部既有MAC也有PHY,你很难把它们完全分开来谈。
| OSI模型 | TCP/IP模型 | 典型协议/硬件 |
|---|---|---|
| 应用层、表示层、会话层 | 应用层 | HTTP、FTP、SSH |
| 传输层 | 传输层 | TCP、UDP |
| 网络层 | 网络层 | IP、ICMP、ARP |
| 数据链路层、物理层 | 网络接口层 | MAC、PHY、以太网帧 |
我在项目中遇到过一个问题:客户说网卡丢包严重。我查了半天,发现是PHY芯片的自动协商没配好,导致链路速率不稳定。你看,这就是网络接口层的问题,但应用层看到的表象就是丢包。所以搞驱动的人,必须能跨层看问题。
数据包封装与解封装:从应用到网线
数据包封装,说白了就是每一层给上层的数据加个头部。就像寄快递,你写个包裹,快递公司给你贴个面单,运输公司再给你贴个转运标签。
咱们以发送一个HTTP请求为例,看看数据包是怎么一层层包起来的:
- 应用层:浏览器生成HTTP请求数据,比如"GET /index.html"。
- 传输层:TCP协议给这段数据加上TCP头部,包含源端口、目的端口、序列号等。这叫TCP段。
- 网络层:IP协议给TCP段加上IP头部,包含源IP、目的IP。这叫IP数据报。
- 数据链路层:MAC层给IP数据报加上以太网帧头部,包含源MAC、目的MAC,尾部还有FCS校验。这叫以太网帧。
- 物理层:PHY芯片把以太网帧变成电信号或光信号,发到网线上。
解封装就是反过来。网卡收到信号后,PHY转成数字信号,MAC去掉帧头和帧尾,把IP数据报交给协议栈。协议栈一层层剥掉头部,最后把HTTP数据交给浏览器。
我曾经调试一个网络性能问题,发现TCP吞吐量上不去。用tcpdump抓包一看,发现每个TCP段都被分成了两个IP分片。原因是什么?MTU设置不对。这就是网络层封装时出的问题。所以抓包分析是驱动工程师的基本功,你得能看懂每一层的头部信息。
MAC与PHY芯片角色分工
很多初学者搞不清MAC和PHY到底有什么区别。我打个比方你就明白了:
- PHY(物理层):就像翻译官。它负责把数字信号变成模拟信号,或者反过来。它管的是电压、电流、编码方式、时钟同步这些物理层面的东西。
- MAC(媒体访问控制层):就像交通警察。它负责控制什么时候可以发数据,怎么避免冲突,怎么重发。它管的是帧的封装、地址过滤、流量控制这些逻辑层面的东西。
在实际的硬件中,MAC和PHY可能集成在一个芯片里,也可能是分开的。比如很多SoC内部集成了MAC,但PHY是外挂的。这时候你写驱动就要分别初始化MAC和PHY。
MAC和PHY之间的接口,最常见的是MII(媒体独立接口)。MII有几种变体:RMII、GMII、RGMII、SGMII等。不同的接口,引脚数不同,速率也不同。
| 接口类型 | 数据位宽 | 时钟频率 | 最大速率 |
|---|---|---|---|
| MII | 4位 | 25MHz | 100Mbps |
| RMII | 2位 | 50MHz | 100Mbps |
| GMII | 8位 | 125MHz | 1000Mbps |
| RGMII | 4位 | 125MHz(DDR) | 1000Mbps |
嗯,这里要注意:PHY芯片的寄存器访问是通过MDIO/MDC接口来做的。MDIO是一个两线制的管理接口,用来读写PHY的内部寄存器。你在驱动里要做的,就是通过MDIO去配置PHY的工作模式、速率、双工模式、自动协商等。
避坑指南:我曾经在移植一个网卡驱动时,发现PHY死活不工作。查了三天,最后发现是MDIO的时序不对。PHY芯片对MDIO的时序要求很严格,尤其是时钟频率不能太高。很多SoC的MDIO控制器默认时钟频率是2.5MHz,但有些PHY只支持到1MHz。所以移植驱动时,第一件事就是确认MDIO时钟频率是否在PHY的规格范围内。
核心逻辑:一张图看懂
下面这张SVG图,我把OSI模型、TCP/IP模型、数据包封装过程、MAC/PHY分工,全部串在了一起。你仔细看一遍,整个知识体系就清晰了。
这张图从左到右,展示了从OSI模型到TCP/IP模型,再到数据封装过程,最后到硬件实现的完整链路。你写驱动时,重点关注的是数据链路层和物理层,也就是MAC和PHY这一块。但你要理解上层协议在干什么,否则出了问题你都不知道该查哪一层。
好了,这一章的内容就到这里。协议栈这块儿是基础中的基础,后面咱们讲具体的驱动移植时,会反复用到这些概念。你先把这张图刻在脑子里,后面就好办了。
公众号:蓝海资料掘金营,微信deep3321