引言:以太网在嵌入式系统中的重要性
以太网作为现代局域网的核心技术,凭借高可靠性、易扩展性和标准化优势,已成为工业控制、智能设备等领域的关键通信方案。本文将基于FPGA平台,深入解析以太网协议栈,并实现UDP数据回环的硬件设计。
一、网络协议栈核心模型
| 层级 | 核心功能 | 关键协议/组件 |
|---|---|---|
| 应用层 | 提供用户接口及网络服务 | HTTP/DNS/DHCP |
| 传输层 | 端到端数据传输与流量控制(无连接、低延迟) | UDP |
| 网络层 | 路由寻址与跨网络传输 | IP/ICMP |
| 数据链路层 | 帧封装、介质访问控制 | MAC/ARP |
| 物理层 | 比特流传输与电气特性定义 | PHY芯片/RJ45接口 |
注:相较于OSI七层模型,UDP合并了会话层、表示层与应用层
二、以太网协议分层定位
三、核心协议解析与实现要点
1. 物理层(PHY)关键设计
-
接口标准选择:
-
MII:16线制,独立收发时钟(25MHz@100Mbps)
-
RMII:7线制,共用50MHz参考时钟(成本更低)
-
信号说明
信号名称 功能描述 MII接口特性 RMII接口特性 TX_CLK 数据发送时钟线 10Mbit/s时2.5MHz,100Mbit/s时25MHz,由PHY提供 无该线,时钟由外部50MHz参考时钟提供 RX_CLK 数据接收时钟线 10Mbit/s时2.5MHz,100Mbit/s时25MHz,由PHY提供 无该线,时钟由外部50MHz参考时钟提供 TX_EN 数据发送使能信号,数据发送期间保持有效 有效时TXD数据有效 有效时TXD数据有效 TXD[3:0] / TXD[1:0] 数据发送数据线 4位数据线 2位数据线 CRS 载波侦听信号,由PHY驱动,介质非空闲时有效 有效(半双工模式) 无独立CRS线,CRS与RX_DV合并为CRS_DV COL 冲突检测信号,由PHY驱动,检测冲突时有效 有效(半双工模式) 无该线 RXD[3:0] / RXD[1:0] 数据接收数据线 4位数据线,由PHY驱动 2位数据线,由PHY驱动 RX_DV 接收数据有效信号,PHY驱动 有效时RXD数据有效 与CRS合并为CRS_DV信号 RX_ER 接收错误信号,由PHY驱动 有效时报告接收错误 有效时报告接收错误 REF_CLK 参考时钟 一般由PHY提供25MHz时钟 由外部提供50MHz参考时钟,供MAC和PHY使用 备注:
- MII接口数据线宽度为4位,RMII接口为2位,导致两者在时钟设计和数据传输方式上存在显著差异。
- MII接口依赖PHY提供TX_CLK和RX_CLK时钟信号,而RMII接口取消了TX_CLK和RX_CLK,改为统一使用外部50MHz参考时钟。
- RMII接口将CRS和RX_DV信号合并为CRS_DV,简化了信号线数量,适合资源受限的应用场景。
-
-
编码方案:
-
曼彻斯特编码(10Mbps):50%效率,自带时钟同步
-
4B/5B编码(100Mbps):80%效率,需外同步时钟
-
2. MAC层数据帧结构
| 前导码(7B) | SFD(1B) | 目的MAC(6B) | 源MAC(6B) | 类型(2B) | 数据(46-1500B) | 填充域 | FCS(4B) |
| 字段名称 | 长度(Byte) | 功能描述 | 详细说明 |
|---|---|---|---|
| 前导字段 | 7 | 时钟同步 | 连续7个字节0x55的方波信号,用于收发节点时钟同步,MAC接收后自动过滤 |
| 帧起始定界符(SFD) | 1 | 标识数据段开始 | 1字节0xD5,用于区分前导字段和数据段,MAC接收后自动过滤 |
| 目标地址(DA) | 6 | 目标MAC地址 | 48位物理地址,标识数据包接收端,支持广播和多播 |
| 源地址(SA) | 6 | 源MAC地址 | 48位物理地址,标识数据包发送端,通常由网卡出厂设置或软件配置 |
| QTag前缀 | 4 (可选) | VLAN标识及优先级 | IEEE 802.3扩展字段,位于SA和数据包类型之间,前2字节固定0x8100,后2字节包含用户优先级、CFI和VLAN ID |
| 数据包类型 | 2 | 类型或长度字段 | 大于0x0600表示协议类型(如IP、ARP、SNMP),否则表示数据段长度 |
| 数据段 | 46~1500 | 上层数据 | MAC包核心内容,长度可变,承载上层协议数据 |
| 填充域 | 可变 | 保证最小帧长 | 当数据段长度<46字节时自动填充无效数据,确保整个帧长度≥64字节 |
| 校验和域(CRC) | 4 | 差错检测 | 保存CRC校验码,用于检测数据包传输错误 |
-
核心规则:
- 最小帧长64字节(含FCS)
- 数据不足46字节时自动填充
- FCS校验采用CRC32算法
3. IPv4协议关键字段
|版本+首部长度(1B) | 服务类型(1B) | 总长度(2B) | 标识(2B) | 标记+分段偏移(2B) | 生存时间(1B) | 协议(1B) | 首部校验和(2B) | 源地址(4B) | 目的地址(4B) | 选项(0~40B,可选) | 数据(可变)|
| 字段名称 | 长度(bit) | 长度(Byte) | 功能描述 | 详细说明 |
|---|---|---|---|---|
| 版本 | 4 | 0.5 | 指明IP协议版本 | IPv4版本号,固定为4,指示数据报格式 |
| 首部长度 | 4 | 0.5 | IP首部长度 | 以32位字(4字节)为单位,最小值5(20字节),最大15(60字节) |
| 服务类型 | 8 | 1 | 服务质量指示 | 包含优先级(3位)、服务类型(4位)、1位未定义 |
| 总长度 | 16 | 2 | 整个IP数据报长度 | 包括首部和数据,最大65535字节 |
| 标识 | 16 | 2 | 数据报标识符 | 用于分段时标识数据报,所有分段共享此值 |
| 标记 | 3 | 0.375 | 分段控制标志 | MF(更多分段)、DF(不分段)、保留位(0) |
| 分段偏移 | 13 | 1.625 | 分段相对偏移 | 指示该分段在原始数据报中的位置 |
| 生存时间(TTL) | 8 | 1 | 限制数据报寿命 | 每经过一个路由器减1,减到0时丢弃 |
| 协议 | 8 | 1 | 上层协议标识 | 指示数据报承载的上层协议类型,如TCP、UDP等 |
| 首部校验和 | 16 | 2 | IP首部完整性校验 | 对IP首部进行校验,确保传输过程中无误 |
| 源地址 | 32 | 4 | 源主机IP地址 | 数据报发送方IP地址,传输过程中不变 |
| 目的地址 | 32 | 4 | 目的主机IP地址 | 数据报接收方IP地址,传输过程中不变 |
4. IP首部校验和(Checksum)计算方法
-
计算步骤
- 校验和字段强制置0,即将IP首部中的校验和字段(2字节)清零。
- 将IP首部(通常20字节)按2字节(16位)为单位拆分,逐个相加。
- 若相加结果超过16位(大于0xFFFF),将高16位与低16位相加,直到结果为16位。
- 对最终结果取反(按位取反),得到校验和字段的值。
-
示例
- 抓取的IP首部20字节数据(十六进制):
45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d- 将校验和字段
b5 2e置为00 00,变为:
45 00 00 30 80 4c 40 00 80 06 00 00 d3 43 11 7b cb 51 15 3d- 按2字节拆分并求和(十六进制):
4500 + 0030 + 804c + 4000 + 8006 + 0000 + d343 + 117b + cb51 + 153d = 34ace- 处理进位(高16位3)加到低16位:
0003 + 4ace = 4ad1- 取反得到校验和:
~4ad1 = b52e
5. 校验和验证方法
-
对完整IP首部(含校验和字段)按2字节反码求和。
-
结果取反后应为0,表示校验通过。
-
示例验证:
4500 + 0030 + 804c + 4000 + 8006 + b52e + d343 + 117b + cb51 + 153d = 3fffc- 进位加法:
0003 + fffc = ffff- 取反:
~ffff = 0000校验正确
6. UDP协议及校验和计算
- UDP数据包格式
| 字段 | 长度(Byte) | 说明 |
|---|---|---|
| 源端口号 | 2 | 发送端口号 |
| 目的端口号 | 2 | 接收端口号 |
| UDP长度 | 2 | UDP头部和数据总长度 |
| UDP校验和 | 2 | 校验和字段(可选) |
| 数据 | 可变 | UDP有效载荷 |
-
UDP校验和计算方法
-
计算时需要三部分数据:
- UDP伪首部(包含IP源地址、目的地址、协议号、UDP长度)
- UDP首部
- UDP数据
-
计算步骤:
- 将UDP校验和字段置0。
- 将伪首部、UDP首部和数据按2字节拆分,逐个相加。
- 若结果超过16位,进位加到低16位。
- 取反得到UDP校验和。
-
示例:
相关数据(十六进制):
a9 fe bf 1f a9 fe 01 17 00 11 00 28 04 d2 04 d2 00 28 00 00 68 74 74 70 3a 2f 2f 77 77 77 2e 63 6d 73 6f 66 74 2e 63 6e 20 51 51 3a 31 30 38 36 35 36 30 30- 将校验和字段
00 92置为00 00。 - 按2字节拆分求和:
a9fe + bf1f + a9fe + 0117 + 0011 + 0028 + 04d2 + 04d2 + 0028 + 0000 + 6874 + 7470 + 3a2f + 2f77 + 7777 + 2e63 + 6d73 + 6f66 + 742e + 636e + 2051 + 513a + 3130 + 3836 + 3536 + 3030 = 6ff67- 进位加法:
6 + ff67 = ff6d- 取反得到校验和:
~ff6d = 0092 - 将校验和字段
-
7. 总结
| 校验和类型 | 计算范围 | 计算步骤简述 | 备注 |
|---|---|---|---|
| IP首部校验和 | IP首部(通常20字节) | 校验和字段置0,16位分段求和,进位加,取反 | 确保IP首部完整性 |
| UDP校验和 | UDP伪首部 + UDP首部 + UDP数据 | 校验和字段置0,16位分段求和,进位加,取反 | 可选字段,保证UDP数据完整性 |