I did some tests. The performance did not change. I think this is the expected behaviour.
BR Simon 2017-01-23 7:35 GMT+01:00, David Gwynne <[email protected]>: > hrvoje popovski hit a problem where the kernel would panic under load. > > i mistakenly called an interfaces qstart routine directly from > if_enqueue rather than via the ifq serializer. this meant that txeof > routines on network cards calling ifq_restart would cause the start > routine to run concurrently, therefore causing corruption of the > ring state. > > this diff fixes that. > > On Mon, Jan 23, 2017 at 01:09:57PM +1000, David Gwynne wrote: >> the short explanation is that this lets interfaces allocate multiple >> ifq structures that can be mapped to their transmit rings. the >> mechanism for this is a driver calling if_attach_queues() after >> theyve called if_attach(). >> >> the long version is that this has if_enqueue access an array of >> ifqueues on the interface instead of if_snd directly. the ifq is >> picked by asking the queue discipline (priq or hfsc) to map an mbuf >> to a slot in the if_ifqs array. >> >> to notify the driver that a particular queue needs to start ive >> added a new function pointer to ifnet called if_qstart. if_qstart >> takes an ifqueue * as an argument instead of an ifnet *, thereby >> getting past the implicit behaviour that interfaces only have a >> single ring. >> >> our drivers all have if_start routines that take ifnet pointers >> though, so there's compatability for those where a default if_qstart >> implementation calls if_start for those drivers. in the future >> if_start will be replaced with if_qstart and we can rename it back >> to if_start. until then, there's compat. >> >> drivers that provide their own if_qstart instead of an if_start >> function notify the stack by setting IFXF_MPSAFE. a chunk of this >> diff is changing the IFXF_MPSAFE drivers to set if_qstart instead >> of if_start. note that this is a mechanical change, it does not add >> multiple tx queues to these drivers. >> >> most of this is straightforward except for the hfsc handling. hfsc >> needs to track all flows going over an interface, which means all >> flows have to be serialised through hfsc. the mechanism in use >> before this change was to swap the priq backend on if_snd with the >> hfsc backend. the trick with this diff is that we still do that, >> ie, we only change the first ifqueue on an interface over to hfsc. >> this works because we use the ifqops on the first ifq to map packets >> to any of them. because the hfsc map function unconditionally maps >> packets to the first ifq, all packets end up going through the one >> hfsc structure we set up. the rest of the ifqs remain set up as >> priq, but dont get used for sending packets after hfsc has been >> enabled. if we ever add another ifqops backend, this will have to >> be rethought. until then this is an elegant hack. >> >> a consequence of this change is that we the ifnet if_start function >> should not be called anymore. this isnt true at the moment because >> of things like net80211 and ppp. they both queue management packets >> onto a separate queue, but those separate queues are dequeued and >> processed in the interfaces start routine. if we want to mark wifi >> and ppp drivers as mpsafe (or get rid of separate if_start and >> if_qstart routines) this will have to change. >> >> the guts of this change are in if_enqueue and if_attach_queues. >> >> ok? >> > > Index: arch/octeon/dev/if_cnmac.c > =================================================================== > RCS file: /cvs/src/sys/arch/octeon/dev/if_cnmac.c,v > retrieving revision 1.61 > diff -u -p -r1.61 if_cnmac.c > --- arch/octeon/dev/if_cnmac.c 5 Nov 2016 05:14:18 -0000 1.61 > +++ arch/octeon/dev/if_cnmac.c 23 Jan 2017 06:32:59 -0000 > @@ -138,7 +138,7 @@ int octeon_eth_ioctl(struct ifnet *, u_l > void octeon_eth_watchdog(struct ifnet *); > int octeon_eth_init(struct ifnet *); > int octeon_eth_stop(struct ifnet *, int); > -void octeon_eth_start(struct ifnet *); > +void octeon_eth_start(struct ifqueue *); > > int octeon_eth_send_cmd(struct octeon_eth_softc *, uint64_t, uint64_t); > uint64_t octeon_eth_send_makecmd_w1(int, paddr_t); > @@ -303,7 +303,7 @@ octeon_eth_attach(struct device *parent, > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = octeon_eth_ioctl; > - ifp->if_start = octeon_eth_start; > + ifp->if_qstart = octeon_eth_start; > ifp->if_watchdog = octeon_eth_watchdog; > ifp->if_hardmtu = OCTEON_ETH_MAX_MTU; > IFQ_SET_MAXLEN(&ifp->if_snd, max(GATHER_QUEUE_SIZE, IFQ_MAXLEN)); > @@ -704,8 +704,6 @@ octeon_eth_ioctl(struct ifnet *ifp, u_lo > error = 0; > } > > - if_start(ifp); > - > splx(s); > return (error); > } > @@ -923,13 +921,14 @@ done: > } > > void > -octeon_eth_start(struct ifnet *ifp) > +octeon_eth_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct octeon_eth_softc *sc = ifp->if_softc; > struct mbuf *m; > > if (__predict_false(!cn30xxgmx_link_status(sc->sc_gmx_port))) { > - ifq_purge(&ifp->if_snd); > + ifq_purge(ifq); > return; > } > > @@ -948,12 +947,12 @@ octeon_eth_start(struct ifnet *ifp) > * and bail out. > */ > if (octeon_eth_send_queue_is_full(sc)) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > timeout_add(&sc->sc_tick_free_ch, 1); > return; > } > > - m = ifq_dequeue(&ifp->if_snd); > + m = ifq_dequeue(ifq); > if (m == NULL) > return; > > Index: dev/ic/re.c > =================================================================== > RCS file: /cvs/src/sys/dev/ic/re.c,v > retrieving revision 1.200 > diff -u -p -r1.200 re.c > --- dev/ic/re.c 22 Jan 2017 10:17:38 -0000 1.200 > +++ dev/ic/re.c 23 Jan 2017 06:32:59 -0000 > @@ -161,7 +161,7 @@ int re_tx_list_init(struct rl_softc *); > int re_rxeof(struct rl_softc *); > int re_txeof(struct rl_softc *); > void re_tick(void *); > -void re_start(struct ifnet *); > +void re_start(struct ifqueue *); > void re_txstart(void *); > int re_ioctl(struct ifnet *, u_long, caddr_t); > void re_watchdog(struct ifnet *); > @@ -1005,7 +1005,7 @@ re_attach(struct rl_softc *sc, const cha > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = re_ioctl; > - ifp->if_start = re_start; > + ifp->if_qstart = re_start; > ifp->if_watchdog = re_watchdog; > ifp->if_hardmtu = sc->rl_max_mtu; > IFQ_SET_MAXLEN(&ifp->if_snd, sc->rl_ldata.rl_tx_desc_cnt); > @@ -1776,8 +1776,9 @@ re_txstart(void *xsc) > */ > > void > -re_start(struct ifnet *ifp) > +re_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct rl_softc *sc = ifp->if_softc; > struct mbuf *m; > unsigned int idx; > @@ -1785,7 +1786,7 @@ re_start(struct ifnet *ifp) > int post = 0; > > if (!ISSET(sc->rl_flags, RL_FLAG_LINK)) { > - IFQ_PURGE(&ifp->if_snd); > + ifq_purge(ifq); > return; > } > > @@ -1797,11 +1798,11 @@ re_start(struct ifnet *ifp) > > for (;;) { > if (sc->rl_ldata.rl_tx_ndescs >= free + 2) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - m = ifq_dequeue(&ifp->if_snd); > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > @@ -1831,7 +1832,7 @@ re_start(struct ifnet *ifp) > > ifp->if_timer = 5; > sc->rl_ldata.rl_txq_prodidx = idx; > - ifq_serialize(&ifp->if_snd, &sc->rl_start); > + ifq_serialize(ifq, &sc->rl_start); > } > > int > Index: dev/pci/if_bge.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_bge.c,v > retrieving revision 1.383 > diff -u -p -r1.383 if_bge.c > --- dev/pci/if_bge.c 22 Jan 2017 10:17:38 -0000 1.383 > +++ dev/pci/if_bge.c 23 Jan 2017 06:32:59 -0000 > @@ -142,7 +142,7 @@ int bge_encap(struct bge_softc *, struct > int bge_compact_dma_runt(struct mbuf *); > > int bge_intr(void *); > -void bge_start(struct ifnet *); > +void bge_start(struct ifqueue *); > int bge_ioctl(struct ifnet *, u_long, caddr_t); > int bge_rxrinfo(struct bge_softc *, struct if_rxrinfo *); > void bge_init(void *); > @@ -2996,7 +2996,7 @@ bge_attach(struct device *parent, struct > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = bge_ioctl; > - ifp->if_start = bge_start; > + ifp->if_qstart = bge_start; > ifp->if_watchdog = bge_watchdog; > IFQ_SET_MAXLEN(&ifp->if_snd, BGE_TX_RING_CNT - 1); > > @@ -4116,14 +4116,15 @@ fail_unload: > * to the mbuf data regions directly in the transmit descriptors. > */ > void > -bge_start(struct ifnet *ifp) > +bge_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct bge_softc *sc = ifp->if_softc; > struct mbuf *m; > int txinc; > > if (!BGE_STS_BIT(sc, BGE_STS_LINK)) { > - IFQ_PURGE(&ifp->if_snd); > + ifq_purge(ifq); > return; > } > > @@ -4132,11 +4133,11 @@ bge_start(struct ifnet *ifp) > /* Check if we have enough free send BDs. */ > if (sc->bge_txcnt + txinc + BGE_NTXSEG + 16 >= > BGE_TX_RING_CNT) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - IFQ_DEQUEUE(&ifp->if_snd, m); > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > Index: dev/pci/if_bnx.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v > retrieving revision 1.123 > diff -u -p -r1.123 if_bnx.c > --- dev/pci/if_bnx.c 22 Jan 2017 10:17:38 -0000 1.123 > +++ dev/pci/if_bnx.c 23 Jan 2017 06:32:59 -0000 > @@ -366,7 +366,7 @@ void bnx_free_tx_chain(struct bnx_softc > void bnx_rxrefill(void *); > > int bnx_tx_encap(struct bnx_softc *, struct mbuf *, int *); > -void bnx_start(struct ifnet *); > +void bnx_start(struct ifqueue *); > int bnx_ioctl(struct ifnet *, u_long, caddr_t); > void bnx_watchdog(struct ifnet *); > int bnx_ifmedia_upd(struct ifnet *); > @@ -873,7 +873,7 @@ bnx_attachhook(struct device *self) > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = bnx_ioctl; > - ifp->if_start = bnx_start; > + ifp->if_qstart = bnx_start; > ifp->if_watchdog = bnx_watchdog; > IFQ_SET_MAXLEN(&ifp->if_snd, USABLE_TX_BD - 1); > bcopy(sc->eaddr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); > @@ -4865,15 +4865,16 @@ bnx_tx_encap(struct bnx_softc *sc, struc > /* Nothing. > */ > /****************************************************************************/ > void > -bnx_start(struct ifnet *ifp) > +bnx_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct bnx_softc *sc = ifp->if_softc; > struct mbuf *m_head = NULL; > int used; > u_int16_t tx_prod, tx_chain_prod; > > if (!sc->bnx_link) { > - ifq_purge(&ifp->if_snd); > + ifq_purge(ifq); > goto bnx_start_exit; > } > > @@ -4895,11 +4896,11 @@ bnx_start(struct ifnet *ifp) > DBPRINT(sc, BNX_INFO_SEND, "TX chain is closed for " > "business! Total tx_bd used = %d\n", > sc->used_tx_bd + used); > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - IFQ_DEQUEUE(&ifp->if_snd, m_head); > + m_head = ifq_dequeue(ifq); > if (m_head == NULL) > break; > > @@ -5149,11 +5150,8 @@ bnx_intr(void *xsc) > > /* Start moving packets again */ > if (ifp->if_flags & IFF_RUNNING && > - !IFQ_IS_EMPTY(&ifp->if_snd)) { > - KERNEL_LOCK(); > - bnx_start(ifp); > - KERNEL_UNLOCK(); > - } > + !IFQ_IS_EMPTY(&ifp->if_snd)) > + ifq_start(&ifp->if_snd); > } > > out: > @@ -5486,8 +5484,8 @@ bnx_tick(void *xsc) > IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { > sc->bnx_link++; > /* Now that link is up, handle any outstanding TX traffic. */ > - if (!IFQ_IS_EMPTY(&ifp->if_snd)) > - bnx_start(ifp); > + if (!ifq_empty(&ifp->if_snd)) > + ifq_start(&ifp->if_snd); > } > > bnx_tick_exit: > Index: dev/pci/if_em.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_em.c,v > retrieving revision 1.333 > diff -u -p -r1.333 if_em.c > --- dev/pci/if_em.c 22 Jan 2017 10:17:38 -0000 1.333 > +++ dev/pci/if_em.c 23 Jan 2017 06:32:59 -0000 > @@ -206,7 +206,7 @@ void em_defer_attach(struct device*); > int em_detach(struct device *, int); > int em_activate(struct device *, int); > int em_intr(void *); > -void em_start(struct ifnet *); > +void em_start(struct ifqueue *); > int em_ioctl(struct ifnet *, u_long, caddr_t); > void em_watchdog(struct ifnet *); > void em_init(void *); > @@ -583,15 +583,16 @@ err_pci: > **********************************************************************/ > > void > -em_start(struct ifnet *ifp) > +em_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct em_softc *sc = ifp->if_softc; > u_int head, free, used; > struct mbuf *m; > int post = 0; > > if (!sc->link_active) { > - IFQ_PURGE(&ifp->if_snd); > + ifq_purge(ifq); > return; > } > > @@ -611,11 +612,11 @@ em_start(struct ifnet *ifp) > for (;;) { > /* use 2 because cksum setup can use an extra slot */ > if (EM_MAX_SCATTER + 2 > free) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - m = ifq_dequeue(&ifp->if_snd); > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > @@ -1870,7 +1871,7 @@ em_setup_interface(struct em_softc *sc) > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = em_ioctl; > - ifp->if_start = em_start; > + ifp->if_qstart = em_start; > ifp->if_watchdog = em_watchdog; > ifp->if_hardmtu = > sc->hw.max_frame_size - ETHER_HDR_LEN - ETHER_CRC_LEN; > Index: dev/pci/if_myx.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_myx.c,v > retrieving revision 1.100 > diff -u -p -r1.100 if_myx.c > --- dev/pci/if_myx.c 22 Jan 2017 10:17:38 -0000 1.100 > +++ dev/pci/if_myx.c 23 Jan 2017 06:32:59 -0000 > @@ -201,7 +201,7 @@ void myx_up(struct myx_softc *); > void myx_iff(struct myx_softc *); > void myx_down(struct myx_softc *); > > -void myx_start(struct ifnet *); > +void myx_start(struct ifqueue *); > void myx_write_txd_tail(struct myx_softc *, struct myx_slot *, u_int8_t, > u_int32_t, u_int); > int myx_load_mbuf(struct myx_softc *, struct myx_slot *, struct mbuf *); > @@ -510,7 +510,7 @@ myx_attachhook(struct device *self) > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = myx_ioctl; > - ifp->if_start = myx_start; > + ifp->if_qstart = myx_start; > ifp->if_watchdog = myx_watchdog; > ifp->if_hardmtu = MYX_RXBIG_SIZE; > strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); > @@ -1200,10 +1200,9 @@ myx_up(struct myx_softc *sc) > goto empty_rx_ring_big; > } > > - ifq_clr_oactive(&ifp->if_snd); > - SET(ifp->if_flags, IFF_RUNNING); > myx_iff(sc); > - if_start(ifp); > + SET(ifp->if_flags, IFF_RUNNING); > + ifq_restart(&ifp->if_snd); > > return; > > @@ -1422,8 +1421,9 @@ myx_write_txd_tail(struct myx_softc *sc, > } > > void > -myx_start(struct ifnet *ifp) > +myx_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct myx_tx_desc txd; > struct myx_softc *sc = ifp->if_softc; > struct myx_slot *ms; > @@ -1448,11 +1448,11 @@ myx_start(struct ifnet *ifp) > > for (;;) { > if (used + sc->sc_tx_nsegs + 1 > free) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - IFQ_DEQUEUE(&ifp->if_snd, m); > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > Index: dev/pci/if_ix.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_ix.c,v > retrieving revision 1.149 > diff -u -p -r1.149 if_ix.c > --- dev/pci/if_ix.c 22 Jan 2017 10:17:38 -0000 1.149 > +++ dev/pci/if_ix.c 23 Jan 2017 06:32:59 -0000 > @@ -93,7 +93,7 @@ const struct pci_matchid ixgbe_devices[] > int ixgbe_probe(struct device *, void *, void *); > void ixgbe_attach(struct device *, struct device *, void *); > int ixgbe_detach(struct device *, int); > -void ixgbe_start(struct ifnet *); > +void ixgbe_start(struct ifqueue *); > int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); > int ixgbe_rxrinfo(struct ix_softc *, struct if_rxrinfo *); > void ixgbe_watchdog(struct ifnet *); > @@ -379,14 +379,15 @@ ixgbe_detach(struct device *self, int fl > **********************************************************************/ > > void > -ixgbe_start(struct ifnet * ifp) > +ixgbe_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct ix_softc *sc = ifp->if_softc; > struct tx_ring *txr = sc->tx_rings; > struct mbuf *m_head; > int post = 0; > > - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) > + if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(ifq)) > return; > if (!sc->link_up) > return; > @@ -398,11 +399,11 @@ ixgbe_start(struct ifnet * ifp) > for (;;) { > /* Check that we have the minimal number of TX descriptors. */ > if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) { > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - m_head = ifq_dequeue(&ifp->if_snd); > + m_head = ifq_dequeue(ifq); > if (m_head == NULL) > break; > > @@ -1612,7 +1613,7 @@ ixgbe_setup_interface(struct ix_softc *s > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = ixgbe_ioctl; > - ifp->if_start = ixgbe_start; > + ifp->if_qstart = ixgbe_start; > ifp->if_timer = 0; > ifp->if_watchdog = ixgbe_watchdog; > ifp->if_hardmtu = IXGBE_MAX_FRAME_SIZE - > Index: dev/pv/if_hvn.c > =================================================================== > RCS file: /cvs/src/sys/dev/pv/if_hvn.c,v > retrieving revision 1.31 > diff -u -p -r1.31 if_hvn.c > --- dev/pv/if_hvn.c 22 Jan 2017 10:17:39 -0000 1.31 > +++ dev/pv/if_hvn.c 23 Jan 2017 06:32:59 -0000 > @@ -179,7 +179,7 @@ void hvn_media_status(struct ifnet *, st > int hvn_iff(struct hvn_softc *); > void hvn_init(struct hvn_softc *); > void hvn_stop(struct hvn_softc *); > -void hvn_start(struct ifnet *); > +void hvn_start(struct ifqueue *); > int hvn_encap(struct hvn_softc *, struct mbuf *, struct hvn_tx_desc **); > void hvn_decap(struct hvn_softc *, struct hvn_tx_desc *); > void hvn_txeof(struct hvn_softc *, uint64_t); > @@ -266,7 +266,7 @@ hvn_attach(struct device *parent, struct > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = hvn_ioctl; > - ifp->if_start = hvn_start; > + ifp->if_qstart = hvn_start; > ifp->if_softc = sc; > > ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | > @@ -320,7 +320,7 @@ hvn_attach(struct device *parent, struct > hvn_rx_ring_destroy(sc); > hvn_tx_ring_destroy(sc); > hvn_nvs_detach(sc); > - if (ifp->if_start) > + if (ifp->if_qstart) > if_detach(ifp); > } > > @@ -441,23 +441,21 @@ hvn_stop(struct hvn_softc *sc) > } > > void > -hvn_start(struct ifnet *ifp) > +hvn_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct hvn_softc *sc = ifp->if_softc; > struct hvn_tx_desc *txd; > struct mbuf *m; > > - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) > - return; > - > for (;;) { > if (!sc->sc_tx_avail) { > /* transient */ > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > > - m = ifq_dequeue(&ifp->if_snd); > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > Index: dev/pv/if_xnf.c > =================================================================== > RCS file: /cvs/src/sys/dev/pv/if_xnf.c,v > retrieving revision 1.47 > diff -u -p -r1.47 if_xnf.c > --- dev/pv/if_xnf.c 22 Jan 2017 10:17:39 -0000 1.47 > +++ dev/pv/if_xnf.c 23 Jan 2017 06:32:59 -0000 > @@ -199,7 +199,7 @@ void xnf_media_status(struct ifnet *, st > int xnf_iff(struct xnf_softc *); > void xnf_init(struct xnf_softc *); > void xnf_stop(struct xnf_softc *); > -void xnf_start(struct ifnet *); > +void xnf_start(struct ifqueue *); > int xnf_encap(struct xnf_softc *, struct mbuf *, uint32_t *); > void xnf_intr(void *); > void xnf_watchdog(struct ifnet *); > @@ -292,7 +292,7 @@ xnf_attach(struct device *parent, struct > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = xnf_ioctl; > - ifp->if_start = xnf_start; > + ifp->if_qstart = xnf_start; > ifp->if_watchdog = xnf_watchdog; > ifp->if_softc = sc; > > @@ -477,17 +477,15 @@ xnf_stop(struct xnf_softc *sc) > } > > void > -xnf_start(struct ifnet *ifp) > +xnf_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct xnf_softc *sc = ifp->if_softc; > struct xnf_tx_ring *txr = sc->sc_tx_ring; > struct mbuf *m; > int pkts = 0; > uint32_t prod, oprod; > > - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) > - return; > - > bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_rmap, 0, 0, > BUS_DMASYNC_POSTREAD); > > @@ -497,10 +495,11 @@ xnf_start(struct ifnet *ifp) > if ((XNF_TX_DESC - (prod - sc->sc_tx_cons)) < > sc->sc_tx_frags) { > /* transient */ > - ifq_set_oactive(&ifp->if_snd); > + ifq_set_oactive(ifq); > break; > } > - m = ifq_dequeue(&ifp->if_snd); > + > + m = ifq_dequeue(ifq); > if (m == NULL) > break; > > Index: net/hfsc.c > =================================================================== > RCS file: /cvs/src/sys/net/hfsc.c,v > retrieving revision 1.34 > diff -u -p -r1.34 hfsc.c > --- net/hfsc.c 22 Jan 2017 04:48:23 -0000 1.34 > +++ net/hfsc.c 23 Jan 2017 06:32:59 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: hfsc.c,v 1.34 2017/01/22 04:48:23 dlg Exp $ */ > +/* $OpenBSD: hfsc.c,v 1.33 2016/09/15 02:00:18 dlg Exp $ */ > > /* > * Copyright (c) 2012-2013 Henning Brauer <[email protected]> > @@ -259,20 +259,22 @@ struct pool hfsc_class_pl, hfsc_internal > * ifqueue glue. > */ > > -void *hfsc_alloc(void *); > -void hfsc_free(void *); > +unsigned int hfsc_idx(unsigned int, const struct mbuf *); > int hfsc_enq(struct ifqueue *, struct mbuf *); > struct mbuf *hfsc_deq_begin(struct ifqueue *, void **); > void hfsc_deq_commit(struct ifqueue *, struct mbuf *, void *); > void hfsc_purge(struct ifqueue *, struct mbuf_list *); > +void *hfsc_alloc(unsigned int, void *); > +void hfsc_free(unsigned int, void *); > > const struct ifq_ops hfsc_ops = { > - hfsc_alloc, > - hfsc_free, > + hfsc_idx, > hfsc_enq, > hfsc_deq_begin, > hfsc_deq_commit, > hfsc_purge, > + hfsc_alloc, > + hfsc_free, > }; > > const struct ifq_ops * const ifq_hfsc_ops = &hfsc_ops; > @@ -414,13 +416,26 @@ hfsc_pf_qstats(struct pf_queuespec *q, v > void > hfsc_pf_free(struct hfsc_if *hif) > { > - hfsc_free(hif); > + hfsc_free(0, hif); > +} > + > +unsigned int > +hfsc_idx(unsigned int nqueues, const struct mbuf *m) > +{ > + /* > + * hfsc can only function on a single ifq and the stack understands > + * this. when the first ifq on an interface is switched to hfsc, > + * this gets used to map all mbufs to the first and only ifq that > + * is set up for hfsc. > + */ > + return (0); > } > > void * > -hfsc_alloc(void *q) > +hfsc_alloc(unsigned int idx, void *q) > { > struct hfsc_if *hif = q; > + KASSERT(idx == 0); /* when hfsc is enabled we only use the first ifq */ > KASSERT(hif != NULL); > > timeout_add(&hif->hif_defer, 1); > @@ -428,12 +443,13 @@ hfsc_alloc(void *q) > } > > void > -hfsc_free(void *q) > +hfsc_free(unsigned int idx, void *q) > { > struct hfsc_if *hif = q; > int i; > > KERNEL_ASSERT_LOCKED(); > + KASSERT(idx == 0); /* when hfsc is enabled we only use the first ifq */ > > timeout_del(&hif->hif_defer); > > @@ -758,18 +774,16 @@ void > hfsc_deferred(void *arg) > { > struct ifnet *ifp = arg; > + struct ifqueue *ifq = &ifp->if_snd; > struct hfsc_if *hif; > - int s; > > KERNEL_ASSERT_LOCKED(); > - KASSERT(HFSC_ENABLED(&ifp->if_snd)); > + KASSERT(HFSC_ENABLED(ifq)); > > - s = splnet(); > - if (!IFQ_IS_EMPTY(&ifp->if_snd)) > - if_start(ifp); > - splx(s); > + if (!ifq_empty(ifq)) > + (*ifp->if_qstart)(ifq); > > - hif = ifp->if_snd.ifq_q; > + hif = ifq->ifq_q; > > /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */ > timeout_add(&hif->hif_defer, 1); > Index: net/if.c > =================================================================== > RCS file: /cvs/src/sys/net/if.c,v > retrieving revision 1.476 > diff -u -p -r1.476 if.c > --- net/if.c 23 Jan 2017 01:26:09 -0000 1.476 > +++ net/if.c 23 Jan 2017 06:32:59 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: if.c,v 1.476 2017/01/23 01:26:09 dlg Exp $ */ > +/* $OpenBSD: if.c,v 1.474 2017/01/12 09:07:46 mpi Exp $ */ > /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ > > /* > @@ -136,7 +136,7 @@ void if_attach_common(struct ifnet *); > int if_setrdomain(struct ifnet *, int); > void if_slowtimo(void *); > > -void if_detached_start(struct ifnet *); > +void if_detached_qstart(struct ifqueue *); > int if_detached_ioctl(struct ifnet *, u_long, caddr_t); > > int if_getgroup(caddr_t, struct ifnet *); > @@ -161,7 +161,7 @@ void if_netisr(void *); > void ifa_print_all(void); > #endif > > -void if_start_locked(struct ifnet *); > +void if_qstart_compat(struct ifqueue *); > > /* > * interface index map > @@ -527,12 +527,53 @@ if_attach(struct ifnet *ifp) > } > > void > +if_attach_queues(struct ifnet *ifp, unsigned int nqs) > +{ > + struct ifqueue **map; > + struct ifqueue *ifq; > + int i; > + > + KASSERT(ifp->if_ifqs == ifp->if_snd.ifq_ifqs); > + KASSERT(nqs != 0); > + > + map = mallocarray(sizeof(*map), nqs, M_DEVBUF, M_WAITOK); > + > + ifp->if_snd.ifq_softc = NULL; > + map[0] = &ifp->if_snd; > + > + for (i = 1; i < nqs; i++) { > + ifq = malloc(sizeof(*ifq), M_DEVBUF, M_WAITOK|M_ZERO); > + ifq_set_maxlen(ifq, ifp->if_snd.ifq_maxlen); > + ifq_init(ifq, ifp, i); > + map[i] = ifq; > + } > + > + ifp->if_ifqs = map; > + ifp->if_nifqs = nqs; > +} > + > +void > if_attach_common(struct ifnet *ifp) > { > TAILQ_INIT(&ifp->if_addrlist); > TAILQ_INIT(&ifp->if_maddrlist); > > - ifq_init(&ifp->if_snd, ifp); > + if (!ISSET(ifp->if_xflags, IFXF_MPSAFE)) { > + KASSERTMSG(ifp->if_qstart == NULL, > + "%s: if_qstart set without MPSAFE set", ifp->if_xname); > + ifp->if_qstart = if_qstart_compat; > + } else { > + KASSERTMSG(ifp->if_start == NULL, > + "%s: if_start set with MPSAFE set", ifp->if_xname); > + KASSERTMSG(ifp->if_qstart != NULL, > + "%s: if_qstart not set with MPSAFE set", ifp->if_xname); > + } > + > + ifq_init(&ifp->if_snd, ifp, 0); > + > + ifp->if_snd.ifq_ifqs[0] = &ifp->if_snd; > + ifp->if_ifqs = ifp->if_snd.ifq_ifqs; > + ifp->if_nifqs = 1; > > ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks), > M_TEMP, M_WAITOK); > @@ -560,22 +601,44 @@ if_attach_common(struct ifnet *ifp) > } > > void > -if_start(struct ifnet *ifp) > +if_attach_ifq(struct ifnet *ifp, const struct ifq_ops *newops, void *args) > { > - if (ISSET(ifp->if_xflags, IFXF_MPSAFE)) > - ifq_start(&ifp->if_snd); > - else > - if_start_locked(ifp); > + /* > + * only switch the ifq_ops on the first ifq on an interface. > + * > + * the only ifq_ops we provide priq and hfsc, and hfsc only > + * works on a single ifq. because the code uses the ifq_ops > + * on the first ifq (if_snd) to select a queue for an mbuf, > + * by switching only the first one we change both the algorithm > + * and force the routing of all new packets to it. > + */ > + ifq_attach(&ifp->if_snd, newops, args); > } > > void > -if_start_locked(struct ifnet *ifp) > +if_start(struct ifnet *ifp) > +{ > + KASSERT(ifp->if_qstart == if_qstart_compat); > + if_qstart_compat(&ifp->if_snd); > +} > +void > +if_qstart_compat(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > int s; > > + /* > + * the stack assumes that an interface can have multiple > + * transmit rings, but a lot of drivers are still written > + * so that interfaces and send rings have a 1:1 mapping. > + * this provides compatability between the stack and the older > + * drivers by translating from the only queue they have > + * (ifp->if_snd) back to the interface and calling if_start. > + */ > + > KERNEL_LOCK(); > s = splnet(); > - ifp->if_start(ifp); > + (*ifp->if_start)(ifp); > splx(s); > KERNEL_UNLOCK(); > } > @@ -583,7 +646,9 @@ if_start_locked(struct ifnet *ifp) > int > if_enqueue(struct ifnet *ifp, struct mbuf *m) > { > - int error = 0; > + unsigned int idx; > + struct ifqueue *ifq; > + int error; > > #if NBRIDGE > 0 > if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) { > @@ -599,14 +664,17 @@ if_enqueue(struct ifnet *ifp, struct mbu > #endif /* NPF > 0 */ > > /* > - * Queue message on interface, and start output if interface > - * not yet active. > + * use the operations on the first ifq to pick which of the array > + * gets this mbuf. > */ > - IFQ_ENQUEUE(&ifp->if_snd, m, error); > + idx = ifq_idx(&ifp->if_snd, ifp->if_nifqs, m); > + ifq = ifp->if_ifqs[idx]; > + > + error = ifq_enqueue(ifq, m); > if (error) > return (error); > > - if_start(ifp); > + ifq_start(ifq); > > return (0); > } > @@ -942,7 +1010,7 @@ if_detach(struct ifnet *ifp) > /* Other CPUs must not have a reference before we start destroying. */ > if_idxmap_remove(ifp); > > - ifp->if_start = if_detached_start; > + ifp->if_qstart = if_detached_qstart; > ifp->if_ioctl = if_detached_ioctl; > ifp->if_watchdog = NULL; > > @@ -1016,7 +1084,16 @@ if_detach(struct ifnet *ifp) > splx(s2); > NET_UNLOCK(s); > > - ifq_destroy(&ifp->if_snd); > + for (i = 0; i < ifp->if_nifqs; i++) > + ifq_destroy(ifp->if_ifqs[i]); > + if (ifp->if_ifqs != ifp->if_snd.ifq_ifqs) { > + for (i = 1; i < ifp->if_nifqs; i++) { > + free(ifp->if_ifqs[i], M_DEVBUF, > + sizeof(struct ifqueue)); > + } > + free(ifp->if_ifqs, M_DEVBUF, > + sizeof(struct ifqueue *) * ifp->if_nifqs); > + } > } > > /* > @@ -2165,21 +2242,24 @@ ifconf(u_long cmd, caddr_t data) > void > if_data(struct ifnet *ifp, struct if_data *data) > { > + unsigned int i; > struct ifqueue *ifq; > uint64_t opackets = 0; > uint64_t obytes = 0; > uint64_t omcasts = 0; > uint64_t oqdrops = 0; > > - ifq = &ifp->if_snd; > + for (i = 0; i < ifp->if_nifqs; i++) { > + ifq = ifp->if_ifqs[i]; > > - mtx_enter(&ifq->ifq_mtx); > - opackets += ifq->ifq_packets; > - obytes += ifq->ifq_bytes; > - oqdrops += ifq->ifq_qdrops; > - omcasts += ifq->ifq_mcasts; > - /* ifq->ifq_errors */ > - mtx_leave(&ifq->ifq_mtx); > + mtx_enter(&ifq->ifq_mtx); > + opackets += ifq->ifq_packets; > + obytes += ifq->ifq_bytes; > + oqdrops += ifq->ifq_qdrops; > + omcasts += ifq->ifq_mcasts; > + mtx_leave(&ifq->ifq_mtx); > + /* ifq->ifq_errors */ > + } > > *data = ifp->if_data; > data->ifi_opackets += opackets; > @@ -2194,9 +2274,9 @@ if_data(struct ifnet *ifp, struct if_dat > * fiddle with the if during detach. > */ > void > -if_detached_start(struct ifnet *ifp) > +if_detached_qstart(struct ifqueue *ifq) > { > - IFQ_PURGE(&ifp->if_snd); > + ifq_purge(ifq); > } > > int > Index: net/if.h > =================================================================== > RCS file: /cvs/src/sys/net/if.h,v > retrieving revision 1.182 > diff -u -p -r1.182 if.h > --- net/if.h 23 Jan 2017 01:26:09 -0000 1.182 > +++ net/if.h 23 Jan 2017 06:32:59 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: if.h,v 1.182 2017/01/23 01:26:09 dlg Exp $ */ > +/* $OpenBSD: if.h,v 1.181 2016/12/12 09:51:30 mpi Exp $ */ > /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ > > /* > @@ -456,10 +456,13 @@ struct if_parent { > #ifdef _KERNEL > struct socket; > struct ifnet; > +struct ifq_ops; > > void if_alloc_sadl(struct ifnet *); > void if_free_sadl(struct ifnet *); > void if_attach(struct ifnet *); > +void if_attach_queues(struct ifnet *, unsigned int); > +void if_attach_ifq(struct ifnet *, const struct ifq_ops *, void *); > void if_attachtail(struct ifnet *); > void if_attachhead(struct ifnet *); > void if_deactivate(struct ifnet *); > Index: net/if_mpw.c > =================================================================== > RCS file: /cvs/src/sys/net/if_mpw.c,v > retrieving revision 1.16 > diff -u -p -r1.16 if_mpw.c > --- net/if_mpw.c 20 Dec 2016 12:18:44 -0000 1.16 > +++ net/if_mpw.c 23 Jan 2017 06:32:59 -0000 > @@ -332,7 +332,7 @@ mpw_output(struct ifnet *ifp, struct mbu > } > > #if NVLAN > 0 > -extern void vlan_start(struct ifnet *ifp); > +extern void vlan_start(struct ifqueue *); > > /* > * This routine handles VLAN tag reinsertion in packets flowing through > @@ -349,7 +349,7 @@ mpw_vlan_handle(struct mbuf *m, struct m > uint16_t tag = 0; > > ifp = if_get(m->m_pkthdr.ph_ifidx); > - if (ifp != NULL && ifp->if_start == vlan_start && > + if (ifp != NULL && ifp->if_qstart == vlan_start && > ISSET(ifp->if_flags, IFF_RUNNING)) { > ifv = ifp->if_softc; > type = ifv->ifv_type; > Index: net/if_var.h > =================================================================== > RCS file: /cvs/src/sys/net/if_var.h,v > retrieving revision 1.79 > diff -u -p -r1.79 if_var.h > --- net/if_var.h 21 Jan 2017 01:32:19 -0000 1.79 > +++ net/if_var.h 23 Jan 2017 06:32:59 -0000 > @@ -157,7 +157,12 @@ struct ifnet { /* and the > entries */ > /* timer routine */ > void (*if_watchdog)(struct ifnet *); > int (*if_wol)(struct ifnet *, int); > - struct ifqueue if_snd; /* output queue */ > + > + struct ifqueue if_snd; /* transmit queue */ > + struct ifqueue **if_ifqs; /* pointer to an array of sndqs */ > + void (*if_qstart)(struct ifqueue *); > + unsigned int if_nifqs; > + > struct sockaddr_dl *if_sadl; /* pointer to our sockaddr_dl */ > > void *if_afdata[AF_MAX]; > Index: net/if_vlan.c > =================================================================== > RCS file: /cvs/src/sys/net/if_vlan.c,v > retrieving revision 1.168 > diff -u -p -r1.168 if_vlan.c > --- net/if_vlan.c 22 Jan 2017 10:17:39 -0000 1.168 > +++ net/if_vlan.c 23 Jan 2017 06:32:59 -0000 > @@ -85,7 +85,7 @@ int vlan_clone_create(struct if_clone *, > int vlan_clone_destroy(struct ifnet *); > > int vlan_input(struct ifnet *, struct mbuf *, void *); > -void vlan_start(struct ifnet *ifp); > +void vlan_start(struct ifqueue *ifq); > int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); > > int vlan_up(struct ifvlan *); > @@ -175,7 +175,7 @@ vlan_clone_create(struct if_clone *ifc, > > ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; > ifp->if_xflags = IFXF_MPSAFE; > - ifp->if_start = vlan_start; > + ifp->if_qstart = vlan_start; > ifp->if_ioctl = vlan_ioctl; > ifp->if_hardmtu = 0xffff; > ifp->if_link_state = LINK_STATE_DOWN; > @@ -238,8 +238,9 @@ vlan_mplstunnel(int ifidx) > } > > void > -vlan_start(struct ifnet *ifp) > +vlan_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct ifvlan *ifv; > struct ifnet *ifp0; > struct mbuf *m; > @@ -249,15 +250,11 @@ vlan_start(struct ifnet *ifp) > ifp0 = if_get(ifv->ifv_ifp0); > if (ifp0 == NULL || (ifp0->if_flags & (IFF_UP|IFF_RUNNING)) != > (IFF_UP|IFF_RUNNING)) { > - ifq_purge(&ifp->if_snd); > + ifq_purge(ifq); > goto leave; > } > > - for (;;) { > - IFQ_DEQUEUE(&ifp->if_snd, m); > - if (m == NULL) > - break; > - > + while ((m = ifq_dequeue(ifq)) != NULL) { > #if NBPFILTER > 0 > if (ifp->if_bpf) > bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); > @@ -296,6 +293,7 @@ vlan_start(struct ifnet *ifp) > > if (if_enqueue(ifp0, m)) { > ifp->if_oerrors++; > + ifq->ifq_errors++; > continue; > } > } > Index: net/ifq.c > =================================================================== > RCS file: /cvs/src/sys/net/ifq.c,v > retrieving revision 1.5 > diff -u -p -r1.5 ifq.c > --- net/ifq.c 20 Jan 2017 03:48:03 -0000 1.5 > +++ net/ifq.c 23 Jan 2017 06:32:59 -0000 > @@ -28,20 +28,23 @@ > /* > * priq glue > */ > -void *priq_alloc(void *); > -void priq_free(void *); > +unsigned int priq_idx(unsigned int, const struct mbuf *); > int priq_enq(struct ifqueue *, struct mbuf *); > struct mbuf *priq_deq_begin(struct ifqueue *, void **); > void priq_deq_commit(struct ifqueue *, struct mbuf *, void *); > void priq_purge(struct ifqueue *, struct mbuf_list *); > > +void *priq_alloc(unsigned int, void *); > +void priq_free(unsigned int, void *); > + > const struct ifq_ops priq_ops = { > - priq_alloc, > - priq_free, > + priq_idx, > priq_enq, > priq_deq_begin, > priq_deq_commit, > priq_purge, > + priq_alloc, > + priq_free, > }; > > const struct ifq_ops * const ifq_priq_ops = &priq_ops; > @@ -119,7 +122,7 @@ ifq_start_task(void *p) > ifq_empty(ifq) || ifq_is_oactive(ifq)) > return; > > - ifp->if_start(ifp); > + ifp->if_qstart(ifq); > } > > void > @@ -129,7 +132,7 @@ ifq_restart_task(void *p) > struct ifnet *ifp = ifq->ifq_if; > > ifq_clr_oactive(ifq); > - ifp->if_start(ifp); > + ifp->if_qstart(ifq); > } > > void > @@ -167,19 +170,26 @@ ifq_barrier_task(void *p) > */ > > void > -ifq_init(struct ifqueue *ifq, struct ifnet *ifp) > +ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx) > { > ifq->ifq_if = ifp; > + ifq->ifq_softc = NULL; > > mtx_init(&ifq->ifq_mtx, IPL_NET); > ifq->ifq_qdrops = 0; > > /* default to priq */ > ifq->ifq_ops = &priq_ops; > - ifq->ifq_q = priq_ops.ifqop_alloc(NULL); > + ifq->ifq_q = priq_ops.ifqop_alloc(idx, NULL); > > ifq->ifq_len = 0; > > + ifq->ifq_packets = 0; > + ifq->ifq_bytes = 0; > + ifq->ifq_qdrops = 0; > + ifq->ifq_errors = 0; > + ifq->ifq_mcasts = 0; > + > mtx_init(&ifq->ifq_task_mtx, IPL_NET); > TAILQ_INIT(&ifq->ifq_task_list); > ifq->ifq_serializer = NULL; > @@ -189,6 +199,8 @@ ifq_init(struct ifqueue *ifq, struct ifn > > if (ifq->ifq_maxlen == 0) > ifq_set_maxlen(ifq, IFQ_MAXLEN); > + > + ifq->ifq_idx = idx; > } > > void > @@ -200,7 +212,7 @@ ifq_attach(struct ifqueue *ifq, const st > const struct ifq_ops *oldops; > void *newq, *oldq; > > - newq = newops->ifqop_alloc(opsarg); > + newq = newops->ifqop_alloc(ifq->ifq_idx, opsarg); > > mtx_enter(&ifq->ifq_mtx); > ifq->ifq_ops->ifqop_purge(ifq, &ml); > @@ -221,7 +233,7 @@ ifq_attach(struct ifqueue *ifq, const st > } > mtx_leave(&ifq->ifq_mtx); > > - oldops->ifqop_free(oldq); > + oldops->ifqop_free(ifq->ifq_idx, oldq); > > ml_purge(&free_ml); > } > @@ -234,7 +246,7 @@ ifq_destroy(struct ifqueue *ifq) > /* don't need to lock because this is the last use of the ifq */ > > ifq->ifq_ops->ifqop_purge(ifq, &ml); > - ifq->ifq_ops->ifqop_free(ifq->ifq_q); > + ifq->ifq_ops->ifqop_free(ifq->ifq_idx, ifq->ifq_q); > > ml_purge(&ml); > } > @@ -368,14 +380,25 @@ ifq_q_leave(struct ifqueue *ifq, void *q > * priq implementation > */ > > +unsigned int > +priq_idx(unsigned int nqueues, const struct mbuf *m) > +{ > + unsigned int flow = 0; > + > + if (ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID)) > + flow = m->m_pkthdr.ph_flowid & M_FLOWID_MASK; > + > + return (flow % nqueues); > +} > + > void * > -priq_alloc(void *null) > +priq_alloc(unsigned int idx, void *null) > { > return (malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK | M_ZERO)); > } > > void > -priq_free(void *pq) > +priq_free(unsigned int idx, void *pq) > { > free(pq, M_DEVBUF, sizeof(struct priq)); > } > Index: net/ifq.h > =================================================================== > RCS file: /cvs/src/sys/net/ifq.h,v > retrieving revision 1.7 > diff -u -p -r1.7 ifq.h > --- net/ifq.h 22 Jan 2017 04:48:23 -0000 1.7 > +++ net/ifq.h 23 Jan 2017 06:32:59 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: ifq.h,v 1.7 2017/01/22 04:48:23 dlg Exp $ */ > +/* $OpenBSD: ifq.h,v 1.6 2017/01/20 03:48:03 dlg Exp $ */ > > /* > * Copyright (c) 2015 David Gwynne <[email protected]> > @@ -25,6 +25,18 @@ struct ifq_ops; > > struct ifqueue { > struct ifnet *ifq_if; > + union { > + void *_ifq_softc; > + /* > + * a rings sndq is found by looking up an array of pointers. > + * by default we only have one sndq and the default drivers > + * dont use ifq_softc, so we can borrow it for the map until > + * we need to allocate a proper map. > + */ > + struct ifqueue *_ifq_ifqs[1]; > + } _ifq_ptr; > +#define ifq_softc _ifq_ptr._ifq_softc > +#define ifq_ifqs _ifq_ptr._ifq_ifqs > > /* mbuf handling */ > struct mutex ifq_mtx; > @@ -49,7 +61,9 @@ struct ifqueue { > struct task ifq_start; > struct task ifq_restart; > > + /* properties */ > unsigned int ifq_maxlen; > + unsigned int ifq_idx; > }; > > #ifdef _KERNEL > @@ -308,21 +322,23 @@ struct ifqueue { > */ > > struct ifq_ops { > - void *(*ifqop_alloc)(void *); > - void (*ifqop_free)(void *); > + unsigned int (*ifqop_idx)(unsigned int, > + const struct mbuf *); > int (*ifqop_enq)(struct ifqueue *, struct mbuf *); > struct mbuf *(*ifqop_deq_begin)(struct ifqueue *, void **); > void (*ifqop_deq_commit)(struct ifqueue *, > struct mbuf *, void *); > void (*ifqop_purge)(struct ifqueue *, > struct mbuf_list *); > + void *(*ifqop_alloc)(unsigned int, void *); > + void (*ifqop_free)(unsigned int, void *); > }; > > /* > * Interface send queues. > */ > > -void ifq_init(struct ifqueue *, struct ifnet *); > +void ifq_init(struct ifqueue *, struct ifnet *, unsigned int); > void ifq_attach(struct ifqueue *, const struct ifq_ops *, void *); > void ifq_destroy(struct ifqueue *); > int ifq_enqueue_try(struct ifqueue *, struct mbuf *); > @@ -370,6 +386,12 @@ static inline void > ifq_restart(struct ifqueue *ifq) > { > ifq_serialize(ifq, &ifq->ifq_restart); > +} > + > +static inline unsigned int > +ifq_idx(struct ifqueue *ifq, unsigned int nifqs, const struct mbuf *m) > +{ > + return ((*ifq->ifq_ops->ifqop_idx)(nifqs, m)); > } > > #define IFQ_ASSERT_SERIALIZED(_ifq) KASSERT(ifq_is_serialized(_ifq)) > >
