diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2017-01-24 03:57:36 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2017-01-24 03:57:36 +0000 |
commit | 38e410c3ec2b9ed68bafb194f1a842cc049bc486 (patch) | |
tree | 04130c870954194face9f3e0397be2ded92d2471 /sys/net | |
parent | d9fc778f44a5b33d674263219b50b7126e81c30c (diff) |
add support for multiple transmit ifqueues per network interface.
an ifq to transmit a packet is picked by the current traffic
conditioner (ie, priq or hfsc) by providing an index into an array
of ifqs. by default interfaces get a single ifq but can ask for
more using if_attach_queues().
the vast majority of our drivers still think there's a 1:1 mapping
between interfaces and transmit queues, so their if_start routines
take an ifnet pointer instead of a pointer to the ifqueue struct.
instead of changing all the drivers in the tree, drivers can opt
into using an if_qstart routine and setting the IFXF_MPSAFE flag.
the stack provides a compatability wrapper from the new if_qstart
handler to the previous if_start handlers if IFXF_MPSAFE isnt set.
enabling hfsc on an interface configures it to transmit everything
through the first ifq. any other ifqs are left configured as priq,
but unused, when hfsc is enabled.
getting this in now so everyone can kick the tyres.
ok mpi@ visa@ (who provided some tweaks for cnmac).
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; |