TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

前言:要实现基于FPGA的TCP硬件协议栈,需要充分了解以太网通信协议,因此先展开对UDPIP的实现。经过一年来不断的探索,最近从新设计并优化了UDPIP协议栈,内容较多,因此分为接收、发送两个部分2篇文章,来介绍UDPIP的调试与实现过程。

文中主要目录:

设计部分:一、ARP数据的发送;二、UDP数据的发送;三、IP数据的发送;

测试部分:一、ARP回复测试;二、UDP测试问题:问题1、UDP校验和问题。问题2、CRC校验问题。问题3、RAM下降沿存数,上升沿读数,造成数据错位

应用拓展:WireShark开启校验和核对功能

 

发送部分的设计

20191103 周日

经过这两天的设计,发现,没法像最初想的那样,一层层往上封装,直到MAC层发送。因为每类数据功能不同,应用场景不同。如,若接收到UDP帧,那建立连接的肯定是UDP。所以针对具体特性,经过反复考虑,最佳的方式,便是分类型,单独给出发送数据接口,再在顶层进行数据输出仲裁。

在此版本中,将ARP和IP分开进行发送。后面,还要对IP下层的UDP,TCP,ICMP都进行单独发送才行。

经过这两天的奋战,终于得到了如下的仿真结果。

仿真文件为:tb1_tcpip_stack.v 顶层全局仿真。具体模块发送测试如下。

一、ARP数据的发送

模块代码文件:arp_tx_framing.v ,mac_tx_control.v

下图为ARP接收到发送的过程。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

展开的ARP发送数据前端,和后端如下:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

二、UDP数据的发送

顶层接口如下:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

三、IP数据的发送

模块代码文件:ip_tx_framing.v

其顶层接口:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

UDP数据接收到发送如下:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

前端:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

中部:从RAM中读取第一个UDP数据,如下。RAM地址要提前给。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

末端:CRC正确

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

MAC层控制数据发送,100us发送一次UDP,仿真如下

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

功能测试部分

20191105 周二

一、ARP回复测试

PC端通过默认网关请求ARP,FPGA解析该请求帧,然后回复ARP请求。如下图,成功收到ARP回复。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

二、UDP测试问题

问题1:UDP校验和问题。

如下图,网络调试助手发的UDP校验和不对,正确的应该是,0xfa90 。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

很奇怪,直接测试UDP收发,是正常的。我加了校验位,反而不对。

UDP校验和问题:经过反复测试,我加上正确的UDP校验和,网络调试助手反而不通过,接收不到数据。反而是置0后,就接收正常了。

 

问题2:CRC校验问题

网络调试助手为什么在WireShark打开时,能接收数据,关闭时,就接收不到数据。

网上解答:wireshark默认启用混杂模式,CRC校验错误的包也能显示。网络调试助手是需要校验FCS的,错误的包是不会显示的。——这个说法有道理。我仔细核查了UDP数据,都是正确的。那么出错地方真的很可能在CRC了。

网上解答2:是因为下位机的端口在发送的时候MAC地址不对,网卡直接屏蔽了数据,当用wireshark工具打开监听的时候相当于屏蔽了网卡mac地址屏蔽的功能 数据就直接进来了。——我仔细核对的MAC地址,是对的。不是这个问题。

CRC前仿真的计算结果。Crc2

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

CRC后仿真,上看,除了时钟转换期间有很多杂数据,中间数据还是对的和前仿真一致。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

经过仔细仿真、分析,结合以前ok的程序进行对比分析,才发现,这个CRC是真的有问题。程序设计中,CRC计算在上升沿,那么就不能在上升沿取数,“那时那刻”的数据是亚稳态的。程序中,将发送时钟改为下降沿取数,就好了!(这个问题,从去年困扰我,到现在才找到原因!)

 

问题3:RAM下降沿存数,上升沿读数,造成数据错位

因为问题2的存在,在发送时改为下降沿取数,测试时发现,第一个数被正确读取。因此,回到程序,再修改RAM读写时的细节控制。

仿真程序为:tb1_tcpip_stack_for_udp_ram.v

程序未改之前的仿真,可见第一个字节FF没正确取出来。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

思路:下降沿给地址,上升沿取数,不用地址超前准备。因此,初始时,地址=0,就好了。改了程序之后的仿真如下:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

本程序中UDP测试小结:

经过前面的调试,终于调通。测试结果如下,可随意更改发送数据,不用开启wireshark都能正常接收。完成UDP的以太网传输功能,定位tcpip_stack_v1,算是初版。

其中,未加UDP校验和。加入了ARP应答功能。未加ICMP和TCP功能。

网络调试助手测试如下:前面测试了随意长度的包,都可以跟新数据回传。下面是1380字节的包,也是正常接收的。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

马上用TCP&UDP助手测试,任意数据,如下,均正常接收。

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

 

PS:遗留问题:为什么UDP校验和加上,测试软件竟然接收不到数据呢?反而校验和=0000时,接收正常。

 

WireShark开启校验和核对功能

前面做了很多测试,发现WireShark把各个校验和都屏蔽了,也就是,数据中的校验和对不对,它没做判断。为了验证我加的IP、UDP等校验和的正确性,在起初,我是用手算的方式,真的累扁我了。今天才发现,原来可以开启WireShark的校验和核对功能,真是涨了见识。软件中设置开启方式如下图:

TCP/IP协议栈设计—UDP/IP协议栈设计与实现(发送部分)

开启这个功能后,我就能很方便地查看自己计算的对不对了。从上图中可以看出,我在程序中的计算是对的。害我还在前面,手动算了那么多次。

针对遗留问题的解答:

文中的CRC问题,后面经仔细研究,终于找到问题。原因在于,CRC计算是组合逻辑的,如果在上升沿赋值,并在上升沿又取结果,在这个时刻,CRC结果存在亚稳态,导致实际工作过程中的CRC检验是错的。

通过优化代码,在时钟上升沿进行CRC计算,下降沿取计算结果,这样就避免亚稳态了。经测试,调试助手正确接收数据,功能完全正常了。

 

欢迎交流、源码分享见****资源,笔者扣扣:1021100382