On Sun, Oct 18, 2026 at 07:03:37PM -0400, Greg Troxel wrote: > Bill Green <[email protected]> writes: > > > I tracked it down at the time to the packet-queuing logic in > > tun_output() (if_tun.c:590) and have been carrying forward a local > > patch that simply deletes the line that sets `error = EAFNOSUPPORT` > > (at if_tun.c:632 in netbsd-11 and current). > > > > According to the notes that I wrote up then, that assignment ended up > > overwriting the actual error that was happening (ENOBUFS, set by the > > IFQ_ENQUEUE macro, which doesn't occur even for AF_INET and AF_INET6 > > until after falling through to the AF_UNSPEC case). That is, the > > actual problem was that the output buffer was filling up (which rsync > > etc. should handle), but because the AF_UNSPEC path (again, which the > > AF_INET(6) paths fall through to as well) unconditionally sets > > EAFNOSUPPORT that ends up getting given to userspace in errno instead, > > confusing rsync (and anyone reading the logs). > > > > Indeed patching that line out solved my rsync issue, but I wasn't > > confident that there weren't other potential paths I didn't > > understand: as I recall from looking into the CVS history it's been > > that way for a very long time (20+ years), so it seemed odd for it > > never to have bitten anyone else before. > > That's a great analysis. I read the code and I think you're right, but > error paths are tricky. > > This was added by pk@ in 2004. The revisions to look at (side by > side, don't try the diff) are 1.69 (before) and 1.70 (after). This was > in general an improvement in locking. > > Look at 1.69 L480 and 1.70 543. This is the switch on address family. > There's no v6, but the fallthrough to af_unspec is there. > This is 1.178 L590. > > In 1.69, the error from IFQ_ENQUEUE is just returned. > > In 1.70, it's overwritten, and then via "goto out;" (a normal BSD > networking style!). However, 0 is returned, not an error. > > In 1.178 (current), the error is returned. > > I conclude that the setting to EAFNOSUPPORT in 1.70, that has survived, > was a bug, and tat it didn't used to manifest because the error path > returned 0. Basically the packet is dropped, for some reason. > > > Now, we have error returns from tun_output. It seems that ENOBUFS, > presumably what IFQ_ENQUEUE returns when the queue is at limit, is a > normal response that the upper layer deals with. > > I think we should change: > > --- if_tun.c.~1.178.~ 2025-11-15 18:30:51.076488670 -0500 > +++ if_tun.c 2026-10-18 19:02:22.920287647 -0400 > @@ -629,7 +629,6 @@ tun_output(struct ifnet *ifp, struct mbu > IFQ_ENQUEUE(&ifp->if_snd, m0, error); > if (error) { > if_statinc(ifp, if_collisions); > - error = EAFNOSUPPORT; > m0 = NULL; > goto out; > } > > and will raise this on tech-net@ for more review.
For what it's worth, I've tested this patch on a 11.0_STABLE amd64 system, and it appears to fix the issue that I first reported. Throughput over Tailscale on NetBSD is dreadfully slow, though, but I can live with that, as it's outweighed by the benefits of being able to use the VPN at all. Regards, Andreas
