FPGA实现UDP协议

基础知识

以太网简介

以太网是现实世界中最普遍的一种计算机网络。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一种称为交换机的设备连接不同的计算机。经典以太网是以太网的原始形式,运行速度从3~10 Mbps不等;而交换式以太网正是广泛应用的以太网,可运行在100、1000和10000Mbps那样的高速率,分别以快速以太网、千兆以太网和万兆以太网的形式呈现。

TCP/IP协议

TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。
TCP/IP协议是Internet最基本的协议,其中应用层的主要协议有Telnet、FTP、SMTP等,是用来接收来自传输层的数据或者按不同应用要求与方式将数据传输至传输层;传输层的主要协议有UDP、TCP,是使用者使用平台和计算机信息网内部数据结合的通道,可以实现数据传输与数据共享;网络层的主要协议有ICMP、IP、IGMP,主要负责网络中数据包的传送等;而网络访问层,也叫网络接口层或数据链路层,主要协议有ARP、RARP,主要功能是提供链路管理错误检测、对不同通信媒介有关信息细节问题进行有效处理等。其结构与OSI参考模型关系如图所示。图0

数据结构

在实现UDP协议之前,我们需要清楚的知道数据是从那一层,以哪种格式进入FPGA的,以及我们在使用一些IP核之后能够获得的数据结构是什么样的。图1

MAC层

链路层,又称MAC层。MAC的全称为Medium Access Control,即媒体访问控制,主要有两个功能,寻址和控制。以太网技术的正式标准是IEEE 802.3,它规定了以太网传输数据的帧结构,我们可以把以太网MAC层理解成高速公路,我们必须遵循它的规则才能在上面通行。以太网MAC层帧格式如图所示。图2

  • 前导码(Preamble):
    为了实现底层数据的正确阐述,物理层使用7个字节同步码(0和1交替(55-55-55-55-55-55-55))实现数据的同步。
  • 帧起始界定符(SFD,Start Frame Delimiter):
    使用1个字节的SFD(固定值为0xd5)来表示一帧的开始,即后面紧跟着传输的就是以太网的帧头。
  • 目的MAC地址:
    即接收端物理MAC地址,占用6个字节。MAC地址从应用上可分为单播地址、组播地址和广播地址。单播地址:第一个字节的最低位为0,比如00-00-00-11-11-11,一般用于标志唯一的设备;组播地址:第一个字节的最低位为1,比如01-00-00-11-11-11,一般用于标志同属一组的多个设备;广播地址:所有48bit全为1,即FF-FF-FF-FF-FF-FF,它用于标志同一网段中的所有设备。
  • 源MAC地址:
    即发送端物理MAC地址,占用6个字节。
  • 长度/类型:
    上图中的长度/类型具有两个意义,当这两个字节的值小于1536(十六进制为0x0600)时,代表该以太网中数据段的长度;如果这两个字节的值大于1536,则表示该以太网中的数据属于哪个上层协议,例如0x0800代表IP协议(网际协议)、0x0806代表ARP协议(地址解析协议)等。
  • 数据:
    以太网中的数据段长度最小46个字节,最大1500个字节。最大值1500称为以太网的最大传输单元(MTU,Maximum Transmission Unit),之所以限制最大传输单元是因为在多个计算机的数据帧排队等待传输时,如果某个数据帧太大的话,那么其它数据帧等待的时间就会加长,导致体验变差,这就像一个十字路口的红绿灯,你可以让绿灯持续亮一小时,但是等红灯的人一定不愿意的。另外还要考虑网络I/O控制器缓存区资源以及网络最大的承载能力等因素,因此最大传输单元是由各种综合因素决定的。为了避免增加额外的配置,通常以太网的有效数据字段小于1500个字节。
  • 帧检验序列(FCS,Frame Check Sequence):
    为了确保数据的正确传输,在数据的尾部加入了4个字节的循环冗余校验码(CRC校验)来检测数据是否传输错误。CRC数据校验从以太网帧头开始即不包含前导码和帧起始界定符。通用的CRC标准有CRC-8、CRC-16、CRC-32、CRCCCIT,其中在网络通信系统中应用最广泛的是CRC-32标准。

MAC层数据为进入FPGA的最原始的数据。显然如果我们直接对MAC层的数据进行操作,由于需要串并转换等操作,会极大增加我们的工作量。而Xilinx官方也提供了较为实用的IP核供我们使用。如10G/25G Ethernet Subusystem。该IP核输出的数据为**目的MAC地址+源MAC地址+长度/类型+数据。因此当我们从该IP核获取数据后,根据帧长度,即可提取帧内部的所有信息。

IP层

网络层,又称IP层,位于以太网MAC帧格式的数据段,由IP首部和IP数据段组成数据报。所有的TCP、UDP及ICMP数据都以IP数据报格式传输。数据报格式如图所示。图3

  • 版本(Version):
    4位IP版本号,这个值设置为二进制的0100时表示IPv4,设置为0110时表示IPv6。
  • 首部长度(IHL, Internet Header Length):
    4位首部长度,表示IP首部一共有多少个32位数据。在没有可选字段时,IP首部长度为20个字节,因此首部长度的值为5。
  • 服务类型(TOS, Type of service):
    8位服务类型,该字段被划分成两个子字段:3位优先级字段和4位TOS字段,最后一位固定为0。服务类型为0时表示一般服务。
  • 总长度(Total Length):
    16位IP数据报总长度,包括IP首部和IP数据部分,以字节为单位。我们利用IP首部长度和IP数据报总长度,就可以知道IP数据报中数据内容的起始位和长度。由于该字段长16bit,所以IP数据报最长可达65535字节。尽管理论上可以传输长达65535字节的IP数据报,但实际上还要考虑网络的最大承载能力等因素。
  • 标识字段(Identification):
    16位标识字段,用来标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1。
  • 标志字段(Flags):
    3位标志字段,第1位为保留位;第2位表示禁止分片(1表示不分片0:允许分片);第3位标识更多分片(除了数据报的最后一个分片外,其它分片都为1)。
  • 片偏移(Fragment Offset):
    13位片偏移,在接收方进行数据报重组时用来标识分片的顺序。
  • 生存时间(TTL, Time To Live):
    8位生存时间字段,域防止丢失的数据包在无休止的传播,一般被设置为64或者128。
  • 首部校验和(Header Checksum):
    16位首部校验和,该字段只校验数据报的首部,不包含数据部分;校验IP数据报头部是否被破坏、篡改和丢失等。
  • 源IP地址(Source Address):
    32位源IP地址,发送端的IP地址。
  • 目的IP地址(Destination Address):
    32位目的IP地址,接收端的IP地址。
  • 可选字段:
    数据报中的一个可变长度的可选信息,选项字段以32bit为界,不足时插入值为0的填充字节,保证IP首部始终是32bit的整数倍。

首部校验和计算方法如下图所示。图4

UDP层

由于我们准备实现UDP协议,因此UDP层对应的OSI参考模型的层级为传输层。在UDP层中,数据遵循UDP协议进行传输。实际上,数据是可以直接封装在IP协议里而不使用TCP、UDP或者其它上层协议的。然而在网络传输中同一IP服务器需要提供各种不同的服务,各种不同的服务类型是使用端口号来区分的,例如用于浏览网页服务的80端口,用于FTP(文件传输协议)服务的21端口等。TCP和UDP都使用两个字节的端口号,理论上可以表示的范围为0~65535,足够满足各种不同的服务类型。
TCP协议为可靠传输协议,UDP协议为不可靠传输协议,虽然UDP无法保证数据的完整和有序,但是UDP的传输速度更快,且消耗的资源更少。并且,虽然FPGA可以实现TCP协议,但是工作量是极大的。UDP相较于TCP,在FPGA的可实现难度上大大降低,因此可以看到网上的大部分资料都在描述FPGA如何实现UDP协议,而非TCP协议。
下图为UDP协议数据格式。图5

  • 源端口号:
    16位发送端端口号,用于区分不同服务的端口,端口号的范围从0到65535。
  • 目的端口号:
    16位接收端端口号。
  • UDP长度:
    16位UDP长度,包含UDP首部长度+数据长度,单位byte。
  • UDP校验和:
    16位UDP校验和。UDP计算校验和的方法和计算IP数据报首部校验和的方法相似,需要校验的内容包含:UDP伪首部,UDP首部和UDP数据段。其中UDP伪首部由源IP地址,目的IP地址,协议类型和UDP长度组成。其目的是让UDP两次检查数据是否已经正确到达目的地。

用户层

用户层对应的OSI参考模型的层级的应用层。用户层的数据段也是我们需要的最原始的数据。FPGA端发送数据时,原始数据经过打包获得UDP数据报,UDP数据包经过打包获得IP数据报,IP数据报添加帧信息形成MAC帧。FPGA接收数据时,MAC帧解析出IP数据报,IP数据报解析出UDP数据报,UDP数据报解析出原始数据。

物理层(硬件知识)

物理层(PHY)在发送数据的时候,接收MAC发过来的数据,把并行数据转化为串行流数据,按照物理层的编码规则把数据编码转换为模拟信号发送出去,接收数据时的流程反之。PHY还提供了和对端设备连接的重要功能并通过LED灯显示出自己目前的连接状态和工作状态。当我们给网卡接入网线的时候,PHY芯片不断发出脉冲信号来检测对端是否有设备,它们通过标准的“语言”交流,互相协商并确定连接速度、双工模式、是否采用流控等。通常情况下,协商的结果是两个设备中能同时支持的最大速度和最好的双工模式。这个技术被称为Auto Negotiation,即自动协商。以太网MAC和PHY之间有一个接口,常用的接口有MII、RMII、GMII、RGMII等。

ARP协议

ARP(Address Resolution Protocol),地址解析协议,是根据IP地址获取物理地址的一个TCP/IP协议。在开始进行网络通讯时,源主机只知道目的主机的IP地址,确不知道目的主机的MAC地址。因此,在网络通讯的一开始,源主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。其工作过程如图所示。图6
任何时候,当主机需要找出这个网络中的另一个主机的物理地址时,它就会发送一个ARP请求报文,这个报文包含发送方的MAC地址和IP地址以及接收方的IP地址。由于发送方不知道接收方的MAC地址,因此ARP请求报文需要在网络层中进行广播。局域网中的所有主机都会接受并处理ARP请求报文,查看请求的IP地址是不是自己的IP地址。如果是,接收方主机会返回一个ARP响应报文,这个响应报文包含接收方的IP地址和MAC地址。由于此时双方的IP地址和MAC地址均已知,因此ARP响应报文以单播的形式在网络层中传输。ARP报文格式如图所示。图7

系统结构框图

图8
ETHERNET_TOP系统框图如图所示。Host端发送过来的数据经过ETHERNET串并转换后得到MAC层数据,该数据经过UDP_TOP和ARP_TOP进行解包分析,最终由UDP_TOP输出用户数据。用户数据经过UDP_TOP进行打包形成MAC层数据,该数据在DATA_ARB处与由ARP_TOP输出的ARP响应数据包进行仲裁,最终输出给ETHERNET进行并串转换发送给Host端。

  • ETHERNET:
    由于我需要实现10G网口的通讯,且使用的FPGA型号为XCKU06。因此该框图中ETHERNET模块为xilinx官方的10G/25G Ethernet Subusystem,其主要作用为串并转换并输出用户数据。
  • DATA_ARB:
    DATA_ARB为数据仲裁功能,其主要作用为选通ARP数据和UDP数据。当处于ARP响应状态时,输出ARP数据,否则输出UDP数据。
  • UDP_TOP:
    UDP_TOP为UDP数据包处理模块,其主要的作用为时钟域转换以及数据打包解包。
  • ARP_TOP:
    ARP_TOP模块为ARP应答模块,其主要作用为在检测到Host端的ARP请求后,输出一个ARP响应数据包。

ETHERNET_TOP系统的输入输出如下表所示。

用户参数

Name Description
BOARD_MAC 系统MAC地址
BOARD_IP 系统IP地址
BOARD_UDP 系统UDP端口号

信号接口

Name Bit Width IO Type Description
sys_clk 1 input 系统时钟
sys_rstn 1 input 系统复位
drp_clk 1 input Ethernet IP核DRP时钟
gt_refclk_p/n 1 input Ethernet IP核gt参考时钟
gt_rxp/n_in 1 input Ethernet IP核gt信号输入
gt_txp/n_out 1 output Ethernet IP核gt信号输出
gt_disable 1 output PHY使能开关,置1关闭
axis_din 32b bus input AXI-Stream总线数据,包含keep,last
axis_dout 32b bus output AXI-Stream总线数据,包含keep,last,user

模块设计

UDP_TOP模块

图9
UDP_TOP模块内部框图如图所示。Host发送过来的MAC层数据axis_rx_mac经过UDP_RX进行解包获取rx_clk下的用户数据,该用户数据经过跨时钟域处理转换为sys_clk下的数据axis_rx_app并输出。FPGA内部待发送的用户数据axis_tx_app经过UDP_TX进行打包获取sys_clk下的MAC层数据,该MAC层数据经过跨时钟域处理转换为tx_clk下的数据axis_tx_mac并输出。

  • UDP_RX:
    接收端MAC层数据解包模块,输出rx_clk时钟域下的用户层数据。
  • RX_FIFO:
    接收端用户层数据跨时钟域处理模块,输出sys_clk时钟域下的用户层数据。
  • UDP_TX:
    发送端用户层数据打包模块,输出sys_clk时钟域下的MAC层数据。
  • TX_FIFO:
    发送端MAC层数据跨时钟域处理模块,输出tx_clk时钟域下的MAC层数据。

UDP_TOP模块的输入输出信号接口如下表所示。

Name Bit Width IO Type Description
sys_clk 1 input 系统时钟
sys_rstn 1 input 系统复位
rx_clk 1 input 接收端时钟
rx_rst 1 input 接收端复位
tx_clk 1 input 发送端时钟
tx_rst 1 input 发送端复位
drp_clk 1 input Ethernet IP核DRP时钟
axis_rx_mac 32b bus input 接收端MAC层AXI-Stream总线数据,包含keep,last
axis_rx_app 32b bus output 接收端用户层AXI-Stream总线数据,包含keep,last,user
axis_tx_app 32b bus input 发送端用户层AXI-Stream总线数据,包含keep,last
axis_tx_mac 32b bus output 发送端MAC层AXI-Stream总线数据,包含keep,last

UDP_RX模块

图10
UDP_RX模块内部框图如图所示。MAC层数据axis_mac经过RX_HEADER和RX_ALIGN分别输出数据包信息和待缓存用户层数据。数据包信息中的Host端信息(MAC地址、IP地址、UDP端口号)被UDP_RX输出到外部,其他的信息被传输给IP_CRC进行IP校验。待缓存的用户层数据一路被传出给UDP_CRC模块进行UDP校验,另一路被传输给RX_FIFO进行缓存并输出最终的用户层数据axis_app。

  • RX_CHECK:
    该模块为UDP_RX模块的核心部分。其中包含了报头信息获取模块RX_HEADER、用户数据获取移位模块RX_ALIGN、IP信息校验模块IP_CRC、UDP信息校验模块UDP_CRC。
  • RX_FIFO:
    该模块的作用为缓存用户数据。

UDP_RX模块的输入输出信号接口如下表所示。

Name Bit Width IO Type Description
clk 1 input 模块时钟
rstn 1 input 模块复位
mac_src 1 output Host端MAC地址
ip_src 1 output Host端ip地址
udp_src 1 output Host端UDP端口
axis_mac 32b bus input 接收端MAC层AXI-Stream总线数据,包含keep,last
axis_app 32b bus output 接收端用户层AXI-Stream总线数据,包含keep,last,user

UDP_TX模块

图11
UDP_TX模块内部框图如图所示。用户层数据axis_app经过TX_HEADER计算输出udp长度udp_length和ip长度ip_total_length。udp长度和用户层数据axis_app在UDP_CRC中进行UDP校验并输出校验结果udp_crc。ip长度和其他的报头信息在IP_CRC中进行IP校验并输出校验结果ip_crc。当所有的校验完成后,缓存在TX_FIFO中的用户层数据被读出,读出的数据在TX_ALIGN中进行打包并输出最终的MAC层数据axis_mac。

  • TX_FIFO:
    用户数据缓存模块,用于等待校验完成时的数据缓。
  • TX_HEADER:
    数据报头信息获取模块,用于获取输入的用户数据长度和IP总长度。
  • IP_CRC:
    IP校验模块,用于获取IP校验信息。
  • UDP_CRC:
    UDP校验模块,用于获取UDP校验信息。
  • TX_ALIGN:
    数据打包模块,将用户层数据打包成MAC层数据。

UDP_TX模块的输入输出信号接口如下表所示。

Name Bit Width IO Type Description
clk 1 input 模块时钟
rstn 1 input 模块复位
mac_src 1 input Host端MAC地址
ip_src 1 input Host端ip地址
udp_src 1 input Host端UDP端口
axis_app 32b bus input 发送端用户层AXI-Stream总线数据,包含keep,last
axis_mac 32b bus output 发送端MAC层AXI-Stream总线数据,包含keep,last

ARP_TOP模块

图12
ARP_TOP模块内部框图如图所示。Host发送过来的MAC层数据axis_rx_mac经过ARP_RX进行解包,若检测到该包为ARP请求包,则拉高arp_vld信号并输出Host端的MAC地址pc_mac和IP地址pc_ip。当ARP_TX检测到arp_vld信号后,开始生成并输出ARP响应包数据axis_tx_mac。

  • ARP_RX:
    ARP请求数据包解析模块,用于获取有效的ARP数据包并输出Host端信息。
  • ARP_TX:
    ARP响应数据包生成模块,用于生成并输出有效的ARP响应数据包。

ARP_TOP模块的输入输出信号接口如下表所示。

Name Bit Width IO Type Description
rx_clk 1 input 接收端时钟
rx_rst 1 input 接收端复位
tx_clk 1 input 发送端时钟
tx_rst 1 input 发送端复位
axis_rx_mac 32b bus input 接收端MAC层AXI-Stream总线数据,包含keep,last
axis_tx_mac 32b bus output 发送端MAC层AXI-Stream总线数据,包含keep,last

当FPGA资源紧张时,可以选择不使用ARP_TOP模块。可以通过管理员运行arp -s IP地址 MAC地址指令设置静态ARP缓存,来实现Host端与该系统之间的通讯。

结语

终于讲完了这部分,期间断断续续更新了好几次,实在是项目事情太多。关于这部分的代码已经在实际工程中使用并测试了一段时间,并无太大的问题。后续计划会对网络协议的知识进行扩展补充。