On 27/05/17(Sat) 11:33, Sebastian Benoit wrote: > (benno_pflow_try3_1_task.diff) > > move sending of pflow packet into a task, seperated from the data > collection by a mbuf queue.
Comments inline. > diff --git sys/net/if_pflow.c sys/net/if_pflow.c > index a40fe23862b..8cfffa1e4e7 100644 > --- sys/net/if_pflow.c > +++ sys/net/if_pflow.c > @@ -67,6 +67,7 @@ struct pflowstats pflowstats; > void pflowattach(int); > int pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, > struct rtentry *rt); > +void pflow_output_process(void *); > int pflow_clone_create(struct if_clone *, int); > int pflow_clone_destroy(struct ifnet *); > int pflow_set(struct pflow_softc *, struct pflowreq *); > @@ -124,11 +125,33 @@ pflow_output(struct ifnet *ifp, struct mbuf *m, struct > sockaddr *dst, > return (EAFNOSUPPORT); > } > > +void > +pflow_output_process(void *xifidx) > +{ You can pass the softc pointer as argument because the task has the same lifetime as its softc. What protects you is the (missing) task_del() in clone_destroy(). > + unsigned int ifidx = (unsigned long)xifidx; > + struct mbuf *m; > + struct ifnet *ifp; > + struct pflow_softc *sc; > + > + ifp = if_get(ifidx); > + if (ifp == NULL) > + return; > + sc = ifp->if_softc; > + > + KERNEL_LOCK(); > + while ((m = mq_dequeue(&sc->sc_outputqueue)) != NULL) { You want to use a mbuf_list, alas, ml_dequeue() because you don't need a mutex protection. > + pflow_sendout_mbuf(sc, m); > + } > + KERNEL_UNLOCK(); > + if_put(ifp); > +} > + > int > pflow_clone_create(struct if_clone *ifc, int unit) > { > struct ifnet *ifp; > struct pflow_softc *pflowif; > + unsigned long ifidx; > > if ((pflowif = malloc(sizeof(*pflowif), > M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) > @@ -241,11 +264,15 @@ pflow_clone_create(struct if_clone *ifc, int unit) > ifp->if_hdrlen = PFLOW_HDRLEN; > ifp->if_flags = IFF_UP; > ifp->if_flags &= ~IFF_RUNNING; /* not running, need receiver */ > + mq_init(&pflowif->sc_outputqueue, IFQ_MAXLEN, IPL_NET); ml_init(9) :) > pflow_setmtu(pflowif, ETHERMTU); > pflow_init_timeouts(pflowif); > if_attach(ifp); > if_alloc_sadl(ifp); > > + ifidx = ifp->if_index; > + task_set(&pflowif->sc_outputtask, pflow_output_process, (void *)ifidx); > + > /* Insert into list of pflows */ > SLIST_INSERT_HEAD(&pflowif_list, pflowif, sc_next); Insertion in pflowif_list needs the NET_LOCK(). > return (0); > @@ -255,11 +282,10 @@ int > pflow_clone_destroy(struct ifnet *ifp) > { > struct pflow_softc *sc = ifp->if_softc; > - int s, error; > + int error; > > error = 0; > > - s = splnet(); > if (timeout_initialized(&sc->sc_tmo)) > timeout_del(&sc->sc_tmo); > if (timeout_initialized(&sc->sc_tmo6)) > @@ -279,7 +305,6 @@ pflow_clone_destroy(struct ifnet *ifp) > if_detach(ifp); > SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next); Deletion as well. > free(sc, M_DEVBUF, sizeof(*sc)); > - splx(s); > return (error); > } > > @@ -311,7 +336,7 @@ pflow_set(struct pflow_softc *sc, struct pflowreq *pflowr) > struct proc *p = curproc; > struct socket *so; > struct sockaddr *sa; > - int error = 0; > + int s, error = 0; > > if (pflowr->addrmask & PFLOW_MASK_VERSION) { > switch(pflowr->version) { > @@ -407,6 +432,8 @@ pflow_set(struct pflow_softc *sc, struct pflowreq *pflowr) > } > > if (sc->so == NULL) { Please leave the unlock/lock dance around pflow_set(). It is not a problem. The rest if fine! Thanks for taking care of this.