Makes sense to me.

-Andrew

On Apr 7, 2012, at 4:02 AM, Andrew Thompson wrote:

> On 3 April 2012 00:35, John Baldwin <j...@freebsd.org> wrote:
>> On Friday, March 30, 2012 6:04:24 pm Andrew Boyer wrote:
>>> While investigating a LACP issue, I turned on LACP_DEBUG on a debug kernel.
>> In this configuration it's easy to panic the kernel - just run 'ifconfig 
>> lagg0
>> laggproto lacp' on a lagg that's already in LACP mode and receiving LACP
>> messages.
>>> 
>>> The problem is that lagg_lacp_detach() drops the lagg wlock (with the
>> comment in the title), which allows incoming LACP messages to get through
>> lagg_input() while the structure is being destroyed in lacp_detach().
>>> 
>>> There's a very simple fix, but I don't know if it's the best way to fix it.
>> Resetting the protocol before calling sc_detach causes any further incoming
>> packets to be dropped until the lagg gets reconfigured.  Thoughts?
>> 
>> This looks sensible.
> 
> Changing the order also needs an additional check as LAGG_PROTO_NONE
> no longer means the detach is finished. If one ioctl sleeps then we
> may nullify all the pointers upon wake that have already been set by
> the other ioctl.
> 
> Does this look ok?
> 
> Index: if_lagg.c
> ===================================================================
> --- if_lagg.c (revision 233252)
> +++ if_lagg.c (working copy)
> @@ -950,11 +950,11 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
>                       error = EPROTONOSUPPORT;
>                       break;
>               }
> +             LAGG_WLOCK(sc);
>               if (sc->sc_proto != LAGG_PROTO_NONE) {
> -                     LAGG_WLOCK(sc);
> +                     /* Reset protocol first in case detach unlocks */
> +                     sc->sc_proto = LAGG_PROTO_NONE;
>                       error = sc->sc_detach(sc);
> -                     /* Reset protocol and pointers */
> -                     sc->sc_proto = LAGG_PROTO_NONE;
>                       sc->sc_detach = NULL;
>                       sc->sc_start = NULL;
>                       sc->sc_input = NULL;
> @@ -966,8 +966,11 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
>                       sc->sc_lladdr = NULL;
>                       sc->sc_req = NULL;
>                       sc->sc_portreq = NULL;
> -                     LAGG_WUNLOCK(sc);
> +             } else if (sc->sc_input != NULL) {
> +                     /* Still detaching */
> +                     error = EBUSY;
>               }
> +             LAGG_WUNLOCK(sc);
>               if (error != 0)
>                       break;
>               for (int i = 0; i < (sizeof(lagg_protos) /

--------------------------------------------------
Andrew Boyer    abo...@averesystems.com




_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to