tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [Greg Troxel] Re: Getting "write: address family not supported by protocol family" when using Restic over Tailscale



On 2026-10-18 16:07, Greg Troxel wrote:
On netbsd-users@ while discussing a tailscale problem in a VM, Bill
Green spotted the bug.  I'd appreciate review and concurrence or telling
me why I'm wrong.  Message forwarded because I don't think crossposting
is ok.

Hello Greg and tech-net; I'm glad my message was helpful. Some further notes I had about this follow below.

 <...>

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 believe that the only values IFQ_ENQUEUE ever sets for error are ENOBUFS or 0; it sets ENOBUFS if IF_QFULL is true (checking whether the struct ifqueue's ifq_len >= ifq_maxlen). However IFQ_ENQUEUE is defined differently if altq is enabled; in this case the altq-aware version of IF_ENQUEUE uses ALTQ_ENQUEUE, which calls the altq_enqueue function whose pointer is stored in a struct ifaltq, setting error to the called function's return value (see sys/net/if.h:985-1003 and 1058-71 and sys/altq/if_altq.h:148, respectively).

Different altq classes have their own <class>_enqueue functions, but from what I can see each of these functions also only ever returns 0 for success or ENOBUFS. However I don't understand the altq code well at all. While in the default (non-altq) IFQ_ENQUEUE, the situation is straightforward (ENOBUFS means IF_QFULL was true), I wonder if ENOBUFS as an error might mean different things in the different altq classes (see for instance the comment at sys/altq/altq_jobs.c:602).

> 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.
>
> <...>
>
> 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;
>                      }
>

This did solve my issues with rsync transfers failing on my netbsd-10 systems and I haven't noticed any issues caused by it. But I wondered what the assignment of EAFNOSUPPORT as error here was originally intended to indicate. The default case of the switch in tun_output (i.e. none of AF_INET, AF_INET6, or AF_UNSPEC) is to set error to EAFNOSUPPORT, but are there any instances where sa_family is AF_UNSPEC (rather than when falling through from AF_INET) that should fail with EAFNOSUPPORT?


I also had a documentation patch to better describe the behaviour when IFQ_ENQUEUE fails here:

--- /usr/src/share/man/man4/tun.4       2022-04-30 17:25:42.000000000 -0700
+++ tun.4       2026-10-18 19:33:54.709613582 -0700
@@ -156,7 +156,8 @@
 Writes will not block; if the packet cannot be accepted for a
 transient reason
 .Pq e.g., no buffer space available ,
-it is silently dropped; if the reason is not transient
+it is dropped and reported as a collision in the interface statistics;
+ if the reason is not transient
 .Pq e.g., packet too large ,
 an error is returned.
 If

...this is the case, anyway, in the error path in the AF_UNSPEC branch (if_tun.c:631), but the packet can also be dropped earlier if the link-layer and address family can't be prepended to the mbuf, according to the comments on the branches at lines 599 and 608, without incrementing the counter.







Home | Main Index | Thread Index | Old Index