arp updated again

This commit is contained in:
2025-11-20 15:52:41 +08:00
parent e909592496
commit be42c9a816
5 changed files with 77 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
#include <string.h>
#include <stdio.h>
#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);
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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