我在
LWIP手记【A】arp流程之典型情况一列举了4种ARP的情况。今天我读了etharp.C的注释。写到:
/*-----------------------------------------------------------------------------------------------------*/
/**
* @file
* Address Resolution Protocol module for IP over Ethernet
*
* Functionally, ARP is divided into two parts. The first maps an IP address
* to a physical address when sending a packet, and the second part answers
* requests from other machines for our physical address.
*
* This implementation complies with RFC 826 (Ethernet ARP). It supports
* Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
* if an interface calls etharp_gratuitous(our_netif) upon address change.
*/
/*-----------------------------------------------------------------------------------------------------*/
就是说LWIP的这个etharp.C主要实现两个功能,一个是发帧的时候IP需要映射个MAC地址。另一个功能是其他主机要求得到本地主机的MAC地址时,本地主机需要响应请求。
那么第二个功能似乎不在
LWIP手记【A】arp流程之典型情况一列举的4种ARP的情况“”之内啊!什么情况!先不管他。
好的,现在就弄个例子模拟一下第二种功能。
将单片机板卡重启后,用电脑发给单片机一个帧,抓图如下:
好现在就来分析一下上面这个过程。
现在打开ARP的调试功能如下
#define ETHARP_DEBUG LWIP_DBG_ON,
把这个过程抓图如下:
看了上面这个图片,是不是感觉迷糊?就是不知道哪个C文件打印的,也不知道第几行?
这是感觉LIWP的打印可以改造一下,原先的如下:
#define LWIP_PLATFORM_DIAG printf
#define LWIP_DEBUGF(debug, message) do {
if (
((debug) & LWIP_DBG_ON) &&
((debug) & LWIP_DBG_TYPES_ON) &&
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) {
LWIP_PLATFORM_DIAG message;
if ((debug) & LWIP_DBG_HALT) {
while(1);
}
}
} while(0)
改造如下:
#include "string.h"
#define LWIP_PLATFORM_DIAG printf
#define LWIP_DEBUGF(debug, message) do {
if (
((debug) & LWIP_DBG_ON) &&
((debug) & LWIP_DBG_TYPES_ON) &&
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) {
printf ((const char *)__FILE__+(strlen((const char *)__FILE__)-20));
printf (" %d ",__LINE__);
LWIP_PLATFORM_DIAG message;
if ((debug) & LWIP_DBG_HALT) {
while(1);
}
}
} while(0)
改造后,打印如下(把发生arp行为的前后几个不想关的帧也打截个图):
这样分析起来更清晰了点。
为什么要采用打印的方法(或者叫做断言),而不是用断点。因为断点有时候会不符合实际情况,可能是超时之类的。
尽管打印本身也会延时,但是是较小的延时。
把文章开头提到的所谓的“”第二个功能”的流程画个图,如下:
第二个功能的etharp_update_arp_entry这个函数内部没有调用etharp_send_ip这个函数。而是在跳出etharp_update_arp_entry这个函数后执行netif->linkoutput(netif, p);也就是执行low_level_output。
而第一个功能的etharp_update_arp_entry这个函数内部调用了etharp_send_ip这个函数。
区别就在这里。