uip源码剖析【一】——【网络层】ARP解读
===================转载请保留头部====================
作者:souroot 来源:WEB DNA
连接:http://www.cnblogs.com/souroot/archive/2013/04/21/3033856.html
关键词:TCPIP UIP 51单片机 计算机网络 网络工程专业 手把手教你写tcpip协议栈
版权: Q college 版权所有
=====================以下为正文=====================
uip对TCPIP协议栈做了最大的精简,最最基本的TCPIP协议栈,最起码要有4个协议:ARP、IP、ICMP、TCP,
为什么ARP很重要呢?因为报文在网络上传递,最终还是需要二层地址,即MAC地址的,而运行uip的主机只知道报文的目的ip地址,而对MAC地址是不了解的。
这时候就需要ARP了。
====ARP流程=====
ARP是已知对端的IP地址,想要获取对端的MAC地址,就会发送一个ARP请求,对端收到ARP请求后,会发送一个ARP应答给源主机。这是个大概的流程。下面讲一下详细的流程:
====详细流程=====
【ARP请求的发送】
主机首先检查要发送的报文的目的IP是否和自己在同一网段,如果在同一网段,就请求目的主机的MAC地址;如果不是同一网段的,就请求网关的MAC地址。
【接收到ARP请求】
如果设备收到个ARP请求,发现请求的就是自己的MAC,首先把对方的IP和MAC映射放到自己的ARP表项中,然后填好ARP应答后,单播给发送ARP请求的
设备。
【接收到ARP应答】
这个很简单了,收到了ARP应答就把对方的IP和MAC地址映射表存入自己的ARP表项即可
====ARP帧格式====
下面讲一下ARP的帧格式:
ARP帧由14字节的以太网首部和28字节的ARP头组成。
----以太网头部解释----
这个比较简单,就是目的MAC,源MAC,以及以太帧中封装的三层报文类型,如果是ip报文,就是0x0800, ARP报文的话,就是0x0806
----ARP头部解释----
硬件类型:以太网地址用1表示;
协议类型:字段表示要映射的协议地址类型它的值为 0 x 0 8 0 0即表示I P地址;
下面两个字节是硬件地址长度和协议地址长度,分别为6字节和4字节;
OP为操作类型,1表示ARP请求,2表示ARP应答;
对于ARP请求来说,除了目的以太网地址,其他的信息都要填充(因为ARP请求就是要获取目的MAC地址)。当目的端收到ARP请求后,目的端把自己的MAC地址填入此报文中,然后把发送地址换成自己的地址(包括MAC和IP),并把OP位置为2(即表示ARP应答),然后发送出去。
====uip中ARP报文的结构体====
uip中的arp基本都放在uip_arp.h和uip_arp.c中
主要包含以下函数接口:
/*-----------------------------------------------------------------------------------*/
/**
* Periodic ARP processing function.
*
* This function performs periodic timer processing in the ARP module
* and should be called at regular intervals. The recommended interval
* is 10 seconds between the calls.
* 每10s就需要被main函数调用一次,在ARP老化后把表项清零
*/
/*-----------------------------------------------------------------------------------*/
void uip_arp_timer(void);
/* 收到ip报文或者ARP报文就可能调用此函数,更新ARP表项*/
static void
uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
/*-----------------------------------------------------------------------------------*/
/**
* ARP processing for incoming IP packets
*
* This function should be called by the device driver when an IP
* packet has been received. The function will check if the address is
* in the ARP cache, and if so the ARP cache entry will be
* refreshed. If no ARP cache entry was found, a new one is created.
*
* This function expects an IP packet with a prepended Ethernet header
* in the uip_buf[] buffer, and the length of the packet in the global
* variable uip_len.
*
* 收到IP报文也需要更新ARP表项
*/
/*-----------------------------------------------------------------------------------*/
void uip_arp_ipin(void)
/*-----------------------------------------------------------------------------------*/
/**
* ARP processing for incoming ARP packets.
*
* This function should be called by the device driver when an ARP
* packet has been received. The function will act differently
* depending on the ARP packet type: if it is a reply for a request
* that we previously sent out, the ARP cache will be filled in with
* the values from the ARP reply. If the incoming ARP packet is an ARP
* request for our IP address, an ARP reply packet is created and put
* into the uip_buf[] buffer.
*
* When the function returns, the value of the global variable uip_len
* indicates whether the device driver should send out a packet or
* not. If uip_len is zero, no packet should be sent. If uip_len is
* non-zero, it contains the length of the outbound packet that is
* present in the uip_buf[] buffer.
*
* This function expects an ARP packet with a prepended Ethernet
* header in the uip_buf[] buffer, and the length of the packet in the
* global variable uip_len.
*
* 收到ARP报文,不管是请求报文还是应答报文,做出相应的处理
*/
/*-----------------------------------------------------------------------------------*/
void uip_arp_arpin(void)
/*-----------------------------------------------------------------------------------*/
/**
* Prepend Ethernet header to an outbound IP packet and see if we need
* to send out an ARP request.
*
* This function should be called before sending out an IP packet. The
* function checks the destination IP address of the IP packet to see
* what Ethernet MAC address that should be used as a destination MAC
* address on the Ethernet.
*
* If the destination IP address is in the local network (determined
* by logical ANDing of netmask and our IP address), the function
* checks the ARP cache to see if an entry for the destination IP
* address is found. If so, an Ethernet header is prepended and the
* function returns. If no ARP cache entry is found for the
* destination IP address, the packet in the uip_buf[] is replaced by
* an ARP request packet for the IP address. The IP packet is dropped
* and it is assumed that they higher level protocols (e.g., TCP)
* eventually will retransmit the dropped packet.
*
* If the destination IP address is not on the local network, the IP
* address of the default router is used instead.
*
* When the function returns, a packet is present in the uip_buf[]
* buffer, and the length of the packet is in the global variable
* uip_len.
*
* 主动发送ARP请求
*/
/*-----------------------------------------------------------------------------------*/
void uip_arp_out(void)