> On 5 Oct 2023, at 21:50, Vitaliy Makkoveev <m...@openbsd.org> wrote:
> 
> Otherwise `if_snd' could still contain packets. If any of them has
> associated data with bumped reference counter, the corresponding
> refcnt_finalize() will sleep forever. I don't think we need to
> transmit these packets when interface became running again.

there were a bunch of paths where the stack would implicitly take an interface 
down and up again around the actual change it was trying to make. from memory 
these kinds of things are disruptive anyway, so losing a few more packets might 
not be a problem. we do ride this out at the moment though.

> 
> I don't like this unlocked if_flags check we have in ifq_start_task().
> Guess READ_ONCE() is much better to load value.

there are no inconsistent intermediate values you can read from if_flags. are 
you worried the compiler will load the value again and maybe we'll get a 
different state the second time?

> The problem reported in the "wg destroy hangs" [1] thread is the kind of
> described above. Also, current ifq_start_task() implementation denies to
> introduce reference counters for wg_peer and remove this
> wg_peer_destroy() hack:
> 
>         NET_LOCK();
>         while (!ifq_empty(&sc->sc_if.if_snd)) {
>                 NET_UNLOCK();
>                 tsleep_nsec(sc, PWAIT, "wg_ifq", 1000);
>                 NET_LOCK();
>         }
>         NET_UNLOCK();
> 
> 1. https://marc.info/?t=169642396300001&r=1&w=2
> 
> ok?

im kind of surprised that when dealing with a problem that only seem to appear 
in wireguard that you lean toward ifqs needing a fix. especially surprising 
when the wg code in question is a tsleep_nsec(1000) in a loop.

i would argue that wg go down, wait for the stack to stop using it, and then do 
it's own purge.

> 
> Index: sys/net/ifq.c
> ===================================================================
> RCS file: /cvs/src/sys/net/ifq.c,v
> retrieving revision 1.51
> diff -u -p -r1.51 ifq.c
> --- sys/net/ifq.c 5 Oct 2023 11:08:56 -0000 1.51
> +++ sys/net/ifq.c 5 Oct 2023 11:49:40 -0000
> @@ -140,8 +140,11 @@ ifq_start_task(void *p)
> struct ifqueue *ifq = p;
> struct ifnet *ifp = ifq->ifq_if;
> 
> - if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
> -    ifq_empty(ifq) || ifq_is_oactive(ifq))
> + if (!ISSET(READ_ONCE(ifp->if_flags), IFF_RUNNING)){
> + ifq_purge(ifq);
> + return;
> + }
> + if (ifq_empty(ifq) || ifq_is_oactive(ifq))
> return;
> 
> ifp->if_qstart(ifq);
> 

Reply via email to