Author: glebius
Date: Fri Sep 26 08:42:32 2014
New Revision: 272161
URL: http://svnweb.freebsd.org/changeset/base/272161

Log:
  - When reconfiguring protocol on a lagg, first set it to LAGG_PROTO_NONE,
    then drop lock, run the attach routines, and then set it to specific
    proto. This removes tons of WITNESS warnings.
  - Make lagg protocol attach handlers not failing and allocate memory
    with M_WAITOK.
  
  Sponsored by: Netflix
  Sponsored by: Nginx, Inc.

Modified:
  head/sys/net/ieee8023ad_lacp.c
  head/sys/net/ieee8023ad_lacp.h
  head/sys/net/if_lagg.c

Modified: head/sys/net/ieee8023ad_lacp.c
==============================================================================
--- head/sys/net/ieee8023ad_lacp.c      Fri Sep 26 08:16:26 2014        
(r272160)
+++ head/sys/net/ieee8023ad_lacp.c      Fri Sep 26 08:42:32 2014        
(r272161)
@@ -783,16 +783,13 @@ lacp_attach_sysctl_debug(struct lacp_sof
            "Bitmap of if_dunit entries to drop TX frames for");
 }
 
-int
+void
 lacp_attach(struct lagg_softc *sc)
 {
        struct lacp_softc *lsc;
        struct sysctl_oid *oid;
 
-       lsc = malloc(sizeof(struct lacp_softc),
-           M_DEVBUF, M_NOWAIT|M_ZERO);
-       if (lsc == NULL)
-               return (ENOMEM);
+       lsc = malloc(sizeof(struct lacp_softc), M_DEVBUF, M_WAITOK | M_ZERO);
 
        sc->sc_psc = (caddr_t)lsc;
        lsc->lsc_softc = sc;
@@ -818,21 +815,18 @@ lacp_attach(struct lagg_softc *sc)
        /* if the lagg is already up then do the same */
        if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
                lacp_init(sc);
-
-       return (0);
 }
 
 void
-lacp_detach(struct lagg_softc *sc)
+lacp_detach(void *psc)
 {
-       struct lacp_softc *lsc = LACP_SOFTC(sc);
+       struct lacp_softc *lsc = (struct lacp_softc *)psc;
 
        KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators),
            ("aggregators still active"));
        KASSERT(lsc->lsc_active_aggregator == NULL,
            ("aggregator still attached"));
 
-       sc->sc_psc = NULL;
        callout_drain(&lsc->lsc_transit_callout);
        callout_drain(&lsc->lsc_callout);
 

Modified: head/sys/net/ieee8023ad_lacp.h
==============================================================================
--- head/sys/net/ieee8023ad_lacp.h      Fri Sep 26 08:16:26 2014        
(r272160)
+++ head/sys/net/ieee8023ad_lacp.h      Fri Sep 26 08:42:32 2014        
(r272161)
@@ -282,8 +282,8 @@ struct lacp_softc {
 
 struct mbuf    *lacp_input(struct lagg_port *, struct mbuf *);
 struct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *);
-int            lacp_attach(struct lagg_softc *);
-void           lacp_detach(struct lagg_softc *);
+void           lacp_attach(struct lagg_softc *);
+void           lacp_detach(void *);
 void           lacp_init(struct lagg_softc *);
 void           lacp_stop(struct lagg_softc *);
 int            lacp_port_create(struct lagg_port *);

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c      Fri Sep 26 08:16:26 2014        (r272160)
+++ head/sys/net/if_lagg.c      Fri Sep 26 08:42:32 2014        (r272161)
@@ -125,19 +125,19 @@ static const void *lagg_gethdr(struct mb
 static int     lagg_sysctl_active(SYSCTL_HANDLER_ARGS);
 
 /* Simple round robin */
-static int     lagg_rr_attach(struct lagg_softc *);
+static void    lagg_rr_attach(struct lagg_softc *);
 static int     lagg_rr_start(struct lagg_softc *, struct mbuf *);
 static struct mbuf *lagg_rr_input(struct lagg_softc *, struct lagg_port *,
                    struct mbuf *);
 
 /* Active failover */
-static int     lagg_fail_attach(struct lagg_softc *);
+static void    lagg_fail_attach(struct lagg_softc *);
 static int     lagg_fail_start(struct lagg_softc *, struct mbuf *);
 static struct mbuf *lagg_fail_input(struct lagg_softc *, struct lagg_port *,
                    struct mbuf *);
 
 /* Loadbalancing */
-static int     lagg_lb_attach(struct lagg_softc *);
+static void    lagg_lb_attach(struct lagg_softc *);
 static void    lagg_lb_detach(struct lagg_softc *);
 static int     lagg_lb_port_create(struct lagg_port *);
 static void    lagg_lb_port_destroy(struct lagg_port *);
@@ -147,13 +147,13 @@ static struct mbuf *lagg_lb_input(struct
 static int     lagg_lb_porttable(struct lagg_softc *, struct lagg_port *);
 
 /* Broadcast */
-static int    lagg_bcast_attach(struct lagg_softc *);
+static void    lagg_bcast_attach(struct lagg_softc *);
 static int    lagg_bcast_start(struct lagg_softc *, struct mbuf *);
 static struct mbuf *lagg_bcast_input(struct lagg_softc *, struct lagg_port *,
                   struct mbuf *);
 
 /* 802.3ad LACP */
-static int     lagg_lacp_attach(struct lagg_softc *);
+static void    lagg_lacp_attach(struct lagg_softc *);
 static void    lagg_lacp_detach(struct lagg_softc *);
 static int     lagg_lacp_start(struct lagg_softc *, struct mbuf *);
 static struct mbuf *lagg_lacp_input(struct lagg_softc *, struct lagg_port *,
@@ -163,16 +163,16 @@ static void       lagg_lacp_lladdr(struct lagg
 static void    lagg_callout(void *);
 
 /* lagg protocol table */
-static const struct {
-       int                     ti_proto;
-       int                     (*ti_attach)(struct lagg_softc *);
+static const struct lagg_proto {
+       lagg_proto      ti_proto;
+       void            (*ti_attach)(struct lagg_softc *);
 } lagg_protos[] = {
        { LAGG_PROTO_ROUNDROBIN,        lagg_rr_attach },
-       { LAGG_PROTO_FAILOVER,  lagg_fail_attach },
+       { LAGG_PROTO_FAILOVER,          lagg_fail_attach },
        { LAGG_PROTO_LOADBALANCE,       lagg_lb_attach },
        { LAGG_PROTO_ETHERCHANNEL,      lagg_lb_attach },
        { LAGG_PROTO_LACP,              lagg_lacp_attach },
-       { LAGG_PROTO_BROADCAST, lagg_bcast_attach },
+       { LAGG_PROTO_BROADCAST,         lagg_bcast_attach },
        { LAGG_PROTO_NONE,              NULL }
 };
 
@@ -281,10 +281,10 @@ lagg_clone_create(struct if_clone *ifc, 
 {
        struct lagg_softc *sc;
        struct ifnet *ifp;
-       int i, error = 0;
        static const u_char eaddr[6];   /* 00:00:00:00:00:00 */
        struct sysctl_oid *oid;
        char num[14];                   /* sufficient for 32 bits */
+       int i;
 
        sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
        ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
@@ -328,11 +328,7 @@ lagg_clone_create(struct if_clone *ifc, 
        for (i = 0; lagg_protos[i].ti_proto != LAGG_PROTO_NONE; i++) {
                if (lagg_protos[i].ti_proto == LAGG_PROTO_DEFAULT) {
                        sc->sc_proto = lagg_protos[i].ti_proto;
-                       if ((error = lagg_protos[i].ti_attach(sc)) != 0) {
-                               if_free(ifp);
-                               free(sc, M_DEVBUF);
-                               return (error);
-                       }
+                       lagg_protos[i].ti_attach(sc);
                        break;
                }
        }
@@ -403,8 +399,8 @@ lagg_clone_destroy(struct ifnet *ifp)
        /* Unhook the aggregation protocol */
        if (sc->sc_detach != NULL)
                (*sc->sc_detach)(sc);
-
-       LAGG_WUNLOCK(sc);
+       else
+               LAGG_WUNLOCK(sc);
 
        sysctl_ctx_free(&sc->ctx);
        ifmedia_removeall(&sc->sc_media);
@@ -984,6 +980,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd
        struct lagg_reqflags *rf = (struct lagg_reqflags *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        struct lagg_port *lp;
+       const struct lagg_proto *proto;
        struct ifnet *tpif;
        struct thread *td = curthread;
        char *buf, *outbuf;
@@ -1031,51 +1028,32 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd
                error = priv_check(td, PRIV_NET_LAGG);
                if (error)
                        break;
-               if (ra->ra_proto >= LAGG_PROTO_MAX) {
+               for (proto = lagg_protos; proto->ti_proto != LAGG_PROTO_NONE;
+                   proto++) {
+                       if (proto->ti_proto == ra->ra_proto) {
+                               if (sc->sc_ifflags & IFF_DEBUG)
+                                       printf("%s: using proto %u\n",
+                                           sc->sc_ifname, proto->ti_proto);
+                               break;
+                       }
+               }
+               if (proto->ti_proto == LAGG_PROTO_NONE) {
                        error = EPROTONOSUPPORT;
                        break;
                }
+               /* Set to LAGG_PROTO_NONE during the attach. */
                LAGG_WLOCK(sc);
                if (sc->sc_proto != LAGG_PROTO_NONE) {
-                       /* Reset protocol first in case detach unlocks */
                        sc->sc_proto = LAGG_PROTO_NONE;
                        if (sc->sc_detach != NULL)
                                sc->sc_detach(sc);
-                       sc->sc_detach = NULL;
-                       sc->sc_start = NULL;
-                       sc->sc_input = NULL;
-                       sc->sc_port_create = NULL;
-                       sc->sc_port_destroy = NULL;
-                       sc->sc_linkstate = NULL;
-                       sc->sc_init = NULL;
-                       sc->sc_stop = NULL;
-                       sc->sc_lladdr = NULL;
-                       sc->sc_req = NULL;
-                       sc->sc_portreq = NULL;
-               } else if (sc->sc_input != NULL) {
-                       /* Still detaching */
-                       error = EBUSY;
-               }
-               if (error != 0) {
-                       LAGG_WUNLOCK(sc);
-                       break;
-               }
-               for (int i = 0; i < (sizeof(lagg_protos) /
-                   sizeof(lagg_protos[0])); i++) {
-                       if (lagg_protos[i].ti_proto == ra->ra_proto) {
-                               if (sc->sc_ifflags & IFF_DEBUG)
-                                       printf("%s: using proto %u\n",
-                                           sc->sc_ifname,
-                                           lagg_protos[i].ti_proto);
-                               sc->sc_proto = lagg_protos[i].ti_proto;
-                               if (sc->sc_proto != LAGG_PROTO_NONE)
-                                       error = lagg_protos[i].ti_attach(sc);
+                       else
                                LAGG_WUNLOCK(sc);
-                               return (error);
-                       }
                }
+               proto->ti_attach(sc);
+               LAGG_WLOCK(sc);
+               sc->sc_proto = proto->ti_proto;
                LAGG_WUNLOCK(sc);
-               error = EPROTONOSUPPORT;
                break;
        case SIOCGLAGGFLAGS:
                rf->rf_flags = sc->sc_flags;
@@ -1668,8 +1646,7 @@ lagg_enqueue(struct ifnet *ifp, struct m
 /*
  * Simple round robin aggregation
  */
-
-static int
+static void
 lagg_rr_attach(struct lagg_softc *sc)
 {
        sc->sc_start = lagg_rr_start;
@@ -1678,8 +1655,6 @@ lagg_rr_attach(struct lagg_softc *sc)
        sc->sc_port_create = NULL;
        sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX;
        sc->sc_seq = 0;
-
-       return (0);
 }
 
 static int
@@ -1721,8 +1696,7 @@ lagg_rr_input(struct lagg_softc *sc, str
 /*
  * Broadcast mode
  */
-
-static int
+static void
 lagg_bcast_attach(struct lagg_softc *sc)
 {
        sc->sc_start = lagg_bcast_start;
@@ -1733,8 +1707,6 @@ lagg_bcast_attach(struct lagg_softc *sc)
        sc->sc_detach = NULL;
        sc->sc_req = NULL;
        sc->sc_portreq = NULL;
-
-       return (0);
 }
 
 static int
@@ -1800,8 +1772,7 @@ lagg_bcast_input(struct lagg_softc *sc, 
 /*
  * Active failover
  */
-
-static int
+static void
 lagg_fail_attach(struct lagg_softc *sc)
 {
        sc->sc_start = lagg_fail_start;
@@ -1809,8 +1780,6 @@ lagg_fail_attach(struct lagg_softc *sc)
        sc->sc_port_create = NULL;
        sc->sc_port_destroy = NULL;
        sc->sc_detach = NULL;
-
-       return (0);
 }
 
 static int
@@ -1858,16 +1827,13 @@ lagg_fail_input(struct lagg_softc *sc, s
 /*
  * Loadbalancing
  */
-
-static int
+static void
 lagg_lb_attach(struct lagg_softc *sc)
 {
        struct lagg_port *lp;
        struct lagg_lb *lb;
 
-       if ((lb = (struct lagg_lb *)malloc(sizeof(struct lagg_lb),
-           M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
-               return (ENOMEM);
+       lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO);
 
        sc->sc_detach = lagg_lb_detach;
        sc->sc_start = lagg_lb_start;
@@ -1881,8 +1847,6 @@ lagg_lb_attach(struct lagg_softc *sc)
 
        SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
                lagg_lb_port_create(lp);
-
-       return (0);
 }
 
 static void
@@ -1891,6 +1855,7 @@ lagg_lb_detach(struct lagg_softc *sc)
        struct lagg_lb *lb;
 
        lb = (struct lagg_lb *)sc->sc_psc;
+       LAGG_WUNLOCK(sc);
        if (lb != NULL)
                free(lb, M_DEVBUF);
 }
@@ -1972,12 +1937,10 @@ lagg_lb_input(struct lagg_softc *sc, str
 /*
  * 802.3ad LACP
  */
-
-static int
+static void
 lagg_lacp_attach(struct lagg_softc *sc)
 {
        struct lagg_port *lp;
-       int error;
 
        sc->sc_detach = lagg_lacp_detach;
        sc->sc_port_create = lacp_port_create;
@@ -1991,28 +1954,26 @@ lagg_lacp_attach(struct lagg_softc *sc)
        sc->sc_req = lacp_req;
        sc->sc_portreq = lacp_portreq;
 
-       error = lacp_attach(sc);
-       if (error)
-               return (error);
+       lacp_attach(sc);
 
        SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
                lacp_port_create(lp);
-
-       return (error);
 }
 
 static void
 lagg_lacp_detach(struct lagg_softc *sc)
 {
        struct lagg_port *lp;
+       void *psc;
 
        SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
                lacp_port_destroy(lp);
 
-       /* unlocking is safe here */
+       psc = sc->sc_psc;
+       sc->sc_psc = NULL;
        LAGG_WUNLOCK(sc);
-       lacp_detach(sc);
-       LAGG_WLOCK(sc);
+
+       lacp_detach(psc);
 }
 
 static void
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to