arp updated again
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include "xarp.h"
|
#include "xarp.h"
|
||||||
#include "xnet_tiny.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 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))
|
#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) {
|
void xarp_init(void) {
|
||||||
for (int i = 0; i < XARP_CACHE_SIZE; i++) {
|
for (int i = 0; i < XARP_CACHE_SIZE; i++) {
|
||||||
arp_table[i].state = XARP_ENTRY_STATE_FREE;
|
arp_table[i].state = XARP_ENTRY_STATE_FREE;
|
||||||
@@ -19,6 +36,15 @@ void xarp_init(void) {
|
|||||||
arp_table[i].tmo = 0;
|
arp_table[i].tmo = 0;
|
||||||
arp_table[i].retry_count = 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) {
|
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) {
|
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);
|
xarp_entry_t *entry = find_entry(ip_addr, force);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
memcpy(entry->ip_addr, ip_addr, 4);
|
memcpy(entry->ip_addr, ip_addr, 4);
|
||||||
memcpy(entry->mac_addr, mac_addr, XNET_MAC_ADDR_SIZE);
|
memcpy(entry->mac_addr, mac_addr, XNET_MAC_ADDR_SIZE);
|
||||||
entry->state = XARP_ENTRY_STATE_RESOLVED;
|
if (entry->state != XARP_ENTRY_STATE_RESOLVED) {
|
||||||
entry->tmo = 0; // Reset timeout
|
entry->state = XARP_ENTRY_STATE_RESOLVED;
|
||||||
entry->retry_count = 0; // Reset retry count
|
entry->tmo = XARP_STABLE_TMO_MS;
|
||||||
|
}
|
||||||
|
entry->retry_count = 0;
|
||||||
|
|
||||||
|
xarp_dump_table();
|
||||||
|
|
||||||
if (entry->packet) {
|
if (entry->packet) {
|
||||||
ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, 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)) {
|
(arp_packet->pro_len != 4)) {
|
||||||
return;
|
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);
|
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);
|
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.
|
* @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.
|
* 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++) {
|
for (int i = 0; i < XARP_CACHE_SIZE; i++) {
|
||||||
xarp_entry_t *entry = &arp_table[i];
|
xarp_entry_t *entry = &arp_table[i];
|
||||||
|
|
||||||
if (entry->state == XARP_ENTRY_STATE_PENDING) {
|
if (entry->state == XARP_ENTRY_STATE_FREE) {
|
||||||
entry->tmo -= XNET_POLL_CYCLE_MS; // Assuming XNET_POLL_CYCLE_MS is defined elsewhere as the poll interval
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry->tmo <= 0) {
|
if (xnet_check_tmo(&entry->tmo)) {
|
||||||
if (entry->retry_count > 0) {
|
if (entry->state == XARP_ENTRY_STATE_PENDING) {
|
||||||
entry->retry_count--;
|
if (entry->retry_count-- > 0) {
|
||||||
entry->tmo = XARP_TIMEOUT_MS; // Reset timeout for retransmission
|
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);
|
send_arp_request(entry->ip_addr);
|
||||||
} else {
|
} 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
|
// No more retries, give up and free the packet
|
||||||
if (entry->packet) {
|
if (entry->packet) {
|
||||||
xnet_free_packet(entry->packet);
|
xnet_free_packet(entry->packet);
|
||||||
entry->packet = (xnet_packet_t *)0;
|
entry->packet = (xnet_packet_t *)0;
|
||||||
}
|
}
|
||||||
entry->state = XARP_ENTRY_STATE_FREE;
|
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
|
// ARP configuration
|
||||||
#define XARP_RETRY_COUNT 3 // Number of ARP retransmissions
|
#define XARP_RETRY_COUNT 3 // Number of ARP retransmissions
|
||||||
#define XARP_TIMEOUT_MS 1000 // ARP timeout in milliseconds (1 second)
|
#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 {
|
typedef enum _xarp_state_t {
|
||||||
XARP_ENTRY_STATE_FREE,
|
XARP_ENTRY_STATE_FREE,
|
||||||
XARP_ENTRY_STATE_RESOLVED,
|
XARP_ENTRY_STATE_RESOLVED,
|
||||||
XARP_ENTRY_STATE_PENDING,
|
XARP_ENTRY_STATE_PENDING,
|
||||||
|
XARP_ENTRY_STATE_STABLE,
|
||||||
} xarp_state_t;
|
} xarp_state_t;
|
||||||
|
|
||||||
typedef struct _xarp_entry_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);
|
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_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_poll(void); // Declaration for the new periodic poll function
|
||||||
|
void xarp_send_gratuitous(void);
|
||||||
|
|
||||||
#endif // XARP_H
|
#endif // XARP_H
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
#define XLOG_LEVEL_WARNING 2
|
#define XLOG_LEVEL_WARNING 2
|
||||||
#define XLOG_LEVEL_INFO 3
|
#define XLOG_LEVEL_INFO 3
|
||||||
|
|
||||||
#ifndef XLOG_LEVEL
|
#ifndef XLOG_LEVEL_DEFAULT
|
||||||
#define XLOG_LEVEL XLOG_LEVEL_ERROR
|
#define XLOG_LEVEL_DEFAULT XLOG_LEVEL_INFO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XLOG_LEVEL >= XLOG_LEVEL_INFO
|
#if XLOG_LEVEL >= XLOG_LEVEL_INFO
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ const uint8_t * get_netif_mac(void) {
|
|||||||
return netif_mac;
|
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 数据空间大小
|
* @param data_size 数据空间大小
|
||||||
@@ -85,6 +93,7 @@ static xnet_err_t ethernet_init (void) {
|
|||||||
xnet_err_t err = xnet_driver_open(netif_mac);
|
xnet_err_t err = xnet_driver_open(netif_mac);
|
||||||
if (err < 0) return err;
|
if (err < 0) return err;
|
||||||
|
|
||||||
|
xarp_send_gratuitous();
|
||||||
return XNET_ERR_OK;
|
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);
|
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);
|
const uint8_t * get_netif_mac(void);
|
||||||
|
|
||||||
|
int xnet_check_tmo(int *tmo);
|
||||||
|
|
||||||
extern const uint8_t my_ip_addr[];
|
extern const uint8_t my_ip_addr[];
|
||||||
|
|
||||||
#endif // XNET_TINY_H
|
#endif // XNET_TINY_H
|
||||||
|
|||||||
Reference in New Issue
Block a user