[Bug 296652] ARP replies from bridge are lost (?runt packet)
[email protected] Fri, 10 Jul 2026 03:10:10 +0000
| Newsgroups | gmane.os.freebsd.devel.net |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=296652 David Horn <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #1 from David Horn <[email protected]> --- Created attachment 272682 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=272682&action=edit Test fix to 15.1 sys/netinet/if_ether.c Please try attached patch against stable/15 (or 15.1) If it works, we can hopefully have ivy@ take a look and see if there are any other scenarios it does not cover. I tested with a vm and igb0 with and without bridge0 against 15.1 If the patch does not work, try building the kernel with INVARIANTS in the kernel config so we can see if the KASSERT(9) triggers from the patch (or other oddities) More background: arp: do not leave trailing mbufs attached to the ARP reply in_arpinput() turns the received request into a reply in place and shrinks it by assigning m_len and m_pkthdr.len. That fixes up the first mbuf and the packet header, but leaves any trailing mbufs of the chain attached, so the chain ends up longer than m_pkthdr.len claims. The if_bridge(4) input path is what produces such a chain. Before reinjecting a broadcast frame into the bridge ifnet, bridge_input() realigns it with m_copyup(mc2, min(mc2->m_pkthdr.len, max_protohdr), ETHER_ALIGN) and m_copyup() attaches whatever does not fit into the new head mbuf as m_next. max_protohdr is 60, so any ARP request longer than 60 bytes leaves a tail; requests are padded to the minimum Ethernet frame size and some senders pad further. The reply is then transmitted with m_pkthdr.len = 42 while the chain really holds 46 bytes. Drivers are entitled to trust m_pkthdr.len: iflib derives the transmit descriptor length from it, so the i210 is handed a length that disagrees with its DMA segment list and the frame never reaches the peer. re(4) instead pads short frames by 60 - m_pkthdr.len = 18 bytes and appends that to the real chain, yielding a 64-byte frame; this is why the failure is visible only with some NICs. Trim the surplus with m_adj() rather than merely assigning the lengths. A negative length truncates the chain to the requested size, frees the trailing mbufs and updates m_pkthdr.len, restoring the invariant m_pkthdr.len == sum(m_len). -- You are receiving this mail because: You are the assignee for the bug.