文章目录
前言:ARP层报文解析
当要和一个目的IP进行通信时,首先检查自己的ARP缓存表,是否存在目的IP对应的目的MAC,如存在则不会触发ARP请求与应答过程,直接根据ARP缓存表项封装目的MAC;
不存在arp缓存表,触发arp请求,对方收到arp请求,根据arp报文中的目的IP判断,是否寻找的主机是自己,如果是则发送arp响应携带自己的MAC地址, 回复对方。
一、ARP接收
该模块对接收到的ARP报文进行解析,主要是解析收到的是请求ARP还是回复ARP。
请求ARP:获取请求报文当中的源MAC和源IP,这些内容会作为回复ARP当中的目的地址,同时检测请求ARP当中的目的IP,如果是本机,则产生一个触发回复信号o_trig_reply给ARP_TX模块,发送模块会产生相应的回复报文;同时请求报文当中的源MAC和源IP也会被发送到ARP_table进行缓存。
回复ARP:获取请求报文当中的源MAC和源IP,将其缓存到ARP_table模块
二、ARP发送
首先系统上电会进行一次主动ARP,当ARP_TX模块收到主动ARP信号请求时,会产生一个ARP请求报文;其次当收到ARP_RX模块的o_trig_reply信号时,会产生一个回复ARP报文。就如何进行组帧的部分前俩章都进行了介绍,不做赘述。
always @(posedge i_clk or posedge i_rst)begin
if(i_rst)
ro_mac_data <= 'd0;
else case (r_arp_cnt)
0 : ro_mac_data <= 8'h00; //硬件类型,对以太网,值为1
1 : ro_mac_data <= 8'h01;
2 : ro_mac_data <= 8'h08; //协议类型,IP 0x0800
3 : ro_mac_data <= 8'h00;
4 : ro_mac_data <= 'd6; //硬件地址长度
5 : ro_mac_data <= 'd4; //协议长度
6 : ro_mac_data <= r_arp_op[15:8]; //操作类型
7 : ro_mac_data <= r_arp_op[7 :0];
8 : ro_mac_data <= r_src_mac[47:40];
9 : ro_mac_data <= r_src_mac[39:32];
10 : ro_mac_data <= r_src_mac[31:24];
11 : ro_mac_data <= r_src_mac[23:16];
12 : ro_mac_data <= r_src_mac[15: 8];
13 : ro_mac_data <= r_src_mac[7 : 0];
14 : ro_mac_data <= r_src_ip[31:24];
15 : ro_mac_data <= r_src_ip[23:16];
16 : ro_mac_data <= r_src_ip[15: 8];
17 : ro_mac_data <= r_src_ip[7 : 0];
18 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[47:40] : 8'h00;
19 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[39:32] : 8'h00;
20 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[31:24] : 8'h00;
21 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[23:16] : 8'h00;
22 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[15: 8] : 8'h00;
23 : ro_mac_data <= r_arp_op == P_ARP_OP_REPLY ? ri_reply_mac[7 : 0] : 8'h00;
24 : ro_mac_data <= r_dst_ip[31:24];
25 : ro_mac_data <= r_dst_ip[23:16];
26 : ro_mac_data <= r_dst_ip[15: 8];
27 : ro_mac_data <= r_dst_ip[7 : 0];
default : ro_mac_data <= 'd0;
endcase
end
三、ARP缓存表
该模块将接收到的回复ARP报文中的MAC和IP地址进行保存,主要通过俩个RAM实现。
当IP层进行组帧时,根据目标IP地址会发出一个寻找请求i_seek_valid和寻找IP信号i_seek_ip到该模块,该模块会查找相应的MAC地址,如果找到则返回对应的MAC地址,如果没有,则返回48’hffff_ffff_ffff,即广播MAC。
RAM_IP RAM_IP_u0 (
.clka (i_clk ),
.ena (r_ip_ram_en ),
.wea (r_ip_ram_we ),
.addra (r_ip_ram_addr ),
.dina (r_updata_ip ),
.douta (w_ip_ram_dout )
);
RAM_MAC RAM_MAC_u0 (
.clka (i_clk ),
.ena (r_mac_ram_en ),
.wea (r_mac_ram_we ),
.addra (r_mac_ram_addr ),
.dina (r_updata_mac ),
.douta (w_mac_ram_dout )
);
这里多提一句: 对于广播的ARP报文,ARP当中的目的MAC字段为全0,MAC层目的MAC地址字段全F。
总结
完整代码参考GitHub:https://github.com/shun6-6/Tri_Eth_UDP_pro_stack