/*
- * Copyright (c) 2011-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/pktsched/pktsched_qfq.h>
#include <netinet/in.h>
+
/*
* function prototypes
*/
-static int qfq_enqueue_ifclassq(struct ifclassq *, struct mbuf *);
-static struct mbuf *qfq_dequeue_ifclassq(struct ifclassq *, cqdq_op_t);
+static int qfq_enqueue_ifclassq(struct ifclassq *, void *, classq_pkt_type_t,
+ boolean_t *);
+static void *qfq_dequeue_ifclassq(struct ifclassq *, classq_pkt_type_t *);
static int qfq_request_ifclassq(struct ifclassq *, cqrq_t, void *);
static int qfq_clear_interface(struct qfq_if *);
static struct qfq_class *qfq_class_create(struct qfq_if *, u_int32_t,
- u_int32_t, u_int32_t, u_int32_t, u_int32_t);
+ u_int32_t, u_int32_t, u_int32_t, u_int32_t, classq_pkt_type_t);
static int qfq_class_destroy(struct qfq_if *, struct qfq_class *);
static int qfq_destroy_locked(struct qfq_if *);
-static inline int qfq_addq(struct qfq_class *, struct mbuf *, struct pf_mtag *);
-static inline struct mbuf *qfq_getq(struct qfq_class *);
-static inline struct mbuf *qfq_pollq(struct qfq_class *);
+static inline int qfq_addq(struct qfq_class *, pktsched_pkt_t *,
+ struct pf_mtag *);
+static inline void qfq_getq(struct qfq_class *, pktsched_pkt_t *);
static void qfq_purgeq(struct qfq_if *, struct qfq_class *, u_int32_t,
u_int32_t *, u_int32_t *);
static void qfq_purge_sc(struct qfq_if *, cqrq_purge_sc_t *);
static int qfq_throttle(struct qfq_if *, cqrq_throttle_t *);
static int qfq_resumeq(struct qfq_if *, struct qfq_class *);
static int qfq_suspendq(struct qfq_if *, struct qfq_class *);
+static int qfq_stat_sc(struct qfq_if *, cqrq_stat_sc_t *);
static inline struct qfq_class *qfq_clh_to_clp(struct qfq_if *, u_int32_t);
static const char *qfq_style(struct qfq_if *);
}
struct qfq_if *
-qfq_alloc(struct ifnet *ifp, int how, boolean_t altq)
+qfq_alloc(struct ifnet *ifp, int how)
{
struct qfq_if *qif;
bzero(qif, qfq_size);
qif->qif_ifq = &ifp->if_snd;
- if (altq) {
- qif->qif_maxclasses = QFQ_MAX_CLASSES;
- qif->qif_maxslots = QFQ_MAX_SLOTS;
- qif->qif_flags |= QFQIFF_ALTQ;
- } else {
- qif->qif_maxclasses = IFCQ_SC_MAX;
- /*
- * TODO: adi@apple.com
- *
- * Ideally I would like to have the following
- * but QFQ needs further modifications.
- *
- * qif->qif_maxslots = IFCQ_SC_MAX;
- */
- qif->qif_maxslots = QFQ_MAX_SLOTS;
- }
+
+ qif->qif_maxclasses = IFCQ_SC_MAX;
+ /*
+ * TODO: adi@apple.com
+ *
+ * Ideally I would like to have the following
+ * but QFQ needs further modifications.
+ *
+ * qif->qif_maxslots = IFCQ_SC_MAX;
+ */
+ qif->qif_maxslots = QFQ_MAX_SLOTS;
if ((qif->qif_class_tbl = _MALLOC(sizeof (struct qfq_class *) *
qif->qif_maxclasses, M_DEVBUF, M_WAITOK|M_ZERO)) == NULL) {
if ((cl = qif->qif_class_tbl[i]) != NULL)
qfq_purgeq(qif, cl, 0, NULL, NULL);
}
-#if !PF_ALTQ
- /*
- * This assertion is safe to be made only when PF_ALTQ is not
- * configured; otherwise, IFCQ_LEN represents the sum of the
- * packets managed by ifcq_disc and altq_disc instances, which
- * is possible when transitioning between the two.
- */
VERIFY(IFCQ_LEN(qif->qif_ifq) == 0);
-#endif /* !PF_ALTQ */
}
static void
int
qfq_add_queue(struct qfq_if *qif, u_int32_t qlimit, u_int32_t weight,
- u_int32_t maxsz, u_int32_t flags, u_int32_t qid, struct qfq_class **clp)
+ u_int32_t maxsz, u_int32_t flags, u_int32_t qid, struct qfq_class **clp,
+ classq_pkt_type_t ptype)
{
struct qfq_class *cl;
u_int32_t w;
if (maxsz == 0 || maxsz > (1 << QFQ_MTU_SHIFT))
return (EINVAL);
- cl = qfq_class_create(qif, weight, qlimit, flags, maxsz, qid);
+ cl = qfq_class_create(qif, weight, qlimit, flags, maxsz, qid, ptype);
if (cl == NULL)
return (ENOMEM);
static struct qfq_class *
qfq_class_create(struct qfq_if *qif, u_int32_t weight, u_int32_t qlimit,
- u_int32_t flags, u_int32_t maxsz, u_int32_t qid)
+ u_int32_t flags, u_int32_t maxsz, u_int32_t qid, classq_pkt_type_t ptype)
{
struct ifnet *ifp;
struct ifclassq *ifq;
IFCQ_LOCK_ASSERT_HELD(qif->qif_ifq);
- /* Sanitize flags unless internally configured */
- if (qif->qif_flags & QFQIFF_ALTQ)
- flags &= QFCF_USERFLAGS;
-
if (qif->qif_classes >= qif->qif_maxclasses) {
log(LOG_ERR, "%s: %s out of classes! (max %d)\n",
if_name(QFQIF_IFP(qif)), qfq_style(qif),
return (NULL);
}
-#if !CLASSQ_RED
- if (flags & QFCF_RED) {
- log(LOG_ERR, "%s: %s RED not available!\n",
- if_name(QFQIF_IFP(qif)), qfq_style(qif));
- return (NULL);
- }
-#endif /* !CLASSQ_RED */
-
-#if !CLASSQ_RIO
- if (flags & QFCF_RIO) {
- log(LOG_ERR, "%s: %s RIO not available!\n",
- if_name(QFQIF_IFP(qif)), qfq_style(qif));
- return (NULL);
- }
-#endif /* CLASSQ_RIO */
-
-#if !CLASSQ_BLUE
- if (flags & QFCF_BLUE) {
- log(LOG_ERR, "%s: %s BLUE not available!\n",
- if_name(QFQIF_IFP(qif)), qfq_style(qif));
- return (NULL);
- }
-#endif /* CLASSQ_BLUE */
-
- /* These are mutually exclusive */
- if ((flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) &&
- (flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) != QFCF_RED &&
- (flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) != QFCF_RIO &&
- (flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) != QFCF_BLUE &&
- (flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) != QFCF_SFB) {
- log(LOG_ERR, "%s: %s more than one RED|RIO|BLUE|SFB\n",
- if_name(QFQIF_IFP(qif)), qfq_style(qif));
- return (NULL);
- }
-
ifq = qif->qif_ifq;
ifp = QFQIF_IFP(qif);
if (qlimit == 0)
qlimit = DEFAULT_QLIMIT; /* use default */
}
- _qinit(&cl->cl_q, Q_DROPTAIL, qlimit);
+ _qinit(&cl->cl_q, Q_DROPTAIL, qlimit, ptype);
cl->cl_qif = qif;
cl->cl_flags = flags;
cl->cl_handle = qid;
if (flags & QFCF_DEFAULTCLASS)
qif->qif_default = cl;
- if (flags & (QFCF_RED|QFCF_RIO|QFCF_BLUE|QFCF_SFB)) {
-#if CLASSQ_RED || CLASSQ_RIO
- u_int64_t ifbandwidth = ifnet_output_linkrate(ifp);
- int pkttime;
-#endif /* CLASSQ_RED || CLASSQ_RIO */
-
+ if (flags & QFCF_SFB) {
cl->cl_qflags = 0;
if (flags & QFCF_ECN) {
- if (flags & QFCF_BLUE)
- cl->cl_qflags |= BLUEF_ECN;
- else if (flags & QFCF_SFB)
- cl->cl_qflags |= SFBF_ECN;
- else if (flags & QFCF_RED)
- cl->cl_qflags |= REDF_ECN;
- else if (flags & QFCF_RIO)
- cl->cl_qflags |= RIOF_ECN;
+ cl->cl_qflags |= SFBF_ECN;
}
if (flags & QFCF_FLOWCTL) {
- if (flags & QFCF_SFB)
- cl->cl_qflags |= SFBF_FLOWCTL;
- }
- if (flags & QFCF_CLEARDSCP) {
- if (flags & QFCF_RIO)
- cl->cl_qflags |= RIOF_CLEARDSCP;
+ cl->cl_qflags |= SFBF_FLOWCTL;
}
-#if CLASSQ_RED || CLASSQ_RIO
- /*
- * XXX: RED & RIO should be watching link speed and MTU
- * events and recompute pkttime accordingly.
- */
- if (ifbandwidth < 8)
- pkttime = 1000 * 1000 * 1000; /* 1 sec */
- else
- pkttime = (int64_t)ifp->if_mtu * 1000 * 1000 * 1000 /
- (ifbandwidth / 8);
-
- /* Test for exclusivity {RED,RIO,BLUE,SFB} was done above */
-#if CLASSQ_RED
- if (flags & QFCF_RED) {
- cl->cl_red = red_alloc(ifp, 0, 0,
- qlimit(&cl->cl_q) * 10/100,
- qlimit(&cl->cl_q) * 30/100,
- cl->cl_qflags, pkttime);
- if (cl->cl_red != NULL)
- qtype(&cl->cl_q) = Q_RED;
- }
-#endif /* CLASSQ_RED */
-#if CLASSQ_RIO
- if (flags & QFCF_RIO) {
- cl->cl_rio =
- rio_alloc(ifp, 0, NULL, cl->cl_qflags, pkttime);
- if (cl->cl_rio != NULL)
- qtype(&cl->cl_q) = Q_RIO;
- }
-#endif /* CLASSQ_RIO */
-#endif /* CLASSQ_RED || CLASSQ_RIO */
-#if CLASSQ_BLUE
- if (flags & QFCF_BLUE) {
- cl->cl_blue = blue_alloc(ifp, 0, 0, cl->cl_qflags);
- if (cl->cl_blue != NULL)
- qtype(&cl->cl_q) = Q_BLUE;
- }
-#endif /* CLASSQ_BLUE */
- if (flags & QFCF_SFB) {
- if (!(cl->cl_flags & QFCF_LAZY))
- cl->cl_sfb = sfb_alloc(ifp, cl->cl_handle,
- qlimit(&cl->cl_q), cl->cl_qflags);
- if (cl->cl_sfb != NULL || (cl->cl_flags & QFCF_LAZY))
- qtype(&cl->cl_q) = Q_SFB;
+ if (flags & QFCF_DELAYBASED) {
+ cl->cl_qflags |= SFBF_DELAYBASED;
}
+ if (!(cl->cl_flags & QFCF_LAZY))
+ cl->cl_sfb = sfb_alloc(ifp, cl->cl_handle,
+ qlimit(&cl->cl_q), cl->cl_qflags);
+ if (cl->cl_sfb != NULL || (cl->cl_flags & QFCF_LAZY))
+ qtype(&cl->cl_q) = Q_SFB;
}
if (pktsched_verbose) {
{
struct ifclassq *ifq = qif->qif_ifq;
int i;
+#if !MACH_ASSERT
+#pragma unused(ifq)
+#endif
IFCQ_LOCK_ASSERT_HELD(ifq);
qif->qif_classes--;
if (cl->cl_qalg.ptr != NULL) {
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- rio_destroy(cl->cl_rio);
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- red_destroy(cl->cl_red);
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- blue_destroy(cl->cl_blue);
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
sfb_destroy(cl->cl_sfb);
cl->cl_qalg.ptr = NULL;
u_int32_t len;
u_int64_t roundedS;
- len = m_pktlen(qhead(&cl->cl_q));
+ len = m_pktlen((struct mbuf *)qhead(&cl->cl_q));
cl->cl_F = cl->cl_S + (u_int64_t)len * cl->cl_inv_w;
roundedS = qfq_round_down(cl->cl_S, grp->qfg_slot_shift);
if (roundedS == grp->qfg_S)
* CLASSQDQ_REMOVE must return the same packet if called immediately
* after CLASSQDQ_POLL.
*/
-struct mbuf *
-qfq_dequeue(struct qfq_if *qif, cqdq_op_t op)
+void
+qfq_dequeue(struct qfq_if *qif, pktsched_pkt_t *pkt)
{
pktsched_bitmap_t er_bits = qif->qif_bitmaps[ER];
struct ifclassq *ifq = qif->qif_ifq;
struct qfq_group *grp;
struct qfq_class *cl;
- struct mbuf *m;
u_int64_t old_V;
u_int32_t len;
IFCQ_LOCK_ASSERT_HELD(ifq);
+ pkt->pktsched_pkt = NULL;
+
for (;;) {
if (er_bits == 0) {
#if QFQ_DEBUG
qfq_dump_sched(qif, "start dequeue");
#endif /* QFQ_DEBUG */
/* no eligible and ready packet */
- return (NULL);
+ return;
}
grp = qfq_ffs(qif, er_bits);
/* if group is non-empty, use it */
cl = grp->qfg_slots[grp->qfg_front];
VERIFY(cl != NULL && !qempty(&cl->cl_q));
- if (op == CLASSQDQ_POLL)
- return (qfq_pollq(cl));
-
- m = qfq_getq(cl);
- VERIFY(m != NULL); /* qalg must be work conserving */
- len = m_pktlen(m);
+ qfq_getq(cl, pkt);
+ VERIFY(pkt->pktsched_pkt != NULL); /* qalg must be work conserving */
+ len = pktsched_get_pkt_len(pkt);
#if QFQ_DEBUG
qif->qif_queued--;
#endif /* QFQ_DEBUG */
IFCQ_DEC_LEN(ifq);
+ IFCQ_DEC_BYTES(ifq, len);
if (qempty(&cl->cl_q))
cl->cl_period++;
PKTCNTR_ADD(&cl->cl_xmitcnt, 1, len);
qif->qif_V += (u_int64_t)len * QFQ_IWSUM;
if (pktsched_verbose > 2) {
- log(LOG_DEBUG, "%s: %s qid=%d dequeue m=%p F=0x%llx V=0x%llx",
- if_name(QFQIF_IFP(qif)), qfq_style(qif), cl->cl_handle,
- m, cl->cl_F, qif->qif_V);
+ log(LOG_DEBUG, "%s: %s qid=%d dequeue pkt=0x%llx F=0x%llx "
+ "V=0x%llx", if_name(QFQIF_IFP(qif)), qfq_style(qif),
+ cl->cl_handle,
+ (uint64_t)VM_KERNEL_ADDRPERM(pkt->pktsched_pkt), cl->cl_F,
+ qif->qif_V);
}
if (qfq_update_class(qif, grp, cl)) {
if (!qif->qif_bitmaps[ER] && qif->qif_queued && pktsched_verbose > 1)
qfq_dump_sched(qif, "end dequeue");
#endif /* QFQ_DEBUG */
-
- return (m);
}
/*
}
int
-qfq_enqueue(struct qfq_if *qif, struct qfq_class *cl, struct mbuf *m,
+qfq_enqueue(struct qfq_if *qif, struct qfq_class *cl, pktsched_pkt_t *pkt,
struct pf_mtag *t)
{
struct ifclassq *ifq = qif->qif_ifq;
VERIFY(cl == NULL || cl->cl_qif == qif);
if (cl == NULL) {
- cl = qfq_clh_to_clp(qif, t->pftag_qid);
+ cl = qfq_clh_to_clp(qif, 0);
if (cl == NULL) {
cl = qif->qif_default;
if (cl == NULL) {
IFCQ_CONVERT_LOCK(ifq);
- m_freem(m);
- return (ENOBUFS);
+ return (CLASSQEQ_DROP);
}
}
}
- len = m_pktlen(m);
-
- ret = qfq_addq(cl, m, t);
- if (ret != 0) {
- if (ret == CLASSQEQ_SUCCESS_FC) {
- /* packet enqueued, return advisory feedback */
- ret = EQFULL;
- } else {
- VERIFY(ret == CLASSQEQ_DROPPED ||
- ret == CLASSQEQ_DROPPED_FC ||
- ret == CLASSQEQ_DROPPED_SP);
- /* packet has been freed in qfq_addq */
- PKTCNTR_ADD(&cl->cl_dropcnt, 1, len);
- IFCQ_DROP_ADD(ifq, 1, len);
- switch (ret) {
- case CLASSQEQ_DROPPED:
- return (ENOBUFS);
- case CLASSQEQ_DROPPED_FC:
- return (EQFULL);
- case CLASSQEQ_DROPPED_SP:
- return (EQSUSPENDED);
- }
- /* NOT REACHED */
- }
+ VERIFY(pkt->pktsched_ptype == qptype(&cl->cl_q));
+ len = pktsched_get_pkt_len(pkt);
+
+ ret = qfq_addq(cl, pkt, t);
+ if ((ret != 0) && (ret != CLASSQEQ_SUCCESS_FC)) {
+ VERIFY(ret == CLASSQEQ_DROP ||
+ ret == CLASSQEQ_DROP_FC ||
+ ret == CLASSQEQ_DROP_SP);
+ PKTCNTR_ADD(&cl->cl_dropcnt, 1, len);
+ IFCQ_DROP_ADD(ifq, 1, len);
+ return (ret);
}
IFCQ_INC_LEN(ifq);
+ IFCQ_INC_BYTES(ifq, len);
#if QFQ_DEBUG
qif->qif_queued++;
pktsched_bit_set(grp->qfg_index, &qif->qif_bitmaps[s]);
if (pktsched_verbose > 2) {
- log(LOG_DEBUG, "%s: %s qid=%d enqueue m=%p state=%s 0x%x "
+ log(LOG_DEBUG, "%s: %s qid=%d enqueue m=0x%llx state=%s 0x%x "
"S=0x%llx F=0x%llx V=0x%llx\n", if_name(QFQIF_IFP(qif)),
- qfq_style(qif), cl->cl_handle, m, qfq_state2str(s),
+ qfq_style(qif), cl->cl_handle,
+ (uint64_t)VM_KERNEL_ADDRPERM(pkt->pktsched_pkt),
+ qfq_state2str(s),
qif->qif_bitmaps[s], cl->cl_S, cl->cl_F, qif->qif_V);
}
}
static inline int
-qfq_addq(struct qfq_class *cl, struct mbuf *m, struct pf_mtag *t)
+qfq_addq(struct qfq_class *cl, pktsched_pkt_t *pkt, struct pf_mtag *t)
{
struct qfq_if *qif = cl->cl_qif;
struct ifclassq *ifq = qif->qif_ifq;
IFCQ_LOCK_ASSERT_HELD(ifq);
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- return (rio_addq(cl->cl_rio, &cl->cl_q, m, t));
- else
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- return (red_addq(cl->cl_red, &cl->cl_q, m, t));
- else
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- return (blue_addq(cl->cl_blue, &cl->cl_q, m, t));
- else
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q)) {
if (cl->cl_sfb == NULL) {
struct ifnet *ifp = QFQIF_IFP(qif);
VERIFY(cl->cl_flags & QFCF_LAZY);
cl->cl_flags &= ~QFCF_LAZY;
- IFCQ_CONVERT_LOCK(ifq);
+ IFCQ_CONVERT_LOCK(ifq);
cl->cl_sfb = sfb_alloc(ifp, cl->cl_handle,
qlimit(&cl->cl_q), cl->cl_qflags);
if (cl->cl_sfb == NULL) {
}
}
if (cl->cl_sfb != NULL)
- return (sfb_addq(cl->cl_sfb, &cl->cl_q, m, t));
+ return (sfb_addq(cl->cl_sfb, &cl->cl_q, pkt, t));
} else if (qlen(&cl->cl_q) >= qlimit(&cl->cl_q)) {
IFCQ_CONVERT_LOCK(ifq);
- m_freem(m);
- return (CLASSQEQ_DROPPED);
+ return (CLASSQEQ_DROP);
}
- if (cl->cl_flags & QFCF_CLEARDSCP)
+#if PF_ECN
+ if (cl->cl_flags & QFCF_CLEARDSCP) {
+ /* not supported for non-mbuf type packets */
+ VERIFY(pkt->pktsched_ptype == QP_MBUF);
write_dsfield(m, t, 0);
+ }
+#endif /* PF_ECN */
- _addq(&cl->cl_q, m);
-
+ VERIFY(pkt->pktsched_ptype == qptype(&cl->cl_q));
+ _addq(&cl->cl_q, pkt->pktsched_pkt);
return (0);
}
-static inline struct mbuf *
-qfq_getq(struct qfq_class *cl)
+static inline void
+qfq_getq(struct qfq_class *cl, pktsched_pkt_t *pkt)
{
IFCQ_LOCK_ASSERT_HELD(cl->cl_qif->qif_ifq);
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- return (rio_getq(cl->cl_rio, &cl->cl_q));
- else
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- return (red_getq(cl->cl_red, &cl->cl_q));
- else
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- return (blue_getq(cl->cl_blue, &cl->cl_q));
- else
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
- return (sfb_getq(cl->cl_sfb, &cl->cl_q));
-
- return (_getq(&cl->cl_q));
-}
-
-static inline struct mbuf *
-qfq_pollq(struct qfq_class *cl)
-{
- IFCQ_LOCK_ASSERT_HELD(cl->cl_qif->qif_ifq);
+ return (sfb_getq(cl->cl_sfb, &cl->cl_q, pkt));
- return (qhead(&cl->cl_q));
+ return (pktsched_pkt_encap(pkt, qptype(&cl->cl_q), _getq(&cl->cl_q)));
}
static void
if ((qlen = qlen(&cl->cl_q)) == 0)
goto done;
- /* become regular mutex before freeing mbufs */
IFCQ_CONVERT_LOCK(ifq);
-
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- rio_purgeq(cl->cl_rio, &cl->cl_q, flow, &cnt, &len);
- else
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- red_purgeq(cl->cl_red, &cl->cl_q, flow, &cnt, &len);
- else
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- blue_purgeq(cl->cl_blue, &cl->cl_q, flow, &cnt, &len);
- else
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
sfb_purgeq(cl->cl_sfb, &cl->cl_q, flow, &cnt, &len);
else
ifclassq_ev2str(ev));
}
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- return (rio_updateq(cl->cl_rio, ev));
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- return (red_updateq(cl->cl_red, ev));
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- return (blue_updateq(cl->cl_blue, ev));
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
return (sfb_updateq(cl->cl_sfb, ev));
}
sp->qtype = qtype(&cl->cl_q);
sp->qstate = qstate(&cl->cl_q);
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- red_getstats(cl->cl_red, &sp->red[0]);
-#endif /* CLASSQ_RED */
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- rio_getstats(cl->cl_rio, &sp->red[0]);
-#endif /* CLASSQ_RIO */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- blue_getstats(cl->cl_blue, &sp->blue);
-#endif /* CLASSQ_BLUE */
+
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
sfb_getstats(cl->cl_sfb, &sp->sfb);
return (0);
}
+static int
+qfq_stat_sc(struct qfq_if *qif, cqrq_stat_sc_t *sr)
+{
+ struct ifclassq *ifq = qif->qif_ifq;
+ struct qfq_class *cl;
+ u_int32_t i;
+
+ IFCQ_LOCK_ASSERT_HELD(ifq);
+
+ VERIFY(sr->sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(sr->sc));
+
+ i = MBUF_SCIDX(sr->sc);
+ VERIFY(i < IFCQ_SC_MAX);
+
+ cl = ifq->ifcq_disc_slots[i].cl;
+ sr->packets = qlen(&cl->cl_q);
+ sr->bytes = qsize(&cl->cl_q);
+
+ return (0);
+}
+
/* convert a class handle to the corresponding class pointer */
static inline struct qfq_class *
qfq_clh_to_clp(struct qfq_if *qif, u_int32_t chandle)
static const char *
qfq_style(struct qfq_if *qif)
{
- return ((qif->qif_flags & QFQIFF_ALTQ) ? "ALTQ_QFQ" : "QFQ");
+#pragma unused(qif)
+ return ("QFQ");
}
/*
for (j = 0; j < qif->qif_maxslots; j++) {
if (g->qfg_slots[j]) {
- log(LOG_DEBUG, "%s: %s bucket %d %p "
+ log(LOG_DEBUG, "%s: %s bucket %d 0x%llx "
"qid %d\n", if_name(QFQIF_IFP(qif)),
- qfq_style(qif), j, g->qfg_slots[j],
+ qfq_style(qif), j,
+ (uint64_t)VM_KERNEL_ADDRPERM(
+ g->qfg_slots[j]),
g->qfg_slots[j]->cl_handle);
}
}
* (*ifcq_enqueue) in struct ifclassq.
*/
static int
-qfq_enqueue_ifclassq(struct ifclassq *ifq, struct mbuf *m)
+qfq_enqueue_ifclassq(struct ifclassq *ifq, void *p, classq_pkt_type_t ptype,
+ boolean_t *pdrop)
{
- u_int32_t i;
+ u_int32_t i = 0;
+ int ret;
+ pktsched_pkt_t pkt;
+ struct pf_mtag *t = NULL;
IFCQ_LOCK_ASSERT_HELD(ifq);
- if (!(m->m_flags & M_PKTHDR)) {
- /* should not happen */
- log(LOG_ERR, "%s: packet does not have pkthdr\n",
- if_name(ifq->ifcq_ifp));
- IFCQ_CONVERT_LOCK(ifq);
- m_freem(m);
- return (ENOBUFS);
+ switch (ptype) {
+ case QP_MBUF: {
+ struct mbuf *m = p;
+ if (!(m->m_flags & M_PKTHDR)) {
+ /* should not happen */
+ log(LOG_ERR, "%s: packet does not have pkthdr\n",
+ if_name(ifq->ifcq_ifp));
+ IFCQ_CONVERT_LOCK(ifq);
+ m_freem(m);
+ *pdrop = TRUE;
+ return (ENOBUFS);
+ }
+ i = MBUF_SCIDX(mbuf_get_service_class(m));
+ t = m_pftag(m);
+ break;
+ }
+
+
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
}
- i = MBUF_SCIDX(mbuf_get_service_class(m));
VERIFY((u_int32_t)i < IFCQ_SC_MAX);
- return (qfq_enqueue(ifq->ifcq_disc,
- ifq->ifcq_disc_slots[i].cl, m, m_pftag(m)));
+ pktsched_pkt_encap(&pkt, ptype, p);
+
+ ret = qfq_enqueue(ifq->ifcq_disc,
+ ifq->ifcq_disc_slots[i].cl, &pkt, t);
+
+ if ((ret != 0) && (ret != CLASSQEQ_SUCCESS_FC)) {
+ pktsched_free_pkt(&pkt);
+ *pdrop = TRUE;
+ } else {
+ *pdrop = FALSE;
+ }
+
+ switch (ret) {
+ case CLASSQEQ_DROP:
+ ret = ENOBUFS;
+ break;
+ case CLASSQEQ_DROP_FC:
+ ret = EQFULL;
+ break;
+ case CLASSQEQ_DROP_SP:
+ ret = EQSUSPENDED;
+ break;
+ case CLASSQEQ_SUCCESS_FC:
+ ret = EQFULL;
+ break;
+ case CLASSQEQ_SUCCESS:
+ ret = 0;
+ break;
+ default:
+ VERIFY(0);
+ }
+ return (ret);
}
/*
* CLASSQDQ_REMOVE must return the same packet if called immediately
* after CLASSQDQ_POLL.
*/
-static struct mbuf *
-qfq_dequeue_ifclassq(struct ifclassq *ifq, cqdq_op_t op)
+static void *
+qfq_dequeue_ifclassq(struct ifclassq *ifq, classq_pkt_type_t *ptype)
{
- return (qfq_dequeue(ifq->ifcq_disc, op));
+ pktsched_pkt_t pkt;
+ bzero(&pkt, sizeof (pkt));
+ qfq_dequeue(ifq->ifcq_disc, &pkt);
+ *ptype = pkt.pktsched_ptype;
+ return (pkt.pktsched_pkt);
}
static int
case CLASSQRQ_THROTTLE:
err = qfq_throttle(qif, (cqrq_throttle_t *)arg);
break;
+ case CLASSQRQ_STAT_SC:
+ err = qfq_stat_sc(qif, (cqrq_stat_sc_t *)arg);
+ break;
}
return (err);
}
int
-qfq_setup_ifclassq(struct ifclassq *ifq, u_int32_t flags)
+qfq_setup_ifclassq(struct ifclassq *ifq, u_int32_t flags,
+ classq_pkt_type_t ptype)
{
struct ifnet *ifp = ifq->ifcq_ifp;
struct qfq_class *cl0, *cl1, *cl2, *cl3, *cl4;
VERIFY(ifq->ifcq_disc == NULL);
VERIFY(ifq->ifcq_type == PKTSCHEDT_NONE);
- if (flags & PKTSCHEDF_QALG_RED)
- qflags |= QFCF_RED;
- if (flags & PKTSCHEDF_QALG_RIO)
- qflags |= QFCF_RIO;
- if (flags & PKTSCHEDF_QALG_BLUE)
- qflags |= QFCF_BLUE;
if (flags & PKTSCHEDF_QALG_SFB)
qflags |= QFCF_SFB;
if (flags & PKTSCHEDF_QALG_ECN)
qflags |= QFCF_ECN;
if (flags & PKTSCHEDF_QALG_FLOWCTL)
qflags |= QFCF_FLOWCTL;
+ if (flags & PKTSCHEDF_QALG_DELAYBASED)
+ qflags |= QFCF_DELAYBASED;
- qif = qfq_alloc(ifp, M_WAITOK, FALSE);
+ qif = qfq_alloc(ifp, M_WAITOK);
if (qif == NULL)
return (ENOMEM);
maxlen = if_sndq_maxlen;
if ((err = qfq_add_queue(qif, maxlen, 300, 1200,
- qflags | QFCF_LAZY, SCIDX_BK_SYS, &cl0)) != 0)
+ qflags | QFCF_LAZY, SCIDX_BK_SYS, &cl0, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 600, 1400,
- qflags | QFCF_LAZY, SCIDX_BK, &cl1)) != 0)
+ qflags | QFCF_LAZY, SCIDX_BK, &cl1, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 2400, 600,
- qflags | QFCF_DEFAULTCLASS, SCIDX_BE, &cl2)) != 0)
+ qflags | QFCF_DEFAULTCLASS, SCIDX_BE, &cl2, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 2700, 600,
- qflags | QFCF_LAZY, SCIDX_RD, &cl3)) != 0)
+ qflags | QFCF_LAZY, SCIDX_RD, &cl3, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 3000, 400,
- qflags | QFCF_LAZY, SCIDX_OAM, &cl4)) != 0)
+ qflags | QFCF_LAZY, SCIDX_OAM, &cl4, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 8000, 1000,
- qflags | QFCF_LAZY, SCIDX_AV, &cl5)) != 0)
+ qflags | QFCF_LAZY, SCIDX_AV, &cl5, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 15000, 1200,
- qflags | QFCF_LAZY, SCIDX_RV, &cl6)) != 0)
+ qflags | QFCF_LAZY, SCIDX_RV, &cl6, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 20000, 1400,
- qflags | QFCF_LAZY, SCIDX_VI, &cl7)) != 0)
+ qflags | QFCF_LAZY, SCIDX_VI, &cl7, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 23000, 200,
- qflags | QFCF_LAZY, SCIDX_VO, &cl8)) != 0)
+ qflags | QFCF_LAZY, SCIDX_VO, &cl8, ptype)) != 0)
goto cleanup;
if ((err = qfq_add_queue(qif, maxlen, 25000, 200,
- qflags, SCIDX_CTL, &cl9)) != 0)
+ qflags, SCIDX_CTL, &cl9, ptype)) != 0)
goto cleanup;
err = ifclassq_attach(ifq, PKTSCHEDT_QFQ, qif,
qfq_enqueue_ifclassq, qfq_dequeue_ifclassq, NULL,
- qfq_request_ifclassq);
+ NULL, NULL, qfq_request_ifclassq);
/* cache these for faster lookup */
if (err == 0) {
{
struct ifclassq *ifq = qif->qif_ifq;
struct qfq_class *cl;
- int err;
+ int err = 0;
IFCQ_LOCK_ASSERT_HELD(ifq);
- VERIFY(!(qif->qif_flags & QFQIFF_ALTQ));
if (!tr->set) {
tr->level = qif->qif_throttle;
{
struct ifclassq *ifq = qif->qif_ifq;
int err = 0;
-
+#if !MACH_ASSERT
+#pragma unused(ifq)
+#endif
IFCQ_LOCK_ASSERT_HELD(ifq);
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- err = rio_suspendq(cl->cl_rio, &cl->cl_q, FALSE);
- else
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- err = red_suspendq(cl->cl_red, &cl->cl_q, FALSE);
- else
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- err = blue_suspendq(cl->cl_blue, &cl->cl_q, FALSE);
- else
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL)
err = sfb_suspendq(cl->cl_sfb, &cl->cl_q, FALSE);
{
struct ifclassq *ifq = qif->qif_ifq;
int err = 0;
-
+#if !MACH_ASSERT
+#pragma unused(ifq)
+#endif
IFCQ_LOCK_ASSERT_HELD(ifq);
-#if CLASSQ_RIO
- if (q_is_rio(&cl->cl_q))
- err = rio_suspendq(cl->cl_rio, &cl->cl_q, TRUE);
- else
-#endif /* CLASSQ_RIO */
-#if CLASSQ_RED
- if (q_is_red(&cl->cl_q))
- err = red_suspendq(cl->cl_red, &cl->cl_q, TRUE);
- else
-#endif /* CLASSQ_RED */
-#if CLASSQ_BLUE
- if (q_is_blue(&cl->cl_q))
- err = blue_suspendq(cl->cl_blue, &cl->cl_q, TRUE);
- else
-#endif /* CLASSQ_BLUE */
if (q_is_sfb(&cl->cl_q)) {
if (cl->cl_sfb != NULL) {
err = sfb_suspendq(cl->cl_sfb, &cl->cl_q, TRUE);