[FPGA]以太网帧数据UDP报文解析接收

前言:做的项目需要读取网口发来的数据,发现做一遍真的是对这几种帧格式熟悉了一遍。
网口发来的格式是以太网帧格式,上一层使用IP协议,传输的UDP报文。

系统:WIN10, 开发平台:ISE 14.7
编程语言:VHDL
硬件平台:Virtex-6 FPGA ML605开发板
项目描述:将网口发来的以太网帧进行接收,层层解析,最后得到UDP报文内容。

一、数据格式

1.1、各层的数据格式

  • TCP和UDP同属运输层的传输协议, 不过UDP的首部是8Byte, TCP为20Byte.
    [FPGA]以太网帧数据UDP报文解析接收_第1张图片

1.2、以太网帧格式

  • 802.3 以太网帧结构
前导码 帧起始 MAC 目标地址 MAC 源地址 类型 负载 帧序列检测
7 Byte 的0x55 1 Byte 的0xD5 6 Byte 6 Byte 2 Byte 46-1500 Byte 4 Byte

(还有一种 Ethernet II 格式的帧, 是当数据大于1500字节时使用, ‘类型’字段换做’长度’)

  • 前导码 和 帧起始 是我们判断一帧数据起始位置的重要依据, 当检测到7个0x55且第8 Byte是0xD5时, 就可以读取接下来的有用数据了.
  • 类型 : 这个字段存储的是负载装的数据报是什么类型, 例如常用的 IP数据报是"0x0800".

1.3、IP数据报格式

版本号(4 bit) IP头长度(4bit) 服务类型(8 bit) 总长度(16 bit)
标识(16 bit) 标志(3 bit) 片偏移(13bit)
生存时间(8 bit) 上层协议标识(8 bit) 头部校验和(16 bit)
源IP地址(32 bit)
目的IP地址(32bit)
选项(选填)
数据
  • IP头一般是20Byte(如果没有附加选项), 所以第21byte就是向上一层协议的数据了(我只写了一些会用到的意义)
  • 版本号(4 bit): IPv4是"B0100" 值是4 , IPv6 是"B0110" 值是6 .
  • 数据包头部长度(4 bit): 它表示数据包头部包括多少个32位长整型,也就是多少个4字节的数据。无选项则为5(“B0101”).
  • 段偏移量(13位): 当大段的数据被分片传输, 为了与更多段位组合, 帮助接收方组合分段的报文, 以字节为单位, 便于分片重组.
  • 上层协议标识(8 bit): 表明使用该报文的上层协议,如TCP=6,ICMP=1,UDP=17等.

1.4、UDP段格式

源端口(16 Bit) 目的端口(16 Bit)
UDP长度(16 Bit) 校验和(16 Bit)
数据
  • UDP首部总共8Byte, '长度’这个字段包含的是整个UDP段的长度,包括首部.

二、传输的数据例举

使用Wireshark保存下的发送的一帧MAC帧,如下:

1    ff ff ff ff ff ff 00 21 86 f6 9f cb 08 00 45 00   
2    00 9c 00 00 00 00 80 11 db 78 0a 6c 54 6d ff ff   
3    ff ff ec 32 12 34 00 88 9f 9c 08 08 08 08 08 08   
4    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08   
5    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08   
6    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08  
7    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08  
8    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08  
9    08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08  
10   08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08  
11   08 08 08 08 08 08 08 08 08 08     
  1. MAC帧的首部被去掉了,是7个0x55和1个0xD5.
  2. 根据第一节中说到的帧格式可以判断出:
    目的物理地址: Broadcast (ff:ff:ff:ff:ff:ff);
    源物理地址: Universa_f6:9f:cb (00:21:86:f6:9f:cb);
    0800表示IP数据报协议;
  3. 4500进入IP头.
    4500表示Internet Protocol Version 4 , 报文长度5个32位, 服务类型 00;
    第二行的11表示 值为17 ,所以使用的UDP传输协议;
    源IP: 10.108.84.109(0a:6c:54:6d)
    目的IP: 255.255.255.255(ff:ff:ff:ff)
  4. 第三行从ec32进入UDP部分, ec32表示源端口为 60466,1234表示目的端口为 4660;
    0088表示UDP段算上首部一共136字节,也就是128字节的数据
    9c9f是16位的校验和;
    在这之后是我发的128Byte的0x08;

三、UDP报文解析程序

  • 使用了7种状态的状态机, 状态转换都是只能由上一个状态转换过来(除了GetUDPHead, GetTCPHead, 这两个是同一位置的两个分支)
  • 七种状态:
     Idle,FindMacHead, GetMacHead, GetIPHead, GetUDPHead, GetTCPHead, GetUDPDate
     空闲→寻找找MAC头状态→获取MAC头→获取IP头→获取UDP/TCP头→ 获取UDP数据
    1. Idle(空闲状态)
      这个状态是除以上6种状态之外的其他状态的总和.

    2. FindMacHead(寻找MAC头状态)
      由Idle状态下, 会直接转到此状态, 当匹配到7个0x55和1个0xD5 会进入GetMacHead状态

    3. GetMacHead(获取MAC头状态)
      当进入GetMacHead状态时, 同时有一个process进行时钟计数, 用来控制取各个字节的内容, 例如,进入此状态时, 数据是一个字节一个字节过来的, 前6个字节是目的MAC地址, 当计数器记到6说明,前六个字节已经取完. 直到取到 数据类型的字段位置时, 值为X"0800"就转到GetIPHead状态

    4. GetIPHead(获取IP头状态)
      同上,进入此状态时,同时也有一个计数器开始计数, 需要记录第10Byte的数字,用来判断使用的传输协议(6-TCP, 17-UDP)用来转到不同的状态.

    5. GetUDPHead / GetTCPHead(获取UDP / TCP头状态)
      同上,因为我没有获取之歌UDP头的信息,所以直接使用计数器过掉这个状态,也就是当他等于8时,转到GetUDPDate状态

    6. GetUDPDate(获取UDP数据)
      直接用计数器获取UDP数据.

这个VHDL文件我放在了GitHub上,希望大家点星星 .

你可能感兴趣的:(FPGA)