这几天一直看LWIP,知道今天才看完ETHARP.C,其实和我以前看的一位南开的老师写的差不多,就是比那个复杂了点。
本来想看1.3呢,但是我觉得1.3太乱了,本人能力有限就选择了0.72了。下面是我看etharp.c的一点体会,总结一下了。
这个c文件有个相对应的.h文件etharp.h
定义了ARP协议的头及IP协议的头,一些和arp有关的函数:
void etharp_init(void); 初始化ARP
void etharp_tmr(void); 随着时钟节拍,更新entry 的状态
struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
从ip输入中提取ARP
struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
struct pbuf *p); ARP输入
struct pbuf *etharp_output(struct netif *netif, struct ip_addr *ipaddr,
struct pbuf *q); ARP输出返回能输出的包
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
ARP查询
//供内部
static s8_t find_arp_entry(void)//返回一个最有理由的ARPentry,不是过期了就是空的
static struct pbuf * update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);当在ip_input()或arp_input()函数中调用,也就是当在前两种情况里捕捉到了entry时更新ARP表
当然主要就是介绍这些函数了。
在介绍函数之前,还有几个结构体要说明一下:
一个是:entry:
struct etharp_entry {
struct ip_addr ipaddr; //ip
struct eth_addr ethaddr; //mac
enum etharp_state state; //状态即下面要说的
#if ARP_QUEUEING
struct pbuf *p; //更新entry 的包,在update()等函数中都有用哦,其实//可以不用
#endif
u8_t ctime; //有效时间
};
一个是:ARP表的entry的状态有三:EMPTY,PENDING,STABLE即空的,未确定的,稳定的
空的就是这个entry还没用;未确定的就是entry中只有ip没有mac,等着去更新呢,用更新包;稳定的就是都有了的
下面具体介绍函数了:
1、 初始化函数:把状态置为EMPTY,然后把CTIME = 0。
2、etharp_tmr(),节拍更新函数,随着时钟节拍,更新entry 的状态,如ctime ++;当过期了状态就成EMPTY了
3、ip_input():在arp表里维护的是最近刚用的ip_mac地址entry,从输入的ip包中更新arp这个函数就是这样,当这个包被送往ip层之前一定要把ip_mac取出来,更新表
4、arp_input():在里面也需要调用arp_update()函数来更新ARP表;当我们接受到arp输入时有两种情况:一、别人要我们的mac,我们必须发给他;二、我们要别人的mac,别人给咱发过来了,因为一上来就用这次接受的信息更新了ARP表了所以这时就不在更新了
5、arp_output():有可能是广播,组播,单播,如果有mac地址,就把这个能发出去的包返回;如果没有的话,就得调用下一个函数etharp_query()了
6、etharp_query():查询ARP
不管ARP表中有没有要查询的ip_addr的记录,pbuf *q总要进入arp_table[i]队列,
关于什么时候发request,程序有两个选择:一、用户想在一个稳定的entry里发ip包,所以想在arp_update函数中发送ip包,这时entry得到了更新,是一个稳定的了;二、立即发ARP_REQUEST,立即得到entry;
程序好像选了前者,不过我认为后者挺好的啊
就是ARP表里已经有ip,但没mac,也就是未确定的,当调用arp_update()时,更新entry自然有了mac,这个mac是在ip_input() 或 arp_input()中提取的,这时再发ip包;
立即发就是立即发arp包,然后获得mac地址,在发ip包
下边两个是供内部使用的函数:
find_arp_entry(void)//返回一个最有理由的ARPentry,不是过期了就是空的
arp_update():供内部
更新ARP表,参数提供ip,mac的entry,如果表中有ip,则更新mac地址,并把pbuf中的ip包发出去
如果没有,能插入则插入这个entry.