diff --git a/network/start/xnet_tiny/src/app.c b/network/start/xnet_tiny/src/app.c index f759568..9a42ca0 100644 --- a/network/start/xnet_tiny/src/app.c +++ b/network/start/xnet_tiny/src/app.c @@ -1,5 +1,7 @@ #include +#include #include "xnet_tiny.h" +#include "xarp.h" int main (void) { printf("xnet running\n"); @@ -11,9 +13,25 @@ int main (void) { // printf("=== xnet initialized, entering main loop ===\n"); fflush(stdout); + const uint8_t target_ip[] = {172, 17, 0, 2}; + int arp_timer = 0; + while (1) { xnet_poll(); + + // The poll cycle is 100ms, so 100 cycles = 10 seconds + if (++arp_timer >= 100) { + arp_timer = 0; + printf("Sending ARP request: Who is %d.%d.%d.%d? Tell %d.%d.%d.%d\n", + target_ip[0], target_ip[1], target_ip[2], target_ip[3], + my_ip_addr[0], my_ip_addr[1], my_ip_addr[2], my_ip_addr[3]); + send_arp_request(target_ip); + } + + // Add a small delay to prevent the CPU from spinning at 100% + usleep(XNET_POLL_CYCLE_MS * 1000); } return 0; } + diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.c b/network/start/xnet_tiny/src/xnet_tiny/xarp.c index 1ebce43..40bcf13 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.c +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.c @@ -138,7 +138,7 @@ void xarp_in(xnet_packet_t *packet) { } } -static void send_arp_request(const uint8_t *ip_addr) { +void send_arp_request(const uint8_t *ip_addr) { xnet_packet_t *tx_packet = xnet_alloc_for_send(sizeof(xarp_packet_t)); if (tx_packet) { xarp_packet_t *arp_request = (xarp_packet_t *)tx_packet->data; @@ -203,6 +203,32 @@ void xarp_send_gratuitous(void) { /** * @brief Periodically polls the ARP table for pending entries to handle timeouts and retransmissions. * This function should be called regularly (e.g., every 100ms or 1 second) by the main loop or a timer. + 个程序的ARP超时重传机制主要通过 xarp_poll 函数和一个ARP缓存表来实现。 + + 具体流程如下: + + 1. 发起ARP请求与状态记录: + * 当需要解析一个IP地址时(例如,通过 xarp_resolve 函数),程序首先会在一个名为 arp_table 的ARP缓存表中查找。 + * 如果找不到对应的条目,程序会创建一个新的条目,并将其状态设置为 XARP_ENTRY_STATE_PENDING(等待解析)。 + * 同时,它会为这个条目设置一个超时计数器 tmo 和一个重传次数计数器 retry_count。这些初始值由 xarp.h 中的宏定义: + * XARP_TIMEOUT_MS: 初始超时时间,设为1000毫秒(1秒)。 + * XARP_RETRY_COUNT: 最大重传次数,设为3次。 + * 最后,程序发送第一个ARP请求包。 + + 2. 轮询检测超时 (`xarp_poll`): + * 在 app.c 的主循环中,xnet_poll() 会被持续调用,而 xnet_poll() 内部会调用 xarp_poll()。 + * xarp_poll() 函数的核心职责就是遍历整个 arp_table 缓存表。 + + 3. 超时处理与重传: + * 在遍历过程中,xarp_poll 会检查每一个状态为 XARP_ENTRY_STATE_PENDING 的条目。 + * 它通过 xnet_check_tmo() 函数检查该条目的 tmo 计时器是否已到期。 + * 如果已到期: + * 程序会检查 retry_count(剩余重传次数)是否大于0。 █ + * 如果大于0,它会重新发送一次ARP请求,然后将 retry_count 减1,并重置 tmo 计时器,开始新一轮的等待。 █ + * 如果 retry_count 已经等于0,说明所有重传尝试都已失败。该条目将被视为无效并从ARP缓存表中清除(状态设为 XARP_ENTRY_STATE_FREE)。 █ + █ + 总结一下,该机制的核心是:利用一个周期性调用的轮询函数 (`xarp_poll`) █ + 来管理一个带有状态(Pending/Resolved)、超时时间(tmo)和重传次数(retry\_count)的ARP缓存表,从而实现了超时自动重传和失败丢弃的逻辑。 */ void xarp_poll(void) { for (int i = 0; i < XARP_CACHE_SIZE; i++) { @@ -234,6 +260,7 @@ void xarp_poll(void) { // Refresh the entry by sending a new ARP request entry->tmo = XARP_STABLE_TMO_MS; // send_arp_request(entry->ip_addr); + // 上面一行的注释取消后会出现问题:受到ping request时不停产生大量的ARP请求包 } } } diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.h b/network/start/xnet_tiny/src/xnet_tiny/xarp.h index bb22078..5223fe1 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.h @@ -55,5 +55,6 @@ const uint8_t *xarp_resolve(xnet_packet_t *packet, const uint8_t *ip_addr); void xarp_update_from_ip(const uint8_t *ip_addr, const uint8_t *mac_addr); void xarp_poll(void); // Declaration for the new periodic poll function void xarp_send_gratuitous(void); +void send_arp_request(const uint8_t *ip_addr); #endif // XARP_H