🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
这个函数是ARP找到了IP地址与MAC地址对应的表项,从而能直接进行发送,除此之外,ARP还需要更新ARP表项,我们知道,LwIP中的ARP表项生存时间是5分钟(300秒),那么在APP表项的生存时间即将到来的时候,ARP需要更新表项,为什么要在发送数据的时候更新呢?因为如果不发送数据,那就没必要更新ARP表项,这样子表项在生存时间到来的时候就会被系统删除,回收ARP表项空间,而一直使用的ARP表项需要是谁更新,更新的方式也有两种: 如果ARP表项还差15秒就过期了,LwIP会通过广播的方式发送一个ARP请求包,试图得到主机的回应。 而如果ARP表项还差30秒就过期了,那么LwIP会通过单播的方式向目标主机发送一个请求包并试图得到回应。 在这种情况下发送ARP请求包的时候,表项的状态会由ETHARP\_STATE\_STABLE变成ETHARP\_STATE\_STABLE\_REREQUESTING\_1,如果目标主机回应了,那就更新ARP缓存表中的表项。 当然,如果还没那么快到期的话,那就直接调用ethernet\_output()函数将数据包传递给网卡进行发送。函数源码具体见代码清单 10‑12 ``` 1 #define ARP_MAXAGE 300 2 3 /* 即将到期的时间 */ 4 #define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) 5 #define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) 6 7 static err_t 8 etharp_output_to_arp_index(struct netif *netif, 9 struct pbuf *q, 10 netif_addr_idx_t arp_idx) 11 { 12 LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", 13 arp_table[arp_idx].state >= ETHARP_STATE_STABLE); 14 /* 如果arp表项即将过期:LwIP会重新请求它, 15 但只有当它的状态是ETHARP_STATE_STABLE才能请求*/ 16 if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) 17 { 18 /* 还差15秒到期 */ 19 if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) 20 { 21 /* 使用广播方式发出请求包 */ 22 if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) 23 { 24 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; 25 } 26 } 27 /* 还差30秒到期 */ 28 else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) 29 { 30 /* 发出单播请求(持续15秒),以防止不必要的广播 */ 31 if (etharp_request_dst(netif, 32 &arp_table[arp_idx].ipaddr, 33 &arp_table[arp_idx].ethaddr) == ERR_OK) 34 { 35 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; 36 } 37 } 38 } 39 40 return ethernet_output(netif, q, 41 (struct eth_addr *)(netif->hwaddr), 42 &arp_table[arp_idx].ethaddr, ETHTYPE_IP); 43 } ```