fix: rewrite PCAP backend for correct bridged networking#1777
Merged
midwan merged 1 commit intoBlitterStudio:masterfrom Feb 11, 2026
Merged
fix: rewrite PCAP backend for correct bridged networking#1777midwan merged 1 commit intoBlitterStudio:masterfrom
midwan merged 1 commit intoBlitterStudio:masterfrom
Conversation
Fix five bugs in the PCAP networking backend that prevented the A2065 (Am7990 LANCE) emulation from working on Linux bridge interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
midwan
approved these changes
Feb 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The PCAP networking backend has five bugs that prevent the A2065 (Am7990 LANCE) emulation from working correctly, particularly on Linux bridge interfaces. With the worker thread deadlock (#1773) and config parsing (#1774) already fixed, these are the remaining issues needed to make PCAP bridged networking fully functional.
The Problems
1.
uaenet_trigger()never transmitsuaenet_trigger()is called by the A2065 emulation when the Am7990 has a packet to send. Instead of actually transmitting, it postsqueue_available— a semaphore used for receive processing. No packet is ever retrieved from the transmit ring buffer or sent via pcap.Before:
Fix: Rewrite
uaenet_trigger()to callgetfunc()(which retrieves the packet from the Am7990 transmit ring buffer) followed bypcap_sendpacket().2.
gotfunc()called from wrong thread (race condition)The worker thread called
uaenet_checkpacket()→gotfunc()→gotfunc2(), which writes directly to Am7990 chip state (csr[],boardram[], interrupt registers). These are also accessed by the emulation thread with no synchronization, causing data corruption and missed interrupts.Fix: Move packet delivery to the emulation thread. The worker thread now only queues received packets. A new
uaenet_receive_poll()function, called froma2065_hsync_handler()on the emulation thread, dequeues and delivers them viagotfunc(). This follows the single-producer/single-consumer pattern — the worker thread produces (enqueues), the emulation thread consumes (dequeues and delivers).3.
uaenet_close()is a no-opuaenet_close()searchesuaenet_data[]for a matching pointer, butuaenet_data[]is never populated —uaenet_open()allocates the array but never stores anything in it. The loop finds no match, so the pcap handle and worker thread are leaked on every chip reinit.Before:
Fix: Call
uaenet_close_driver_internal()directly. Remove the never-populateduaenet_data[]array,uaenet_count, andqueue_availablesemaphore (dead code). Don'txfree(ud)— the caller (a2065.cpp) owns thesysdatabuffer. Add a re-open guard inuaenet_open()that cleanly shuts down any existing state before reinitializing.4. Non-promiscuous mode drops all unicast on bridge interfaces
pcap_open_live()was called with thepromiscuousparameter from the caller, which is 0 for normal operation. On a Linux bridge interface, the bridge has its own MAC address (e.g.,de:91:f6:91:1a:eb) which differs from the emulated NIC's MAC (00:80:10:00:00:00). Without promiscuous mode, the kernel only delivers frames addressed to the bridge's own MAC — unicast frames to the Amiga's MAC are silently discarded before reaching the pcap socket.This bug was particularly difficult to diagnose because
tcpdumptemporarily enables promiscuous mode on the interface while it runs, so the emulated NIC would appear to work whenever diagnostic capture was active.Fix: Always open pcap in promiscuous mode. The BPF filter (see below) already restricts capture to relevant packets, so promiscuous mode does not cause excessive CPU usage.
5.
pcap_setdirection(PCAP_D_IN)drops broadcast/multicast on bridgesThe original code used
pcap_setdirection(PCAP_D_IN)to filter out transmitted packets. On Linux bridge interfaces, the kernel classifies broadcast and multicast frames as "outgoing" even when they arrive from the network, soPCAP_D_INsilently drops them all — ARP, DHCP, and any broadcast/multicast traffic never reaches the emulated NIC.Fix: Replace
pcap_setdirection()with a BPF source-exclusion filter:This accepts all frames destined to the Amiga (unicast, broadcast, multicast) while rejecting transmit loopback, without relying on the kernel's direction classification.
Bonus: Semaphore inflation on re-open
uae_sem_init()on an already-initialized semaphore callsSDL_SemPost()instead of recreating it. Whenuaenet_open()is called a second time (chip reinit),queue_semgoes from value 1 to 2, breaking its use as a mutex.Fix: Call
uae_sem_destroy()beforeuae_sem_init()on re-open.Files Changed
src/osdep/amiberry_uaenet.cpp— All backend fixes: transmit rewrite, receive poll, close fix, re-open guard, semaphore fix, promiscuous mode, BPF filter, dead code removalsrc/a2065.cpp— Callethernet_receive_poll()froma2065_hsync_handler()for thread-safe packet deliverysrc/ethernet.cpp— Addethernet_receive_poll()dispatch functionsrc/include/ethernet.h— Addethernet_receive_poll()declarationsrc/osdep/amiberry_uaenet.h— Adduaenet_receive_poll()declarationTesting
Tested on Debian 13 (kernel 6.12) with an emulated A2065 NIC using PCAP on a Linux bridge interface (
br0). The bridge connects the host to a VLAN where the Amiga gets a real IP via DHCP.All tests pass:
🤖 Generated with Claude Code