diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.c b/network/start/xnet_tiny/src/xnet_tiny/xarp.c index fc65224..2f37c8e 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.c +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.c @@ -8,21 +8,6 @@ static const uint8_t net_broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -typedef enum _xarp_state_t { - XARP_ENTRY_STATE_FREE, - XARP_ENTRY_STATE_RESOLVED, - XARP_ENTRY_STATE_PENDING, -} xarp_state_t; - -typedef struct _xarp_entry_t { - uint8_t ip_addr[4]; - uint8_t mac_addr[XNET_MAC_ADDR_SIZE]; - xarp_state_t state; - int tmo; - int retry; - xnet_packet_t *packet; -} xarp_entry_t; - static xarp_entry_t arp_table[XARP_CACHE_SIZE]; #define swap_order16(v) ((((v) & 0xFF) << 8) | (((v) >> 8) & 0xFF)) @@ -31,6 +16,8 @@ void xarp_init(void) { for (int i = 0; i < XARP_CACHE_SIZE; i++) { arp_table[i].state = XARP_ENTRY_STATE_FREE; arp_table[i].packet = (xnet_packet_t *)0; + arp_table[i].tmo = 0; + arp_table[i].retry_count = 0; } } @@ -58,6 +45,8 @@ static void update_entry(const uint8_t *ip_addr, const uint8_t *mac_addr, int fo 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->packet) { ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, entry->packet); @@ -136,6 +125,9 @@ const uint8_t *xarp_resolve(xnet_packet_t *packet, const uint8_t *ip_addr) { if (entry->state == XARP_ENTRY_STATE_RESOLVED) { return entry->mac_addr; } else if (entry->state == XARP_ENTRY_STATE_PENDING) { + // A packet is already pending for this IP, so store this new packet as well + // Or replace the old one if only one packet can be queued. + // For now, let's assume only one packet can be queued per pending ARP entry. if (entry->packet) { xnet_free_packet(entry->packet); } @@ -148,9 +140,12 @@ const uint8_t *xarp_resolve(xnet_packet_t *packet, const uint8_t *ip_addr) { entry->state = XARP_ENTRY_STATE_PENDING; memcpy(entry->ip_addr, ip_addr, 4); entry->packet = packet; + entry->tmo = XARP_TIMEOUT_MS; // Initialize timeout + entry->retry_count = XARP_RETRY_COUNT; // Initialize retry count send_arp_request(ip_addr); } else { + // ARP table full, free the packet xnet_free_packet(packet); } } @@ -161,3 +156,32 @@ 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) { update_entry(ip_addr, mac_addr, 1); } + +/** + * @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. + */ +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->tmo <= 0) { + if (entry->retry_count > 0) { + entry->retry_count--; + entry->tmo = XARP_TIMEOUT_MS; // Reset timeout for retransmission + send_arp_request(entry->ip_addr); + } else { + // 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; + } + } + } + } +} diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.h b/network/start/xnet_tiny/src/xnet_tiny/xarp.h index e8c4d1a..bc64863 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xarp.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xarp.h @@ -3,6 +3,25 @@ #include "xnet_tiny.h" +// ARP configuration +#define XARP_RETRY_COUNT 3 // Number of ARP retransmissions +#define XARP_TIMEOUT_MS 1000 // ARP timeout in milliseconds (1 second) + +typedef enum _xarp_state_t { + XARP_ENTRY_STATE_FREE, + XARP_ENTRY_STATE_RESOLVED, + XARP_ENTRY_STATE_PENDING, +} xarp_state_t; + +typedef struct _xarp_entry_t { + uint8_t ip_addr[4]; + uint8_t mac_addr[XNET_MAC_ADDR_SIZE]; + xarp_state_t state; + uint32_t tmo; // Timeout counter for pending entries + uint32_t retry_count; // Remaining retry attempts for pending entries + xnet_packet_t *packet; // Packet awaiting resolution +} xarp_entry_t; + #define XARP_HW_ETHER 1 // 硬件类型:以太网 #define XARP_PROTOCOL_IP 0x0800 // 协议类型:IP @@ -32,5 +51,6 @@ void xarp_init(void); 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 #endif // XARP_H 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 86324f8..4de1866 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c +++ b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c @@ -169,4 +169,5 @@ void xnet_init (void) { */ void xnet_poll(void) { ethernet_poll(); + xarp_poll(); // Call ARP poll to handle timeouts and retransmissions } 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 d925d04..5cf4aac 100644 --- a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h +++ b/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h @@ -1,16 +1,17 @@ -#ifndef XNET_TINY_H +#ifndef XNET_TINY_H #define XNET_TINY_H #include #define XNET_CFG_PACKET_MAX_SIZE 1516 // 收发数据包的最大大小 +#define XNET_POLL_CYCLE_MS 100 // Polling cycle in milliseconds, used by ARP and other modules #pragma pack(1) #define XNET_MAC_ADDR_SIZE 6 // MAC地址长度 /** - * 以太网数据帧格式:RFC894 + * 以太网数据帧格式:RFC894 */ typedef struct _xether_hdr_t { uint8_t dest[XNET_MAC_ADDR_SIZE]; // 目标mac地址