UDP收发以及所需要的ARP协议已经全部实现,接下来让咱们的协议栈支持ping,俗称能ping通。
ping的请求和发送实际是ICMP协议的一个子集,ICMP可以参考ICMP数据包结构_Focus_新浪博客
在IP头中ICMP协议的标识是01,其ICMP头结构是用C语言表示为:
// ICMP header
typedef struct _tagX_icmphdr
{
unsigned char i_type; //类型
unsigned char i_code; //代码
unsigned short i_cksum; //检验和
unsigned short i_id; //标识符
unsigned short i_seq; //序列号
unsigned long i_timestamp; //当前时间 =(unsigned long)::GetTickCount();
}XIcmpHeader;
其中
unsigned char 是8位的字节 1个字节
unsigned short 是16位的字 2个字节
unsigned long 是32位的字 4个字节
看见整个ICMP头部是1+1+2+2+2+4 = 12 字节。
我们每个字段过滤一下:
第一字节type:8代表ping request ,0 代表ping reply。我们收到的是type=8的ping请求包,我们回复type=0的ping回复包。
第二字节code:ping request实际抓包数据是0.
第三双字节字chksum,需要进一步资料或者例子看看都是哪写内容的chksum。
第四个双字节字id,我觉得这应该是ping_request端任意写的,而我们回应ping就要把这个原封不动回应回去。
第5个双字节字sequence,应该跟ID一样需要在ping reply中直接返回去就好。
后续的32个字节,需要原封不动的回传就好(我看到这些字节都是依次+1,是否可以考虑不用数组保存呢,算了吧不差那点ram,因为那些数据的顺序+1肯定不是协议规定的,我们既然做就得兼容尽量)。
这里有个问题,就是后续字节长度没有被明确字段标注出来,只能数完了得到结果。
这样其实基本明了了:
id和sequence以及后面的字节,我们直接拷贝发回去就好,type=0,code=0(需要抓包确认下),再确认以下checksum是那些字节参与的加。
icmp包检验和计算方法及python实现 | 馨木
这个文章明确给出了icmp的check sum计算的(12-2)字节的头部除去check sum的其他字段以及携带的数据。这样就很明确了。
解析出来的接口内容要包含type,code.之后check sum我们就不检验了,直接按照检验通过处理。其余剩下的字段(id ,seq以及data)就原封不动的发回去。我们用一个FIFO来保存上述三部分,在写入bram的时候,计算出来这些数据的check sum,再加上确定的id和type。check sum就是确定的了。
上述分析基本比较全面,代码也呼之欲出。这就开始撸代码。
{{aAxvOXMOIvVUoXMxvoxiowMwWV8xxWTxoxOIOVIUUOvwVOUiIoUvvTMMVMwovWHWX8vOUOVUViOXUWTvUViUWWXWmVoT8HIOHwTVTiiWIX88ioVomHMoiHIoVU8VvmvIWXTvvOvv8xvMovOWomOTvoiM8UiUTWTMvOMMXVmWZz}}