On Wed, Oct 24, 2018 at 04:34:43PM -0300, Martin Pieuchot wrote: > I'd like to take brigde_input() & bridge_output() outside of the > KERNEL_LOCK(). My previous approach relying on the NET_LOCK() didn't > work because wireless drivers might call bridge_output() from their > interrupt handler. > > So we'll need another mechanism. The first step would be to use a > mutex. One of the fields that will be protect by this lock is > `if_bridgeport'. So here's a small cleanup diff to make it clear > that the field is read in ioctl path. > > ok?
OK bluhm@ > Index: net/bridgectl.c > =================================================================== > RCS file: /cvs/src/sys/net/bridgectl.c,v > retrieving revision 1.10 > diff -u -p -r1.10 bridgectl.c > --- net/bridgectl.c 22 Oct 2018 13:18:23 -0000 1.10 > +++ net/bridgectl.c 24 Oct 2018 19:33:56 -0000 > @@ -55,7 +55,7 @@ int bridge_rtfind(struct bridge_softc *, > int bridge_rtdaddr(struct bridge_softc *, struct ether_addr *); > u_int32_t bridge_hash(struct bridge_softc *, struct ether_addr *); > > -int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *); > +int bridge_brlconf(struct bridge_iflist *, struct ifbrlconf *); > int bridge_addrule(struct bridge_iflist *, struct ifbrlreq *, int out); > > int > @@ -64,6 +64,7 @@ bridgectl_ioctl(struct ifnet *ifp, u_lon > struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc; > struct ifbreq *req = (struct ifbreq *)data; > struct ifbrlreq *brlreq = (struct ifbrlreq *)data; > + struct ifbrlconf *bc = (struct ifbrlconf *)data; > struct ifbareq *bareq = (struct ifbareq *)data; > struct ifbrparam *bparam = (struct ifbrparam *)data; > struct bridge_iflist *bif; > @@ -160,7 +161,17 @@ bridgectl_ioctl(struct ifnet *ifp, u_lon > bridge_flushrule(bif); > break; > case SIOCBRDGGRL: > - error = bridge_brlconf(sc, (struct ifbrlconf *)data); > + ifs = ifunit(bc->ifbrl_ifsname); > + if (ifs == NULL) { > + error = ENOENT; > + break; > + } > + bif = (struct bridge_iflist *)ifs->if_bridgeport; > + if (bif == NULL || bif->bridge_sc != sc) { > + error = ESRCH; > + break; > + } > + error = bridge_brlconf(bif, bc); > break; > default: > break; > @@ -535,21 +546,13 @@ bridge_update(struct ifnet *ifp, struct > * bridge filter/matching rules > */ > int > -bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc) > +bridge_brlconf(struct bridge_iflist *bif, struct ifbrlconf *bc) > { > - struct ifnet *ifp; > - struct bridge_iflist *bif; > + struct bridge_softc *sc = bif->bridge_sc; > struct brl_node *n; > struct ifbrlreq req; > int error = 0; > u_int32_t i = 0, total = 0; > - > - ifp = ifunit(bc->ifbrl_ifsname); > - if (ifp == NULL) > - return (ENOENT); > - bif = (struct bridge_iflist *)ifp->if_bridgeport; > - if (bif == NULL || bif->bridge_sc != sc) > - return (ESRCH); > > SIMPLEQ_FOREACH(n, &bif->bif_brlin, brl_next) { > total++;