diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/hfsc.c | 44 | ||||
-rw-r--r-- | sys/net/if.c | 136 | ||||
-rw-r--r-- | sys/net/if.h | 5 | ||||
-rw-r--r-- | sys/net/if_mpw.c | 6 | ||||
-rw-r--r-- | sys/net/if_var.h | 9 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 18 | ||||
-rw-r--r-- | sys/net/ifq.c | 51 | ||||
-rw-r--r-- | sys/net/ifq.h | 30 |
8 files changed, 222 insertions, 77 deletions
diff --git a/sys/net/hfsc.c b/sys/net/hfsc.c index 447ca4f9cd0..f8e67722bb7 100644 --- a/sys/net/hfsc.c +++ b/sys/net/hfsc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hfsc.c,v 1.34 2017/01/22 04:48:23 dlg Exp $ */ +/* $OpenBSD: hfsc.c,v 1.35 2017/01/24 03:57:35 dlg Exp $ */ /* * Copyright (c) 2012-2013 Henning Brauer <henning@openbsd.org> @@ -259,20 +259,22 @@ struct pool hfsc_class_pl, hfsc_internal_sc_pl; * 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, void *ubuf, int *nbytes) 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); diff --git a/sys/net/if.c b/sys/net/if.c index b01f9a539d5..3e10955e1be 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.478 2017/01/23 11:37:29 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.479 2017/01/24 03:57:35 dlg 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 mbuf *m) #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); } @@ -943,7 +1011,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; @@ -1017,7 +1085,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); + } } /* @@ -2166,21 +2243,24 @@ ifconf(u_long cmd, caddr_t data) void if_getdata(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; @@ -2195,9 +2275,9 @@ if_getdata(struct ifnet *ifp, struct if_data *data) * 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 diff --git a/sys/net/if.h b/sys/net/if.h index cbc25aaecb5..549f854993a 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.184 2017/01/23 11:37:29 mpi Exp $ */ +/* $OpenBSD: if.h,v 1.185 2017/01/24 03:57:35 dlg Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -457,10 +457,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 *); diff --git a/sys/net/if_mpw.c b/sys/net/if_mpw.c index cd51b2387e9..aaabf84498f 100644 --- a/sys/net/if_mpw.c +++ b/sys/net/if_mpw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mpw.c,v 1.17 2017/01/23 11:37:29 mpi Exp $ */ +/* $OpenBSD: if_mpw.c,v 1.18 2017/01/24 03:57:35 dlg Exp $ */ /* * Copyright (c) 2015 Rafael Zalamena <rzalamena@openbsd.org> @@ -333,7 +333,7 @@ mpw_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, } #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 @@ -350,7 +350,7 @@ mpw_vlan_handle(struct mbuf *m, struct mpw_softc *sc) 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; diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 3059acef552..dab939a648c 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_var.h,v 1.79 2017/01/21 01:32:19 patrick Exp $ */ +/* $OpenBSD: if_var.h,v 1.80 2017/01/24 03:57:35 dlg Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -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]; diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 8ec731e89c3..a0166e6b8c7 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.169 2017/01/23 11:37:29 mpi Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.170 2017/01/24 03:57:35 dlg Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -85,7 +85,7 @@ int vlan_clone_create(struct if_clone *, int); 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, int unit) ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED|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; } } diff --git a/sys/net/ifq.c b/sys/net/ifq.c index e92d6f09490..40731637a2c 100644 --- a/sys/net/ifq.c +++ b/sys/net/ifq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.c,v 1.5 2017/01/20 03:48:03 dlg Exp $ */ +/* $OpenBSD: ifq.c,v 1.6 2017/01/24 03:57:35 dlg Exp $ */ /* * Copyright (c) 2015 David Gwynne <dlg@openbsd.org> @@ -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 ifnet *ifp) 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 struct ifq_ops *newops, void *opsarg) 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 struct ifq_ops *newops, void *opsarg) } 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)); } diff --git a/sys/net/ifq.h b/sys/net/ifq.h index 4dbef36090e..d159f80d0fe 100644 --- a/sys/net/ifq.h +++ b/sys/net/ifq.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.h,v 1.7 2017/01/22 04:48:23 dlg Exp $ */ +/* $OpenBSD: ifq.h,v 1.8 2017/01/24 03:57:35 dlg Exp $ */ /* * Copyright (c) 2015 David Gwynne <dlg@openbsd.org> @@ -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 *); @@ -372,6 +388,12 @@ 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)) extern const struct ifq_ops * const ifq_priq_ops; |