From d6d9c368e91c541a68eb1bdb697d38a85ba4fcf6 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:55:37 +0200 Subject: [PATCH] Refresh ARP entries from incoming IP traffic uip_arp_ipin() is an empty macro with its body under #if 0, both inherited from the uIP import and untouched since. That leaves uip_arp_update() reachable only from uip_arp_arpin(), so an entry is refreshed only by ARP addressed to us and ages out after UIP_ARP_MAXAGE no matter how much traffic passed over it. When it goes, the next transmission to that host hits the miss path of uip_arp_out(), which overwrites the packet in uip_buf with an ARP request and returns. For TCP that costs a retransmission. For UDP nothing retransmits, and handle_tx() sends the UDP connections through uip_arp_out() too, so the datagram is lost. The body could not be enabled as written: uip_len -= sizeof(struct uip_eth_hdr) is a leftover from when UIP_LLH_LEN was 0. Here it is ETHER_HEADER_SIZE + RTL_FRAME_DESC_SIZE and uip.c reads the IP header at uip_buf[UIP_LLH_LEN], so uip_len has to keep the link layer in it. The rest of the function is sound. --- rtlplayground.c | 2 +- uip/uip_arp.c | 6 +----- uip/uip_arp.h | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/rtlplayground.c b/rtlplayground.c index 700df0b8..6d88e145 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1252,7 +1252,7 @@ void handle_rx(void) } } else if (ETH_IN->ether_type == HTONS(0x0800)) { // IPv4 if (!management_vlan || management_vlan == rx_packet_vlan) { - uip_arp_ipin(); // Learn MAC addresses in TCP packets + uip_arp_ipin(); uip_input(); if (uip_len) { // Add ethernet frame diff --git a/uip/uip_arp.c b/uip/uip_arp.c index 44bee6c4..42d48213 100644 --- a/uip/uip_arp.c +++ b/uip/uip_arp.c @@ -239,12 +239,9 @@ uip_arp_update(__xdata u16_t * __xdata ipaddr, __xdata struct uip_eth_addr * __x * variable uip_len. */ /*-----------------------------------------------------------------------------------*/ -#if 0 void -uip_arp_ipin(void) +uip_arp_ipin(void) __banked { - uip_len -= sizeof(struct uip_eth_hdr); - /* Only insert/update an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ if((IPBUF->srcipaddr[0] & uip_netmask[0]) != @@ -259,7 +256,6 @@ uip_arp_ipin(void) return; } -#endif /* 0 */ /*-----------------------------------------------------------------------------------*/ /** * ARP processing for incoming ARP packets. diff --git a/uip/uip_arp.h b/uip/uip_arp.h index 833d7c22..57930979 100644 --- a/uip/uip_arp.h +++ b/uip/uip_arp.h @@ -78,8 +78,7 @@ void uip_arp_init(void) __banked; inserts a new mapping if none exists. The function assumes that an IP packet with an Ethernet header is present in the uip_buf buffer and that the length of the packet is in the uip_len variable. */ -/*void uip_arp_ipin(void);*/ -#define uip_arp_ipin() +void uip_arp_ipin(void) __banked; /* The uip_arp_arpin() should be called when an ARP packet is received by the Ethernet driver. This function also assumes that the