赞
踩
上回确定了UDP/IP硬件协议栈的基本目标,历时五天终于把代码撸完了,简单上板测试下问题不大,接下来就是简单把设计过程介绍下。
首先声明:并未参考网上其他代码 ,全部是对照《TCP/IP详解》一书完成的,所以处理机制不合适还望指正!
首先是分类,即问进来的以太网数据“你是什么垃圾?”
对于本弟弟协议栈来说,进入的数据先粗分为“ARP”、“ICMP”、“UDP”和“others”。其中ICMP和UDP是基于IP协议的,而本协议栈的IP协议不支持分片、option、IPv6等,所以在分类时需注意。
如上图所示[1],以TCP协议为例:
直接使用wireshark抓包来看以太网帧结构会更加方便,如下图所示 :
总之,以太网帧就像套娃一样将“用户数据”层层打包进行发送,而接收的时候也是层层拆包把“用户数据”解析出来。
ARP的请求或应答的帧结构如下图所示[2],有14字节的MAC首部和28字节ARP数据,其中MAC首部中的帧类型字段为0806标明接下来的是ARP帧,而ARP除了标明硬件、协议的类型/地址长度字段外,有个2字节的opcode字段,当为0x0001时为请求,0x0002为应答。
似乎看不太明白,直接上wireshark,下图即一次ARP的请求帧。
那么获取ARP请求帧就简单了,当MAC首部的Type字段为0x0806,并且ARP数据报中Opcode字段为0x0001,并且请求的Target IP地址为本机的IP地址,这样就能筛选出一条对本机请求的一条ARP帧。
前面说了MAC首部中的类型字段若是0x0800的话即表示接下来的协议为IPv4协议,而ICMP和UDP都是基于IP协议的,所以先来看看它的首部的字段。
4bit的版本字段(Version)标明其IP协议的版本,4'b0100即表示为IPv4;
4bit的首部长度字段(Header length)标明IP首部的长度,像是4'b0101即表示首部长度为20字节(若有option则首部长度会更长一点);
1字节的协议字段(Protocol)标明IP数据部分的协议,像是8'h01为ICMP,8'h11为UDP;
当然,其他字段也有用,但对于本文来说只关注其版本、首部长度、协议等字段,可用于分类使用。
对于ICMP,是基于IP协议的(前面所示),直接看ICMP的报文,此外不同类型/代码的ICMP的报文格式会有些许差别,下图仅为回显请求和应答的报文格式(用于PING)[3],其中的类型字段,0x08标明请求,0x00标明应答。
直接看wireshark抓包,如下图所示
那么,要获取ICMP帧(ping请求)则需要,MAC首部的类型字段为0x0800(仅考虑IPv4),IP首部协议字段为0x01,ICMP报文的类型字段为0x08(请求)。
UDP帧是本协议栈的重点,直接看wireshark抓包,如下图
UDP也是采用IP协议,所以可以通过IP首部的protocol类型来判断,0x11即标明为UDP。而UDP作为本协议栈的主要传输的数据,所以对于其首部的端口等信息直接传给应用层,不再加以分类处理了。
总结就是,要获取UDP帧,MAC首部的类型字段为0x0800(仅考虑IPv4),IP首部协议字段为0x11(即UDP)。
对本协议栈来说,非上述协议的以太网帧即其他帧,可以选择直接丢弃。
由于以太网帧传输采用大端模式,所以对接收的数据提取关键信息时需注意,此外整个流程为流水处理,所以直接对接收的字节进行移位寄存获取相应字段的信息,从而完成提取和分类。
always
以上即获取MAC首部,只有当目的mac地址与本机的mac地址一样或者为广播地址时才认为有效,同时在MAC首部中可以简单分为IP协议和ARP协议,其余的进行舍弃。
IP首部获取同样采用移位寄存方式,获取20字节的IP首部信息(暂不支持IPv6和option等),从协议类型字段中可获取IP数据部分的协议,总长度字段需小于等于1500字节(MTU),至于帧长大于MTU的巨型帧采取丢弃处理,此外目的IP地址需要与本机的一致,其他的予以舍弃。
assign
always
只有当icmp_type为0x08时才认为有效,其他予以舍弃。
always
UDP首部同理,解析后的首部信息{源端口、目的端口、UDP帧长、UDP首部checksum}需交予其他逻辑处理,在分类中暂不说明。
对于ARP而言,数据部分只对ARP处理模块输出完整的28字节的ARP数据(padding不输出),至于是否应答均交由后续逻辑判断,本文不加以说明;
对于ICMP而言,输出完整的ICMP数据(8字节头和数量不等的padding),交由后续逻辑处理;
对于UDP而言,输出完整的UDP纯数据(UDP首部以后的数据),交由后续逻辑处理。
包括:源/目的MAC地址,源/目的IP地址,源/目的端口,数据帧长等,这个状态信息随着每帧的数据进行输出,供后续模块处理使用。
当然,仅仅完成协议解析分类还是不够的,如果需要检验checksum或者FCS进行过滤的话,还需要再次对解析的数据进行校验计算,为降低延迟,需要在收到数据的同时进行校验的计算,不过,这也就是下篇该完成的事情了。
若有不足之处还望请批评指教~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。