From be42c9a816b24c4ac4c6b0b69efd888136c0853b Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Thu, 20 Nov 2025 15:52:41 +0800 Subject: [PATCH] arp updated again --- network/start/xnet_tiny/src/xnet_tiny/xarp.c | 69 ++++++++++++++++--- network/start/xnet_tiny/src/xnet_tiny/xarp.h | 3 + network/start/xnet_tiny/src/xnet_tiny/xlog.h | 4 +- .../start/xnet_tiny/src/xnet_tiny/xnet_tiny.c | 9 +++ .../start/xnet_tiny/src/xnet_tiny/xnet_tiny.h | 2 + 5 files changed, 77 insertions(+), 10 deletions(-) diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.c b/network/start/xnet_tiny/src/xnet_tiny/xarp.c index 2f37c8e..1ebce43 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.c +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.c @@ -1,4 +1,5 @@ #include +#include #include "xarp.h" #include "xnet_tiny.h" @@ -10,8 +11,24 @@ static const uint8_t net_broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF static xarp_entry_t arp_table[XARP_CACHE_SIZE]; +static xarp_entry_t *find_entry(const uint8_t *ip_addr, int force); + #define swap_order16(v) ((((v) & 0xFF) << 8) | (((v) >> 8) & 0xFF)) +static void xarp_dump_table(void) { + printf("ARP table:\n"); + for (int i = 0; i < XARP_CACHE_SIZE; i++) { + xarp_entry_t *entry = &arp_table[i]; + if (entry->state != XARP_ENTRY_STATE_FREE) { + printf("Entry %d: IP %d.%d.%d.%d, MAC %02x:%02x:%02x:%02x:%02x:%02x, State: %s\n", + i, + entry->ip_addr[0], entry->ip_addr[1], entry->ip_addr[2], entry->ip_addr[3], + entry->mac_addr[0], entry->mac_addr[1], entry->mac_addr[2], entry->mac_addr[3], entry->mac_addr[4], entry->mac_addr[5], + (entry->state == XARP_ENTRY_STATE_RESOLVED) ? "RESOLVED" : "PENDING"); + } + } +} + void xarp_init(void) { for (int i = 0; i < XARP_CACHE_SIZE; i++) { arp_table[i].state = XARP_ENTRY_STATE_FREE; @@ -19,6 +36,15 @@ void xarp_init(void) { arp_table[i].tmo = 0; arp_table[i].retry_count = 0; } + + // Add a permanent entry for myself + xarp_entry_t *entry = find_entry(my_ip_addr, 1); + if (entry) { + memcpy(entry->ip_addr, my_ip_addr, 4); + memcpy(entry->mac_addr, get_netif_mac(), XNET_MAC_ADDR_SIZE); + entry->state = XARP_ENTRY_STATE_RESOLVED; + entry->tmo = 0; // Never expires + } } static xarp_entry_t *find_entry(const uint8_t *ip_addr, int force) { @@ -40,13 +66,21 @@ static xarp_entry_t *find_entry(const uint8_t *ip_addr, int force) { } static void update_entry(const uint8_t *ip_addr, const uint8_t *mac_addr, int force) { + printf("update arp entry: ip: %d.%d.%d.%d, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + xarp_entry_t *entry = find_entry(ip_addr, force); if (entry) { memcpy(entry->ip_addr, ip_addr, 4); memcpy(entry->mac_addr, mac_addr, XNET_MAC_ADDR_SIZE); - entry->state = XARP_ENTRY_STATE_RESOLVED; - entry->tmo = 0; // Reset timeout - entry->retry_count = 0; // Reset retry count + if (entry->state != XARP_ENTRY_STATE_RESOLVED) { + entry->state = XARP_ENTRY_STATE_RESOLVED; + entry->tmo = XARP_STABLE_TMO_MS; + } + entry->retry_count = 0; + + xarp_dump_table(); if (entry->packet) { ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, entry->packet); @@ -73,6 +107,10 @@ void xarp_in(xnet_packet_t *packet) { (arp_packet->pro_len != 4)) { return; } + printf("arp in: op: %d, sender ip: %d.%d.%d.%d, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + swap_order16(arp_packet->oper), + arp_packet->send_ip[0], arp_packet->send_ip[1], arp_packet->send_ip[2], arp_packet->send_ip[3], + arp_packet->send_mac[0], arp_packet->send_mac[1], arp_packet->send_mac[2], arp_packet->send_mac[3], arp_packet->send_mac[4], arp_packet->send_mac[5]); update_entry(arp_packet->send_ip, arp_packet->send_mac, 1); @@ -157,6 +195,11 @@ void xarp_update_from_ip(const uint8_t *ip_addr, const uint8_t *mac_addr) { update_entry(ip_addr, mac_addr, 1); } +void xarp_send_gratuitous(void) { + printf("send gratuitous arp\n"); + send_arp_request(my_ip_addr); +} + /** * @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. @@ -165,22 +208,32 @@ void xarp_poll(void) { for (int i = 0; i < XARP_CACHE_SIZE; i++) { xarp_entry_t *entry = &arp_table[i]; - if (entry->state == XARP_ENTRY_STATE_PENDING) { - entry->tmo -= XNET_POLL_CYCLE_MS; // Assuming XNET_POLL_CYCLE_MS is defined elsewhere as the poll interval + if (entry->state == XARP_ENTRY_STATE_FREE) { + continue; + } - if (entry->tmo <= 0) { - if (entry->retry_count > 0) { - entry->retry_count--; + if (xnet_check_tmo(&entry->tmo)) { + if (entry->state == XARP_ENTRY_STATE_PENDING) { + if (entry->retry_count-- > 0) { entry->tmo = XARP_TIMEOUT_MS; // Reset timeout for retransmission + printf("arp req re-send: ip: %d.%d.%d.%d\n", + entry->ip_addr[0], entry->ip_addr[1], entry->ip_addr[2], entry->ip_addr[3]); send_arp_request(entry->ip_addr); } else { + printf("arp entry drop: ip: %d.%d.%d.%d\n", + entry->ip_addr[0], entry->ip_addr[1], entry->ip_addr[2], entry->ip_addr[3]); // No more retries, give up and free the packet if (entry->packet) { xnet_free_packet(entry->packet); entry->packet = (xnet_packet_t *)0; } entry->state = XARP_ENTRY_STATE_FREE; + xarp_dump_table(); } + } else if (entry->state == XARP_ENTRY_STATE_RESOLVED) { + // Refresh the entry by sending a new ARP request + entry->tmo = XARP_STABLE_TMO_MS; + // send_arp_request(entry->ip_addr); } } } diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.h b/network/start/xnet_tiny/src/xnet_tiny/xarp.h index bc64863..bb22078 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.h @@ -6,11 +6,13 @@ // ARP configuration #define XARP_RETRY_COUNT 3 // Number of ARP retransmissions #define XARP_TIMEOUT_MS 1000 // ARP timeout in milliseconds (1 second) +#define XARP_STABLE_TMO_MS (10 * 1000) // Refresh resolved entries every 10 seconds typedef enum _xarp_state_t { XARP_ENTRY_STATE_FREE, XARP_ENTRY_STATE_RESOLVED, XARP_ENTRY_STATE_PENDING, + XARP_ENTRY_STATE_STABLE, } xarp_state_t; typedef struct _xarp_entry_t { @@ -52,5 +54,6 @@ void xarp_in(xnet_packet_t *packet); 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); #endif // XARP_H diff --git a/network/start/xnet_tiny/src/xnet_tiny/xlog.h b/network/start/xnet_tiny/src/xnet_tiny/xlog.h index 61d4269..e834fd3 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xlog.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xlog.h @@ -8,8 +8,8 @@ #define XLOG_LEVEL_WARNING 2 #define XLOG_LEVEL_INFO 3 -#ifndef XLOG_LEVEL -#define XLOG_LEVEL XLOG_LEVEL_ERROR +#ifndef XLOG_LEVEL_DEFAULT +#define XLOG_LEVEL_DEFAULT XLOG_LEVEL_INFO #endif #if XLOG_LEVEL >= XLOG_LEVEL_INFO diff --git a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c index 4de1866..db510d0 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c +++ b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c @@ -20,6 +20,14 @@ const uint8_t * get_netif_mac(void) { return netif_mac; } +int xnet_check_tmo(int *tmo) { + if (*tmo <= 0) { + return 0; // Already expired, or not set + } + *tmo -= XNET_POLL_CYCLE_MS; + return *tmo <= 0; +} + /** * 分配一个网络数据包用于发送数据 * @param data_size 数据空间大小 @@ -85,6 +93,7 @@ static xnet_err_t ethernet_init (void) { xnet_err_t err = xnet_driver_open(netif_mac); if (err < 0) return err; + xarp_send_gratuitous(); return XNET_ERR_OK; } diff --git a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h index 5cf4aac..0df17b5 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h @@ -55,6 +55,8 @@ void remove_header(xnet_packet_t *packet, uint16_t header_size); xnet_err_t ethernet_out_to(xnet_protocol_t protocol, const uint8_t *mac_addr, xnet_packet_t * packet); const uint8_t * get_netif_mac(void); +int xnet_check_tmo(int *tmo); + extern const uint8_t my_ip_addr[]; #endif // XNET_TINY_H