arp updated again
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user